Cloud Images Beyond AWS
What exists today for non-AWS targets, what you can build yourself, and how far official support extends.
Current Reality
There are two distribution paths:
- Official automated pipeline: AWS AMI.
shani-install-media/packer/contains a working Packer template (amazon-ebssurrogatebuilder) that turns a.zstbase image into a bootable AMI — profiles, variables, and the GitHub Actions OIDC workflow are documented in OEM & Fleet Deployment. This is the only cloud target with an end-to-end maintained path.
- Raw artifacts for every profile and release. The image build publishes each profile's artifacts publicly to Cloudflare R2 and SourceForge mirrors:
| Artifact | Contents |
|---|---|
shanios-<profile>-<version>.zst | Compressed Btrfs send-stream of the full OS image |
shanios-<profile>-<version>.zst.sha256 | Checksum |
shanios-<profile>-<version>.zst.asc | Detached GPG signature |
The .zst send-stream is the same artifact the AWS Packer build consumes — anything it can do with it, you can replicate on another platform.
Verify Artifacts Before Use
sha256sum -c shanios-server-2026.08.zst.sha256
# One-time: import and trust the signing key
gpg --keyserver keys.openpgp.org --recv-keys 7B927BFFD4A9EAAA8B666B77DE217F3DA8014792
gpg --fingerprint 7B927BFFD4A9EAAA8B666B77DE217F3DA8014792 # confirm before trusting
gpg --verify shanios-server-2026.08.zst.asc shanios-server-2026.08.zst
A failed checksum or signature means do not use the artifact — fetch again from another mirror (R2 primary, SourceForge fallback) and re-verify.
Generic KVM / qcow2 (Advanced, Unofficial)
This is not a supported or documented product surface. The steps below describe the concept using standard tools; they assume familiarity with Btrfs, UEFI booting, and cloud-init. Read upstream's build.sh test bootstrap first — that local test loop performs exactly this class of operation (loop-mount, receive stream, chroot configure) and is the best available prior art.
Conceptual flow:
# 1. Create a blank disk sized for the profile (server needs ~28 GB minimum)
truncate -s 30G shanios-server.raw
# 2. Format Btrfs and receive the verified send-stream into it,
# following the subvolume layout the images expect (@blue/@green/@data)
mkfs.btrfs shanios-server.raw
mount -o loop shanios-server.raw /mnt
zstd -dc shanios-server-2026.08.zst | btrfs receive /mnt
# 3. Bootloader setup follows the image conventions: UKIs generated by
# gen-efi and systemd-boot entries on an ESP, exactly as physical
# installs produce them. Replicating this outside the Packer pipeline
# means reproducing what the pipeline's configuration stage does.
# Consult the upstream build scripts and the Arch Wiki pages on
# systemd-boot and unified kernel images — this is the step that
# requires real experience to get right.
# 4. Swap the cloud-init datasource: the shipped config targets AWS
# (IMDSv2 strict, EC2 metadata). Replace it inside the received rootfs.
rm /mnt/etc/cloud/cloud.cfg.d/10-shanios-aws.cfg
cat > /mnt/etc/cloud/cloud.cfg.d/10-myorg-generic.cfg <<'EOF'
datasource_list: [ NoCloud ]
EOF
umount /mnt
Then convert and attach as a VM disk:
qemu-img convert -f raw -O qcow2 shanios-server.raw shanios-server.qcow2
virt-install --name shanios-01 --memory 4096 --vcpus 2 \
--disk path=shanios-server.qcow2 \
--boot uefi --os-variant archlinux --import --no-console
UEFI firmware (OVMF) is required — Secure Boot with MOK-enrolled UKIs is part of the boot chain. If your hypervisor cannot enforce Secure Boot, the machine still boots via the MOK-signed UKI path but report boot state accordingly in your own compliance evidence (see Compliance & Benchmarks).
Azure / GCP
No official templates exist. The practical approach: copy packer/shanios-ami.pkr.hcl, swap the amazon-ebssurrogate builder block for azure-arm or googlecompute, and keep the three provisioner scripts (00-bootstrap-shanios.sh, 01-configure-aws.sh → rename/adjust its cloud-init bits, 02-verify.sh) operating on the attached volume unchanged where possible.
Variable differences from the AWS template:
| Variable | AWS template | Azure/GCP adaptation |
|---|---|---|
r2_base_url / s3_base_url | Base .zst source for the build | Unchanged — still pulled from R2/SourceForge |
gpg_public_key | Optional org signing key baked at build time | Unchanged |
shanios_profile | gnome/plasma/cosmic (server default) | Unchanged |
| Credentials | AWS OIDC role, no long-lived keys | Azure: OIDC/service principal; GCP: service account impersonation |
| Added | — | azure_subscription_id + resource group / gcp_project_id + zone |
Budget time for the platform-specific parts of 01-configure-aws.sh (fstab device naming differs; serial console targets differ).
Proxmox / OpenStack
Both consume the output of either path above directly:
| Platform | Import | cloud-init datasource |
|---|---|---|
| Proxmox VE | qm importdisk with the qcow2/raw; attach as SCSI disk | NoCloud (Proxmox cloud-init drive) |
| OpenStack | Upload to Glance, boot from image | OpenStack datasource (metadata service) |
| Plain libvirt/KVM | Attach qcow2 | NoCloud seed ISO |
The server profile is built for exactly this usage: headless, systemd-networkd + cloud-init networking, serial console on ttyS0, sshd/firewalld/fail2ban/auditd enabled by default. After swapping the AWS datasource config (step 4 above) for the platform's datasource, first boot picks up hostname, SSH keys, and network from the metadata provider as usual.
Support Posture
- Officially supported: AWS only. The AMI pipeline is tested end-to-end, including the CI build workflow.
- Everything else: community/DIY. The raw artifacts are public and verifiable precisely so this remains possible, but nobody has validated Azure, GCP, Proxmox, or bare-KVM builds against release QA.
- Issues and improvements for other platforms are welcome upstream at the shani-install-media repository. For organisation-scale needs, contact the project.
See Also
- OEM & Fleet Deployment — Packer AMI pipeline, profiles, signing
- Kubernetes — server-profile workloads
- Virtual Networking — bridges, libvirt, VM networking
- Blog: Kubernetes on Shani OS