Repositories, Mirrors & Self-Hosting
InterGenOS installs software from signed binary packages. This page explains how
the package repository is structured, how the client (pkm) trusts it, how the
official mirror is published, and how to host your own.
Every trust decision in the repository chain is reproducible by hand, with no opaque steps. The goal is a machine you understand, can modify, and can trust.
For how pkm installs and verifies packages once they reach your disk, see
Package Management. For the build pipeline that produces
packages, see Building from Source.
What a repository is
A package archive is a single file with the extension .igos.tar.gz. Each archive
carries its file list and per-file SHA-256 hashes inside its manifest. A repository
is a directory of these archives plus a single index that names every archive and
records its SHA-256.
The index file is InterGenOS.db (gzipped JSON, the format pkm/repo.py parses).
It is generated by pkm.repo.generate_index() over an archive directory for a given
architecture (x86_64). Alongside it sits InterGenOS.db.sig, a detached GPG
signature over the index.
The packages themselves are organized into six build tiers — toolchain, core,
base, desktop, extra, and ai. As of mid-2026 a full set is roughly 857
packages across those tiers; derive the live count from the index rather than
trusting a fixed number, since tier contents drift between builds.
The trust model
The integrity boundary is the GPG signature on InterGenOS.db, not TLS. TLS protects
the transport, but trust in what you downloaded rests entirely on the signature and
the per-package hashes it commits to.
The chain works in two layers:
-
The signature on the index.
InterGenOS.db.sigis verified against a trusted public key shipped on the system at/etc/pkm/trusted.gpg. The index is signed by a release subkey held on a hardware token; that subkey is certified by an offline master key that never touches the mirror host. The master public key is published so anyone can verify the chain end to end. -
The hash on each package. Once the index is trusted, every package install verifies the archive’s SHA-256 against the entry in that index. A tampered archive fails this check even if it was served over a valid TLS connection.
This means a compromised mirror cannot hand you a modified package: it would have to forge a signature for a key it does not hold. The signing keys live on hardware tokens, and the master is kept offline.
Verify the chain by hand
Nothing about the trust chain is hidden. You can reproduce the verification the client performs with standard tools:
curl -O https://repo.intergenos.org/x86_64/current/InterGenOS.db
curl -O https://repo.intergenos.org/x86_64/current/InterGenOS.db.sig
gpg --verify InterGenOS.db.sig InterGenOS.db # signed by a release subkey, certified by the master
# then check any archive against its SHA-256 entry in the index
sha256sum <package>.igos.tar.gz
Using the official mirror
The official binary mirror is repo.intergenos.org. Client configuration lives in
/etc/pkm/repos.conf. The two everyday commands are:
pkm sync # fetch the index, GPG-verify InterGenOS.db.sig, cache per-package metadata
pkm install <pkg> # download an archive, verify its SHA-256 against the trusted index
pkm sync fetches InterGenOS.db, verifies its signature against
/etc/pkm/trusted.gpg, and refreshes the local cache of available packages. From
that point an install trusts the per-package hashes the verified index commits to.
Source archives
The mirror also serves the upstream source tarballs used to build each package, under
https://repo.intergenos.org/sources/. Because InterGenOS is built from source, the
source set is published alongside the binaries so the build is reproducible by anyone.
See Reproducibility for what that buys you.
How the official mirror is published
The repository is published by a signed-publish process. The canonical script is
scripts/publish-repo.sh, which is also wired into the build pipeline as an optional
publish phase (the build itself runs 20 phases, from validation through ISO; publish
is the optional step after). The flow is:
- Pre-checks. The chosen signing subkey must be present in the local keyring, and the archive directory must exist and be non-empty.
- Generate the index.
generate_index()writesInterGenOS.dbwith each package’s SHA-256. - Sign the index. A detached, armored GPG signature is written to
InterGenOS.db.sigusing the release subkey. The hardware token prompts for PIN and touch on the workstation. This is the human-in-the-loop step; signing material never sits unattended on the mirror. - Rsync to staging. The signed tree (and the source archives, unless skipped) is copied into a per-publish, timestamped staging directory under the architecture path.
- Atomic promote. The live
currentsymlink is swapped to the new staging directory in a single atomic operation. The prior target is archived. There is no 404 window: in-flight clients finish against the old target or restart against the new one, and no web-server restart is needed. - Transparency-log append. The signed index is appended to an append-only transparency log, giving cold-read auditability of every publish.
A dry run (scripts/publish-repo.sh --dry-run) validates the key, generates the index
in place, and prints the rsync and promote it would perform without writing to the
mirror. Run it before every real publish to confirm the archive count and staging path.
First-publish client switch
On a fresh image, /etc/pkm/repos.conf ships with signature verification commented
off, so a brand-new install’s first pkm sync against an empty mirror does not fail
closed. Once the first signed index is live, the verify default is turned on
(gpg_verify = true) so all subsequent syncs require a valid signature.
Ongoing verification
The mirror host runs a verification pass on a schedule: it checks the index signature, walks every file’s SHA-256, and scans for stray files, alerting on any drift. The same check can be run by hand right after a publish to confirm the live set verifies.
Self-hosting your own repository
Because the format and the publish path are plain files and standard tools, you can host your own repository — a private mirror inside an air-gapped network, a team repo of in-house packages, or a full clone of the official set.
The minimum a repository needs is:
- A directory of
.igos.tar.gzarchives. - An
InterGenOS.dbindex generated over that directory for your architecture, viapkm.repo.generate_index(). - A detached GPG signature
InterGenOS.db.sigover that index, made with a key you control. - A static web server (or any HTTP server) exposing those files under an
x86_64/current/path. - The signing key’s public half distributed to your clients’
/etc/pkm/trusted.gpg, and the repository URL set in/etc/pkm/repos.conf.
The publish script’s design — generate, sign, rsync to a timestamped staging
directory, then atomically swap a current symlink — is worth copying even for a
small repo. It gives you reproducible, no-downtime promotes and a clean rollback (the
previous target is kept), all with ln, mv, and rsync.
Use your own signing key, not the official one. The whole point of the trust model is that signatures are non-transferable: clients trust a repository only because they hold the matching public key. If you run a private repo, you are the trust root for that repo, and your clients should carry your public key — not the official master.
Related pages
- Package Management — installing, removing, and verifying packages on a live system.
- Building from Source — the build pipeline that produces the archives a repository serves.
- Reproducibility — why the source archives ship alongside the binaries.