Skip to content

feat: release ignity as deb, rpm and apk packages - #35

Merged
amannocci merged 3 commits into
mainfrom
feat/linux-packages
Oct 22, 2026
Merged

amannocci merged 3 commits into
mainfrom
feat/linux-packages

Conversation

@amannocci

@amannocci amannocci commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

What is the change being made?

Ignity is released as Linux packages (.deb, .rpm, .apk) for amd64 and arm64, published on GitHub Releases. The layout follows techcode-io/terranova.

  • distributions/build/: builds execline, s6 and s6-portable-utils statically (musl) in an Alpine container and bundles them with src/ (without install-ignity.sh). The versions are still read from install-ignity.sh, so poe project:upgrade keeps bumping both install paths.
  • distributions/packages/: nfpm configs per arch, plus postinstall.sh/preremove.sh. Assets are named ignity-<version>-linux-<amd64|arm64>.<deb|rpm|apk>, so a Dockerfile can pick one from TARGETARCH.
  • scripts/binds/ + scripts/tasks/: new poe tasks build, package:{deb,rpm,apk}, release:pre, release, release:post. The version is now 0.1.0-dev.
  • Workflows:
    • ci.yml (now reusable): builds packages per arch, attests them, then runs the full suite from the packages on debian, alpine and fedora.
    • pre-release.yml / release.yml: the terranova release flow (bump PR → tag + GitHub release → next iteration PR).

Binaries out of the root filesystem, for the packages and the source install alike:

  • execline, s6 and s6-portable-utils live in /usr/lib/ignity/{bin,libexec}, built with --enable-absolute-paths. Nothing goes into /bin or /usr/bin anymore.
  • /init puts /usr/lib/ignity/bin first in PATH through /usr/lib/ignity/libexec/with-ignity-path. The entry points that can run outside /init (preboot, fix-perms, gen-accounts, load-envfile, with-retries) start with the same helper. The old PATH=/usr/bin:/bin reset came from the previous layout and is gone.
  • Ignity's own scripts use #!/usr/lib/ignity/bin/execlineb. /bin/execlineb is a compat link for user scripts, created only when no other execline provides one, and removed on uninstall if it's ours.
  • As a result the packages declare no Conflicts/Provides. The distribution's execline/s6 can be installed alongside, which was checked on Alpine. bash's cd/umask/wait on rpm distributions no longer matter, so stage3 keeps plain cd / and wait { }.

Other changes:

  • The apk depends on GNU findutils and grep: fix-perms uses find -gid/-uid and gen-accounts uses grep -z, which busybox lacks.
  • The default 00-container-discover init script is dropped.

Why is the change being made?

install-ignity.sh only works on Debian/Ubuntu and compiles the skarnet stack in every image build. It needs git, build-essential and network access to GitHub. Packages install in one layer on Debian/Ubuntu, Alpine and Fedora/RHEL/UBI, with nothing to compile and nothing written over the distribution's files.

How has this been tested?

Locally on arm64 (podman), with /usr/lib/ignity:

  • uv run poe test (source install) and IGNITY_INSTALL=package DOCKER_BASE_IMAGE=<base> uv run poe test on debian:bookworm-slim, alpine:3 and fedora:latest: 69 passed each. This includes two new tests: binaries resolve from /usr/lib/ignity (wait too), and the compat link is present.
  • The entry points were also run by hand outside /init, with the image's PATH and with PATH unset.
  • deb/rpm/apk install, coexistence with Alpine's execline/s6, and a clean uninstall (link and /usr/lib/ignity removed).
  • Not run after the 00-container-discover removal.

Test changes that were not caused by the packages:

  • The "no-start service" tests sleep 1s before exiting. The CMD exited before the service printed, and Fedora's slower sh lost that race every time.
  • The owner checks accept busybox's ls column padding.

ubuntu:24.04 is not in the CI matrix: its image already has a uid/gid 1000 user, which the tests map.

Not run yet: the CI workflows themselves, amd64, and the release flow. release.yml uses techcode-io/github-actions/setup-github-bot, so this repo needs the same access to it as terranova.

How has this been documented?

  • README:
    • install from a package (Debian/Ubuntu, Fedora/RHEL/UBI, Alpine);
    • "Where ignity installs its binaries", including ENV PATH for exec sessions and probes;
    • how to build and release packages.
  • .claude/CLAUDE.md updated.

Related Issues

Build static (musl) execline, s6 and s6-portable-utils in a container and
bundle them with ignity into deb, rpm and apk packages for amd64 and
arm64, published on GitHub Releases. Same layout as techcode-io/terranova.

- distributions: build script, Containerfile and nfpm configs
- scripts: binds (container, nfpm, git, gh) and tasks (build, package,
  release, project); poe build, package:{deb,rpm,apk}, release:{pre,post}
- stage3: execline-cd and /usr/libexec/ignity/wait, as bash owns cd,
  umask and wait on rpm distributions; install-ignity.sh links the wait
- packages: GNU findutils and grep on alpine (fix-perms, gen-accounts)
- tests: IGNITY_INSTALL=package runs the suite against the package,
  portable owner matching, no-start services get time to print
- ci: package per arch, attest, run the suite from the packages on
  debian, alpine and fedora; pre-release and release workflows
- docs: install from a package, build and release
@amannocci amannocci self-assigned this Oct 21, 2026
Keep execline, s6 and s6-portable-utils out of the root filesystem, for
both the packages and the source install: nothing conflicts with the
distribution anymore, its own execline/s6 can be installed alongside.

- build with --bindir/--libexecdir under /usr/lib/ignity and
  --enable-absolute-paths
- /init and the entry points that can run outside it put
  /usr/lib/ignity/bin first in PATH (with-ignity-path); the PATH reset
  of fix-perms, gen-accounts and load-envfile is gone
- ignity scripts use #!/usr/lib/ignity/bin/execlineb; /bin/execlineb is
  a compat link for user scripts, created only when absent
- packages: no conflicts/provides, no rpm special case; stage3 back to
  plain cd and wait
- drop the default 00-container-discover init script
- tests: binaries resolved from /usr/lib/ignity, compat link present
- docs: where ignity installs its binaries, ENV PATH for exec sessions
Git doesn't keep empty directories: with 00-container-discover removed,
nothing under src/etc/ignity is tracked, so a fresh checkout installed
from source has no /etc/ignity. The packages already create them.
@amannocci
amannocci merged commit 88ddba9 into main Oct 22, 2026
9 checks passed
@amannocci
amannocci deleted the feat/linux-packages branch October 23, 2026 10:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant