TrueNAS setup
Server plus one local worker on TrueNAS SCALE, with the worker's
storage pool on a zvol instead of the default
image file. The server keeps the database, repository, logs and worker CA; the
worker builds each package in a devtools chroot inside that zvol.
1. Make the zvol
Create it under your pool, sized at the worker's total (WORKER_DISK_MAX)
plus the margin — 5%, at least 2 GiB — or larger, so WORKER_DISK_MAX can grow
later. The worker only uses as much of the device as the quota allows.
zfs create -s -V 1T \
-o volblocksize=32K \
-o compression=off \
-o primarycache=metadata \
-o logbias=throughput \
tank/aurcache-worker
-smakes it sparse, so it takes pool space as builds write. Leave-sout to reserve the whole size up front.volblocksize=16Kor32K. btrfs's metadata nodes are 16K; 32K trades a little write amplification on metadata for less overhead on data. It cannot be changed after creation — check it later withzfs get volblocksize tank/aurcache-worker.compression=off(orlz4): the pool compresses with zstd inside, so ZFS finds little left to compress.primarycache=metadataandlogbias=throughput: the kernel already caches the pool's data, and the flushes btrfs sends need not be written twice through the ZIL.
In the web UI this is Datasets → Add Zvol with the same size, then set the three tunables afterwards:
zfs set compression=off primarycache=metadata logbias=throughput tank/aurcache-worker
The device appears on the host as /dev/zvol/tank/aurcache-worker.
2. Generate the compose file
On any machine with aurcli — no server needed:
aurcli setup compose --role bundle \
--pool-device /dev/zvol/tank/aurcache-worker --disk-max 950G -o -
-o - writes to stdout, to paste into TrueNAS as a custom app. Without it the
command writes docker-compose.yaml and refuses to clobber an existing file
without --force.
What those flags do to the worker service:
--pool-devicepasses the zvol through as a device (/dev/zvol/tank/aurcache-worker:/dev/aurcache-pool) and setsWORKER_POOL=/dev/aurcache-pool. The worker formats it on first start (mkfs.btrfs, labelledaurcache-pool); a device holding a filesystem the worker did not create is refused, never formatted.--disk-maxsetsWORKER_DISK_MAX_DEFAULT, the pool's total — a starting point you can later change from the worker's page, not a pin.
The command also asks which database the server should use. PostgreSQL is
recommended for anything you intend to keep (--database postgres, with a
generated password unless you pass --db-password), and it asks whether to add
the ixsystems/postgres-upgrade step (--postgres-upgrade /
--no-postgres-upgrade) that TrueNAS's own apps use for major-version
upgrades. See Setup and health.
3. App config
Deploy the pasted file as a custom app. The parts worth checking before it starts:
- Device passthrough. The host path
/dev/zvol/tank/aurcache-workermust resolve on the TrueNAS host; inside the worker it is always/dev/aurcache-pool. - Server storage. Everything the server keeps lives under
/app(the database unless PostgreSQL holds it, the package repository, the internal worker CA, each build's log, the source cache), persisted inaurcache_data. Keep that volume on a dataset with room. Splitting pieces onto different storage (a large/app/repoon bulk disks) works, but the inner mount shadows whatever the outer volume holds at that path — copy existing data across before adding one to a running deployment, or it looks exactly like data loss. See Docker Compose setup. - Ports.
8080(web UI + API),8081(pacman repository, served by the bundled nginx),8083(worker protocol). Publish all three on the LAN. AURCACHE_PUBLIC_URL. Set it to how pacman clients reach this machine, e.g.http://192.168.1.10:8081— the defaulthttp://localhost:8081only works from the host itself.- The worker stays
privileged: truewith a tmpfs/run. Each package is built in asystemd-nspawnchroot, which needs the mounts and namespaces a plain container forbids. Only the worker needs this; the server runs unprivileged. - Enrollment needs nothing. Server and worker share the
enrollvolume, so the worker auto-approves on first start — no token, no approval click.
4. Verify
The worker enrolls itself within a few seconds and starts polling for jobs. On
the Workers page it should read as connected; if a build does not start,
aurcli doctor says
why. Then:
aurcli pkg add --from-installed
aurcli repo config | sudo tee -a /etc/pacman.conf
Moving the pool to another backing later (a larger zvol, a partition) is just
pause, stop, set WORKER_POOL, start — the pool holds nothing that cannot be
rebuilt. See Storage pool.