Sign Your Repository
Repository signing has two layers: metadata signatures and RPM package signatures. Configure each layer separately:
| Path | Output | Client control |
|---|---|---|
| RPM metadata | repodata/repomd.xml.asc |
repo_gpgcheck=1 |
| APT metadata | InRelease and Release.gpg |
Signed-By |
| RPM package body | embedded RPM signature | gpgcheck=1 |
APT verifies package hashes through the signed Release file, so DEBs need no separate package signature. Start with metadata signing. Add RPM package signing when clients require gpgcheck=1.
This guide uses the pigsty Repository from the YUM or APT tutorial. Run only the commands for the formats and Dists you created.
1. Create a dedicated key
Install GPG first. These commands create an unencrypted test key and export it to a private directory. For an existing protected key, use a passfile as described below.
SOW reads the private key from /srv/sow-secrets, outside the public Repository. Give the SOW service account access to this directory if it differs from your user. Distribute repo-signing.pub to clients.
2. Configure metadata signing
In /srv/sow/sow.yml, merge these metadata entries into the Repository’s existing signing block. Keep its package policy and Dist definitions. Include only the formats you use:
For a protected key, configure the password source before checking or building.
Add passfile: /run/secrets/gpg-password next to key,
or run export SOW_GPG_PASSFILE=/run/secrets/gpg-password. For one invocation, use
sow build -r pigsty --passfile /run/secrets/gpg-password. This also works with
agent://FINGERPRINT keys. Keep the file outside the repository, normally mode 0600.
Its contents are the password itself: one nonempty UTF-8 line, with an optional final
LF or CRLF. SOW preserves spaces and tabs and searches no default file.
See Password files for priority and format details.
Existing passphrase references continue to work. Configuration stores references, not secret values.
Validate the configuration, rebuild, and check:
3. Optional: inspect the metadata signer
The preceding sow check verifies metadata signatures. To inspect the signer with GPG,
run the commands for your Dists:
Compare the displayed fingerprint with the public key you distribute to clients.
4. Optional: sign RPM package bodies
For a new repository, configure package signing before importing RPMs. Add this block under the existing signing.rpm configuration:
Replace the placeholder with the 40-hex fingerprint in $FPR. Install rpm and gpg,
and make the secret key available in the GPG keyring used by rpm.
fill signs newly imported packages unless their signatures already verify against the
configured key or trusted_keys. SOW verifies RSA, DSA, ECDSA, and EdDSA RPM signatures, including header-only signatures stored in RPM signature header tag 267 (RPMSIGTAG_DSA). See RPM signing policy for
other modes.
For a protected package-signing key, configure passfile under signing.rpm.packages
or use SOW_GPG_PASSFILE. A passfile under metadata only applies to that metadata
key. config check validates the package-signing prerequisites, but it does not test
the password by signing a package. The following add must sign a package to test that path.
SOW signs a private copy during add; the input file stays unchanged. build checks stored RPMs against the policy but does not re-sign them.
If you already imported RPMs, check their signatures before enabling fill. Keep trusted upstream public keys in trusted_keys. For unsigned or untrusted stored packages, prepare correctly signed packages with new versions and filenames. Alternatively, configure signing in a new repository, then import the originals.
After configuring the policy, import a new package and check the result:
To inspect a resulting package independently, run rpmkeys --checksig on its file in
pigsty/pool/.
5. Enable DNF verification
First publish the signed Repository. Then transfer the public key to the client through a trusted channel:
Then enable the checks that correspond to what you signed:
If you sign only metadata, use repo_gpgcheck=1 and gpgcheck=0. With package checking enabled, install each trusted upstream package key as well as your own key. Then run sudo dnf makecache --refresh and install a package.
6. Enable APT verification
After publishing the signed Repository, install its public key on the client as a dedicated keyring:
Reference it from deb822 configuration and do not set Trusted: yes:
Run sudo apt update and install a package. If verification fails, compare the client keyring fingerprint with the signer shown by gpg --verify. For ARM64 clients, change Architectures to arm64.
Plain-mode RPM signing
Plain mode can sign RPM package bodies, but it does not sign repository metadata or create
an APT Release:
Replace 0123456789ABCDEF with your key ID or fingerprint. The matching private key must
be available to rpm and GPG. SOW preserves existing signatures, including upstream signatures, and recognizes RSA, DSA, ECDSA, and EdDSA header-only signatures in RPM signature header tag 267 (RPMSIGTAG_DSA). To replace all RPM signatures with your key, use --overwrite on a separate
working copy. See sow create for key formats.
For a protected key, add
--passfile /run/secrets/gpg-password or set SOW_GPG_PASSFILE to that path.
These options only supply SOW’s signing password. A separate gpg command needs
its own credential configuration.
For an existing YUM repository, follow the migration guide
to preserve publication time and sign repomd.xml after the final create run.
Key changes
To rotate a metadata key, distribute the new public key, update the key reference, then run build, check, and publish. Changing the reference or resolved fingerprint marks affected Dists dirty.
For RPM package keys, use fill and keep the old public key in trusted_keys until packages signed by it are withdrawn or replaced. Keep the corresponding client key available during this period. Existing package objects remain unchanged.
Test the final repository with the DNF or APT versions your users run. See Platforms & Integrations for automated coverage.