Debian live-build configuration and GitHub Actions ISO build pipeline for Zurvan Linux.
The full spec-compliant desktop baseline. Builds Debian Stable (pinned to the
trixie codename) amd64 with the complete KDE Plasma stack, multimedia codecs,
hardware firmware, Flatpak integration, Calamares, and Persian-first localization
baked in.
- Base: Debian Stable (pinned to the
trixiecodename),amd64+arm64;main+contrib+non-free+non-free-firmware. - Desktop: KDE Plasma (latest stable), Wayland session by default (X11 fallback), SDDM, Plymouth.
- Fonts/localization:
fonts-vazirmatnas system default via/etc/fonts/local.conf;fa_IR.UTF-8locale (RTL mirroring + Jalali calendar); ISIRI 9147irkeyboard with ZWNJ onShift+Space;Asia/Tehrantimezone. - Firmware:
firmware-linux{,-nonfree},firmware-iwlwifi/-realtek/-atheros,nvidia-detect. - Installer: Calamares +
calamares-settings-debian(branding customization is Phase 3).
M1.1a (the minimal CLI proof build that validated the pipeline + loop-device behavior on hosted runners) is superseded by this milestone. The build pipeline itself is unchanged and proven.
| Manifest name | In ISO | Reason |
|---|---|---|
plasma-workspace-wayland |
dropped (use plasma-workspace) |
Folded into plasma-workspace in Plasma 6 (verified via madison). |
khotkeys |
dropped | Removed in Plasma 6; shortcuts now use KDE's built-in global-accel. |
spectacle |
kde-spectacle |
Renamed in current Debian Stable. |
zurvan-dns-bypass |
commented | Custom package, built in Phase 2 (M2.2), published to the Zurvan APT repo. |
fonts-vazirmatn "Vazirmatn UI FD" monospace |
not set | The Debian package ships only the proportional Vazirmatn family; the Farsi-Digits monospace variant is bundled from Google Fonts in Phase 2 (branding-assets, M2.1). Flagged spec divergence — local.conf leaves monospace at the system default meanwhile. |
The CI builds both amd64 and arm64 ISOs in a single matrix job:
| Arch | Runner | Container | Boot mode |
|---|---|---|---|
amd64 |
ubuntu-latest |
debian:trixie (pinned) |
BIOS (isolinux + grub-pc) + UEFI (grub-efi-amd64) |
arm64 |
ubuntu-24.04-arm |
debian:trixie (arm64 manifest) |
UEFI only (grub-efi-arm64) |
The active arch is controlled by ZURVAN_ARCH in the workflow matrix.
auto/config passes it to lb config --architecture ${ARCH}.
arm64 firmware support is deferred to a future release. The
linux-image-arm64kernel is included, but board-specific firmware (RPi, RK35xx, etc.) would bloat the ISO for all users and will be added once the target boards are locked in.
build.env # Debian infra + pinned images (NOT Zurvan identity)
zurvan-config/ # single source of truth for Zurvan identity/localization/branding
localization # timezone, locale, keyboard, font
live-session # live user credentials, SDDM theme
iso-metadata # ISO application/publisher/volume labels
flathub-apps # default Flatpak apps
repo-urls # APT repo URL, website, download origin
branding # theme colors, logo path
repo-metadata # APT repo key ID, components
versions/akaran/dist-version # version, codename
auto/
config # -> lb config (sources build.env, arch-conditional)
config/
archives/ # Zurvan custom APT repo config (commented until Phase 2)
package-lists/ # one file per package-manifest.md section (§1–§15)
# kernel/bootloaders lists are generated by gen-arch-packages.sh
includes.chroot/ # files overlaid into the chroot at /
etc/... # fonts, keyboard, locale, timezone, SDDM config
usr/local/bin/zurvan-flathub-install.sh # first-boot Flatpak installer
etc/systemd/system/flathub-install.service # oneshot service for above
hooks/normal/ # chroot-phase hooks (locale, guest agents, GRUB, etc.)
hooks/binary/ # binary-phase hooks (GRUB cfg fixes)
scripts/
gen-arch-packages.sh # generates kernel + bootloader lists per arch
build-iso-multipass.sh # local Multipass-based build (streams local files)
qemu-arm64.sh # QEMU boot test for arm64 ISO
packages/
zurvan-base-files/ # custom identity .deb (built in CI)
.github/workflows/
build-iso.yml # privileged debian:trixie (pinned) container build + release
lint.yml # shellcheck + yamllint + bash -n
Makefile # config / build / clean / test / lint / qemu targets
SECURITY.md # default credentials and SSH settings documentation
.gitignore excludes live-build generated control files, build stages
(chroot/, binary/, .build/), and generated arch-conditional package lists;
only the authored config is committed.
- Host:
ubuntu-latest(amd64) orubuntu-24.04-arm(arm64) GitHub-hosted runners. - Container:
debian:trixie(pinned by digest for both amd64 and arm64),--privilegedso thelb_binarystage can mount the squashfs vialosetup./dev/loop-control+/dev/loopNare provisioned if missing. - Timeout: 90 minutes for amd64, 120 minutes for arm64 (a full Plasma squashfs is materially larger/slower than the M1.1a minimal build).
- Outputs:
live-image-<arch>.hybrid.iso+SHA256SUMSare uploaded as arch-suffixed workflow artifacts (zurvan-live-iso-amd64,zurvan-live-iso-arm64) on every run. If arelease_taginput (or a pushedv*.*.*-pre.*tag) is supplied, thepublish-releasefan-in job aggregates both arch artifacts and creates a single GitHub pre-release.
A full KDE ISO is ~2.3 GB, above GitHub Releases' 2 GB per-asset cap, so the
ISO binary is published to a Cloudflare R2 bucket (zero-egress object storage)
served at https://download.zurvanlinux.org/iso/zurvan-<version>-<arch>.iso
(the subdomain is bound to the bucket as a Cloudflare custom domain). GitHub
Releases keeps the release notes + SHA256SUMS and links to the R2 URL. The
upload uses rclone (R2's S3-compatible API), env-configured from secrets.
Maintainer prerequisites (block the first release-to-R2; see the project plan):
- Create the R2 bucket (e.g.
zurvan-iso) and enable public access. - Bind
download.zurvanlinux.orgto the bucket as a Cloudflare custom domain. - Create an R2 API token (Object Read & Write); note the Access Key ID, Secret,
and S3 endpoint (
https://<accountid>.r2.cloudflarestorage.com). - Add
iso-builderActions secrets:R2_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEY,R2_ENDPOINT,R2_BUCKET.
Until these exist, a tagged build creates the GitHub Release + artifact but the R2
upload step fails with a clear ::error:: (artifact-only, no-tag runs are unaffected).
workflow_dispatch— manual, optionalrelease_taginput.pushto tags matchingv*.*.*-pre.*— automatic pre-release + R2 publish.
From the Actions tab → Build ISO (live-build) → Run workflow, then download the artifact.
make build-arm64This streams the local working tree into a Multipass VM and builds inside a native Debian Trixie container. No need to push first — local edits take effect immediately.
make config ARCH=arm64 # or ARCH=amd64
make build# amd64 QEMU/KVM:
qemu-system-x86_64 -m 4G -cdrom live-image-amd64.hybrid.iso -boot d
# amd64 UEFI:
qemu-system-x86_64 -m 4G -bios /usr/share/OVMF/OVMF_CODE.fd \
-cdrom live-image-amd64.hybrid.iso -boot d
# arm64 QEMU (UEFI only — AAVMF is the UEFI firmware for ARM):
qemu-system-aarch64 -m 4G -M virt -cpu cortex-a72 -bios /usr/share/qemu-efi-aarch64/QEMU_EFI.fd \
-drive id=hd,file=live-image-arm64.hybrid.iso,if=none,format=raw \
-device virtio-blk-device,drive=hd -boot dIf the arm64 image fails to boot, verify the ISO structure with
xorriso -indev live-image-arm64.hybrid.iso -report_el_torito as_mkisofs.
Builds must pass in both QEMU/KVM and VirtualBox (BIOS + UEFI): reaches the
Plasma desktop, Vazirmatn renders Persian, us/ir toggle + ZWNJ work,
Asia/Tehran auto-applied, Wi-Fi firmware loads, Flathub visible in Discover,
Calamares launches, apt update is clean. Tag v0.2.0-pre once verified.
Debian infrastructure values (codename, mirrors, images, archive areas)
live in build.env. Zurvan identity values (ISO labels, locale, keyboard,
SDDM theme) live in zurvan-config — the single source of truth for
Zurvan-specific configuration.
- Update
DEBIAN_CODENAMEinbuild.envto the new codename. - Resolve new pinned image digests and update
DEBIAN_IMAGE_AMD64/DEBIAN_IMAGE_ARM64in bothbuild.envand theenv:blocks in.github/workflows/build-iso.yml(CI cannot source shell files before the container starts, so the image values are mirrored there). - Update
ZURVAN_CONFIG_REFinbuild.envand the CIenv:blocks to the newZurvanLinux/zurvan-configcommit SHA. - Re-verify every package name in
config/package-lists/against the new suite via Debian madison — package names drift across Debian + Plasma majors (see the substitution notes in05-plasma.list.chroot). - Update the "(pinned to the
<codename>codename)" note in this README. - Trigger
build-iso.yml, boot-test in QEMU/KVM + VirtualBox (BIOS + UEFI),
- Make changes in
ZurvanLinux/zurvan-config(or usescripts/fetch-zurvan-config.sh). The config files control ISO metadata, locale/keyboard/language defaults, SDDM theme, and live user credentials. - Commit and push the new
zurvan-configcommit SHA. - Update
ZURVAN_CONFIG_REFinbuild.envand the CIenv:blocks.
| Setting | Source |
|---|---|
| Debian codename, mirrors, images | build.env |
| ISO_APPLICATION, ISO_PUBLISHER, ISO_VOLUME | zurvan-config/iso-metadata |
| Keyboard, locale, timezone, SDDM, password | zurvan-config/localization + zurvan-config/live-session |
| Live-build options (binary images, APT recommends…) | build.env |
| ISO_PREPARER (pipeline identity) | build.env |
zurvan-dns-bypass and the Zurvan branding package (Phase 2), the welcome app
and Calamares branding (Phase 3), download.zurvanlinux.org ISO hosting (Phase 5).
See the project plan and the spec docs in
ZurvanLinux/ZurvanLinux.