Publish a signed local registry
This tutorial publishes the repository's real zlib package to a signed
registry on the local filesystem, then reads it through apm. It exercises the
same catalog, signature, release, and binary-cache paths used by a hosted
registry without requiring a server.
For production consumer configuration, including other public and internal registries, use Configure package registries.
You need Nix with flakes enabled, Git with SHA-256 repository support, and an
incremental builds of the independent apr and apm programs:
nix develop -c cargo build --manifest-path crates/Cargo.toml --bin apr --bin apm
export PATH="$PWD/crates/target/debug:$PATH"
git init --object-format=sha256 /tmp/aos-sha256-probe
Remove the probe after Git accepts the command. Configure a real Git author identity if one is not already present:
git config --global user.name "AOS Registry Maintainer"
git config --global user.email "registry@example.com"
#Build a package
Build zlib and capture its store path without creating a result symlink:
STORE_PATH="$(nix build .#pkg-zlib --no-link --print-out-paths)"
printf '%s\n' "$STORE_PATH"
apr reads the package version, platform, runtime closure, and NAR hashes from
the store path. Overrides such as --name and --version are available, but a
normal AOS package should not need them.
#Create a signed registry
Generate the first maintainer key. The private key is created with mode 0600
under ~/.config/apm/keys; the command prints the public trust line:
KEY_OUTPUT="$(apr keys generate initial --registry acme 2>&1)"
printf '%s\n' "$KEY_OUTPUT"
KEY="$HOME/.config/apm/keys/acme-initial.key"
TRUST_KEY="$(printf '%s\n' "$KEY_OUTPUT" | \
awk '$NF ~ /^acme:Ed25519:/ { print $NF; exit }')"
test -n "$TRUST_KEY"
Create a bare Git origin on the local filesystem, then create the registry with that remote. The public key enters the committed roster and the matching private key signs the initial commit:
GIT_DIR="$PWD/acme-registry.git"
git init --bare --object-format=sha256 "$GIT_DIR"
apr create acme \
--remote "file://$GIT_DIR" \
--trust-key "$TRUST_KEY" \
--trust-key-id initial \
--key "$KEY"
The authoring clone is under ~/.local/share/apm/registries/acme. The bare
origin will become the filesystem read surface after the first push.
#Release and publish it
Choose an empty absolute directory for the generated HTTP surface and binary cache:
PUBLISH_DIR="$PWD/acme-registry-public"
mkdir -p "$PUBLISH_DIR"
apr release 1.0.0 \
--registry acme \
--store-path "$STORE_PATH" \
--description "Compression library" \
--license Zlib \
--maintainer registry@example.com \
--key "$KEY" \
--cache-url "file://$PUBLISH_DIR" \
--upload-url "file://$PUBLISH_DIR"
apr push --registry acme --branch stable --set-upstream
git -C "$HOME/.local/share/apm/registries/acme" \
push origin refs/tags/1.0.0
The release command publishes and commits package metadata, records the store
closure, generates the static Nix cache, creates a signed 1.0.0 tag, and
uploads the generated HTTP origin in safe order. The following push makes the
branch and signed tag available through the bare filesystem Git origin. Inspect
both sides:
apr packages --registry acme
apr keys list --registry acme
git --git-dir "$GIT_DIR" show-ref
find "$PUBLISH_DIR" -maxdepth 2 -type f | sort | head
#Consume the registry
Add the bare Git origin as a user-scope registry. Select stable explicitly
because a newly initialized bare repository may retain a different default
HEAD. Supplying the trust key makes the first synchronization verifiable:
apm registry add "file://$GIT_DIR" \
--name acme \
--priority 900 \
--branch stable \
--trust-key "$TRUST_KEY"
apm search zlib --registry acme
apm show zlib --registry acme
apm install zlib --registry acme --dry-run
The filesystem transport is useful for development, removable media, and
shared storage. The package metadata comes from the bare Git repository; the
cache URL committed in the release points at $PUBLISH_DIR. Production rollout
channels require a static HTTP origin.
Now that acme has a local consumer configuration, register the private key
path so later producer commands can use the roster id instead of repeating a
path:
apr keys register initial --key "$KEY" --registry acme
apr status --registry acme
Continue with Host a registry to put the same static tree behind HTTPS, or Stage and schedule updates to introduce a channel.