The Handbook

    Theme
    • Guides
        • Check a system before installing FreeBSD
        • Orient a Linux administrator on FreeBSD
        • Supported FreeBSD releases
        • Choose a FreeBSD documentation and support channel
        • Move files safely without GNU mv -t
        • Update, upgrade, or update packages?
        • Upgrade 14.4 or 15.0 to FreeBSD 15.1
        • Choose packages, ports, or poudriere
        • Choose the quarterly or latest package branch
        • Choose a FreeBSD download or package mirror
        • Make a system setting persistent
        • Configure locale, keyboard, and time zone
        • Configure a serial console for recovery
        • Choose a custom kernel, module, or loader setting
        • Run a Linux binary with the compatibility layer
        • Check desktop and laptop hardware before installation
        • Choose and check a graphics driver
        • Choose Xorg or Wayland
        • Build a maintainable desktop baseline
        • Install and check a desktop browser
        • Check laptop Wi-Fi, power, and suspend
        • Check multimedia readiness
        • Choose and configure a printing stack
        • Run Windows applications with Wine
        • Snapshot and replicate a ZFS dataset
        • Choose a filesystem and storage layout
        • Operate ZFS without losing the recovery path
        • Restore files from a ZFS snapshot
        • Read ZFS pool health and run a scrub
        • Replace a failed device in a ZFS mirror
        • Replicate a ZFS dataset over SSH
        • Change PF safely on a remote host
        • Configure a narrow WireGuard tunnel
        • Plan a FreeBSD home server
        • Choose a mail server or an outgoing relay
        • Publish a network service safely
        • Choose a jail network model
        • Choose native jails or a jail manager
        • Choose a jail or a bhyve virtual machine
        • Establish a FreeBSD security baseline
        • Choose a MAC policy
        • Audit security-relevant activity
        • Start a DTrace performance investigation
    • Integrations
        • Create a first jail with Bastille
        • Compare jail managers and OCI tooling
        • Publish a Bastille service through PF
        • Mount a ZFS dataset in a Bastille jail
        • Update and upgrade Bastille jails
        • Back up and restore a Bastille jail
        • Prepare bhyve and vm-bhyve
        • Choose NFS or Samba for file sharing
        • Choose ZFS backup automation
        • Operate a signed poudriere repository
        • Manage FreeBSD configuration with Ansible or Salt
        • Run Motion with webcamd on FreeBSD
        • Design a reverse proxy, certificates, and monitoring
    • FAQ
      • Troubleshooting
          • Recover an interrupted freebsd-update run
          • Resolve a package repository or ABI mismatch
          • Diagnose the FreeBSD boot path
          • Recover with a ZFS boot environment
          • Diagnose DNS, routing, and firewall paths
          • Diagnose network mbuf exhaustion
          • Bind a service to a low port without running it as root
          • Diagnose audio output or input
          • Diagnose webcamd, cuse, and a webcam
          • Fix USB device permissions without opening every device
      • About this handbook
      • Synopsis
      • Define the repository contract
      • Create controlled build inputs
      • Separate package signing from transport security
      • Publish only a completed repository
      • Enroll clients with explicit trust
      • Maintain and retire repository generations
      • Primary references

      Operate a signed poudriere repository

      Last reviewed
      13 August 2026
      Applies to
      15.1-RELEASE, 15.0-RELEASE, 14.4-RELEASE

      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:

      1. a source policy for the ports tree and local overlays;
      2. an isolated build for each supported FreeBSD ABI and architecture;
      3. a signed, immutable publication result;
      4. 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:

      InputDecision to preserve
      Target systemsFreeBSD release, architecture, and package ABI
      Ports sourceBranch or reviewed commit and update procedure
      Package scopeVersion-controlled list of required port origins
      CustomizationOptions, make.conf, overlays, and local patches
      SigningCatalogue signer, key custody, rotation, and revocation path
      PublicationStaging location, current URL, retention, and rollback
      Client policyRepository 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:

      1. confirm the selected repository and package origins;
      2. save and review the proposed transaction;
      3. test the transaction on a representative non-production system;
      4. verify service health and rollback after installation;
      5. 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.

      Primary references #

      • FreeBSD Handbook: Building packages with poudriere
      • FreeBSD Handbook: Configuring pkg clients for poudriere
      • Poudriere project
      • poudriere-repo(8)
      • pkg-repo(8)
      • pkg-rquery(8)
      • pkg.conf(5)

      Independent documentation. Not affiliated with or endorsed by the FreeBSD Project or the FreeBSD Foundation.

      Report a bug
      • Synopsis
      • Define the repository contract
      • Create controlled build inputs
      • Separate package signing from transport security
      • Publish only a completed repository
      • Enroll clients with explicit trust
      • Maintain and retire repository generations
      • Primary references