Synopsis #
Poudriere turns a selected Ports Collection, package list, and option set into a binary package repository. It provides clean build jails and repeatable package production; it does not decide which source revision is trusted, protect the signing key, publish the result, or approve a client upgrade.
A maintainable repository therefore has four distinct boundaries:
- a source policy for the ports tree and local overlays;
- an isolated build for each supported FreeBSD ABI and architecture;
- a signed, immutable publication result;
- client configuration that trusts only the intended signing identity.
Use packages, ports, or poudriere to confirm that a private repository is warranted before adopting this operating burden.
Define the repository contract #
Record the following inputs before creating a build jail:
| Input | Decision to preserve |
|---|---|
| Target systems | FreeBSD release, architecture, and package ABI |
| Ports source | Branch or reviewed commit and update procedure |
| Package scope | Version-controlled list of required port origins |
| Customization | Options, make.conf, overlays, and local patches |
| Signing | Catalogue signer, key custody, rotation, and revocation path |
| Publication | Staging location, current URL, retention, and rollback |
| Client policy | Repository priority and whether official packages remain enabled |
A build named only production conceals important compatibility information. Names should expose the intended release, architecture, ports source, and option set without being treated as the source of truth.
Kernel modules and packages that depend closely on base-system libraries need stricter alignment than ordinary applications. A package repository is not evidence that one build can safely serve every supported release.
Create controlled build inputs #
Install poudriere from one coherent package repository, then use the current FreeBSD poudriere procedure to create the target jail and Git-backed ports tree. The exact commands depend on the chosen release, architecture, filesystem layout, and poudriere version, so long-lived automation should not copy identifiers from a generic example.
Inspect the resulting inputs before the first bulk build:
# poudriere jail -l
# poudriere ports -l
Keep package lists and files beneath /usr/local/etc/poudriere.d/ under version control, excluding private keys and credentials. Record the ports commit used for every published build. Interactive option changes that are not captured with the rest of the input make a rebuild non-reproducible.
Run an initial bulk build for a small package list and review its build log and generated repository before adding production clients. A failed build is not an acceptable partial publication merely because some packages were produced.
Separate package signing from transport security #
pkg-repo(8) strongly recommends signing the repository catalogue. Poudriere supports a private key through PKG_REPO_SIGNING_KEY or an external SIGNING_COMMAND.
These choices create different trust boundaries:
- A local signing key is simpler, but compromise of the builder can expose both packages and the signing identity.
- An external signer can keep the private key away from the build and web roots, but requires a separately reviewed protocol and availability plan.
The private key must not be stored in the published package tree, included in configuration management, or copied to clients. Clients receive only the public key or trusted fingerprint material through a channel independent of the repository URL.
HTTPS authenticates and protects transport. A pkg catalogue signature authenticates repository metadata against the locally configured signing identity. One does not replace the other. Certificate automation for the web endpoint belongs to the reverse proxy, certificate, and monitoring architecture .
Publish only a completed repository #
Expose the package directory generated by a successful poudriere run through a dedicated virtual host or a narrow static-file location. The web service needs read access to published files, not write access to build configuration or signing keys.
Publication should switch clients from one complete repository generation to another. Avoid synchronizing changing catalogue and package files directly into the live path while clients can read them. Retain at least the previously approved generation until the new generation has passed client qualification.
Test from an expendable client before broad enrollment:
$ fetch -o /dev/null https://pkg.example.invalid/repository/meta.conf
# pkg -vv
# pkg update -f
$ pkg rquery -r LocalRepository '%n-%v' | head
Replace the example host and repository name with the reviewed deployment values. pkg -vv confirms effective repository configuration; it can contain more output than should be attached unredacted to a public issue.
Enroll clients with explicit trust #
Place local repository configuration beneath /usr/local/etc/pkg/repos/, not in /etc/pkg/FreeBSD.conf. For built-in signing, the repository entry uses signature_type: "pubkey" and a local pubkey path. An external signing command uses signature_type: "fingerprints" and the trusted fingerprint directory described by pkg-repo(8) and pkg.conf(5).
Decide deliberately whether the official repository remains enabled. Enabling multiple repositories without an origin and priority policy can combine dependencies from different builds. Disabling the official repository makes the private repository responsible for every required package and security rebuild.
Before approving a package upgrade:
- confirm the selected repository and package origins;
- save and review the proposed transaction;
- test the transaction on a representative non-production system;
- verify service health and rollback after installation;
- promote the same repository generation without rebuilding it.
The quarterly or latest package guide explains branch policy. An unexpected ABI or catalogue error belongs in package repository and ABI troubleshooting , not in a forced installation.
Maintain and retire repository generations #
Each publication record should contain the build inputs, successful log, catalogue signing identity, publication time, client test result, and replacement or retirement date. Monitor build failures, repository reachability, certificate expiry, catalogue age, and outstanding package vulnerabilities.
Signing-key rotation requires an overlap plan that establishes the new public identity on clients before the old identity disappears. Repository rollback restores a previously complete and signed generation; it does not automatically downgrade packages already installed on clients.