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 and Upgrade FreeBSD
        • 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
        • Run a command from cron reliably
        • 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
        • Find what is using ZFS space
        • Grow a ZFS virtual disk
        • 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
        • Share a directory with NFS
        • Share files with a named Samba account
        • 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
        • Build a first signed poudriere repository
        • 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 a service that will not start
          • Diagnose audio output or input
          • Diagnose webcamd, cuse, and a webcam
          • Fix USB device permissions without opening every device
      • About this handbook
      • Synopsis
      • Prepare the builder and signing key
      • Create the inputs and build
      • Publish a complete generation
      • Configure a client with explicit trust
      • Primary references

      Build a first signed poudriere repository

      Last reviewed
      7 November 2026
      Applies to
      15.1-RELEASE
      Tested on
      15.1-RELEASE

      Synopsis #

      Start a private repository with one small package before adding a production package list. This procedure builds misc/figlet, signs the catalogue with a local RSA key, and installs the result on another FreeBSD system. One builder and disk-backed working files limit memory use.

      The examples use ZFS pool zroot, a 15.1 amd64 jail, and ports branch 2026Q4. Substitute the actual pool, architecture, and reviewed branch. Clients need a compatible ABI; matching major versions alone do not qualify kernel modules or every base-library dependency.

      Prepare the builder and signing key #

      # pkg install poudriere git-lite
      # install -d -m 755 /usr/local/poudriere/distfiles
      # install -d -m 700 /usr/local/etc/ssl/keys
      # install -d -m 755 /usr/local/etc/ssl/certs
      # openssl genrsa -out /usr/local/etc/ssl/keys/poudriere.key 3072
      # chmod 0600 /usr/local/etc/ssl/keys/poudriere.key
      # openssl rsa -in /usr/local/etc/ssl/keys/poudriere.key -pubout -out /usr/local/etc/ssl/certs/poudriere.pub
      # chmod 0644 /usr/local/etc/ssl/certs/poudriere.pub
      

      Keep the private key outside the web root. Clients receive only the public key. Do not regenerate an established repository’s key during ordinary setup or rebuilds.

      Edit these settings in /usr/local/etc/poudriere.conf, preserving unrelated configuration:

      ZPOOL=zroot
      BASEFS=/usr/local/poudriere
      FREEBSD_HOST=https://download.freebsd.org
      DISTFILES_CACHE=/usr/local/poudriere/distfiles
      USE_TMPFS=no
      PARALLEL_JOBS=1
      PKG_REPO_SIGNING_KEY=/usr/local/etc/ssl/keys/poudriere.key
      

      The distfiles directory must exist before building. Disk-backed working files do not remove a compiler’s own memory requirement.

      Create the inputs and build #

      # poudriere ports -c -p quarterly -B 2026Q4 -m git+https
      # poudriere jail -c -j 151amd64 -v 15.1-RELEASE -a amd64
      # poudriere ports -l
      # poudriere jail -l
      $ git -C /usr/local/poudriere/ports/quarterly rev-parse HEAD
      

      Jail creation applies available base updates. Check its reported version. Preserve the ports commit with the approved package list and options; a quarterly branch continues changing.

      Create /usr/local/etc/poudriere.d/small-packages containing:

      misc/figlet
      

      Set MAKE_JOBS_NUMBER=2 in /usr/local/etc/poudriere.d/make.conf, or use a lower value on a smaller host. Compiler jobs within a port are separate from concurrent port builders.

      Build:

      # poudriere bulk -j 151amd64 -p quarterly -J 1 -f /usr/local/etc/poudriere.d/small-packages
      

      The first run also builds the package-management bootstrap. Review final counts and individual logs. Continue only after the requested packages and dependencies built successfully, with no unexplained failures or skips.

      Publish a complete generation #

      For these jail and ports-tree names, .latest selects the completed generation:

      # install -d -m 755 /usr/local/www/packages/generation-1
      # cp -a /usr/local/poudriere/data/packages/151amd64-quarterly/.latest/. /usr/local/www/packages/generation-1/
      # chmod -R a+rX /usr/local/www/packages/generation-1
      # ln -s generation-1 /usr/local/www/packages/current
      

      Preserve the whole hierarchy, including catalogue files. Use a new generation name for later publications; do not overwrite files while clients read them. The web service needs read access to the copy, without write access or access to signing keys.

      Expose current/ through the existing web server. An nginx server block can contain:

      location /packages/ {
          alias /usr/local/www/packages/current/;
          autoindex off;
      }
      

      Validate and reload that server’s configuration. Use HTTPS for normal deployment. HTTP is appropriate only where a deliberately trusted private transport is acceptable; signatures provide authenticity, not confidentiality.

      Configure a client with explicit trust #

      Transfer poudriere.pub through an already trusted administrative channel. Install it on the client as /usr/local/etc/pkg/keys/poudriere.pub, readable by the package manager. Do not accept a signing key solely from the repository it is meant to authenticate.

      Create /usr/local/etc/pkg/repos/Local.conf, substituting the real URL:

      Local: {
          url: "https://packages.example.org/packages",
          enabled: yes,
          signature_type: "pubkey",
          pubkey: "/usr/local/etc/pkg/keys/poudriere.pub",
          priority: 100
      }
      

      Preserve other repository definitions. Explicit -r Local limits the following transaction to this repository; it does not establish a complete policy for mixing sources.

      $ fetch -o /dev/null https://packages.example.org/packages/meta.conf
      # pkg update -f -r Local
      $ pkg rquery -r Local '%n-%v'
      # pkg install -r Local figlet
      $ pkg info -f figlet
      $ figlet -f small hello
      

      Read the complete update output. Stop on an invalid signature even if another line says the repository is up to date. A previous cached catalogue can remain usable after an unsuccessful refresh. Check the trusted key, URL, and published generation; do not disable signature checking.

      Confirm that the installed package identifies the intended repository and that the program runs. Before broad enrollment, repeat application checks for the actual package list. See repository operations for generation retention, key rotation, and client policy.

      Primary references #

      • FreeBSD Handbook: poudriere
      • poudriere-jail(8)
      • poudriere-ports(8)
      • poudriere-bulk(8)
      • pkg-repo(8)
      • pkg.conf(5)

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

      Report a bug
      • Synopsis
      • Prepare the builder and signing key
      • Create the inputs and build
      • Publish a complete generation
      • Configure a client with explicit trust
      • Primary references