5.2 KiB
PXEForge on Unraid
Three paths from "I have an Unraid box with Gitea on it" to "PXE clients boot from PXEForge". Pick the one that matches what you have.
Path A — build on Unraid, push to Gitea registry, pull by tag
Recommended once you've done it once. Image is published to
gitea.milesward.dev/mward4/pxeforge:0.1.0 (or your equivalent) and
every Unraid template / docker-compose just references the tag.
Pre-flight:
- Gitea has the Container Registry enabled (Site Admin → Configuration → set
[packages] ENABLED = trueinapp.ini; default-on in Gitea ≥ 1.18). - You have a Gitea personal access token with
write:packagescope (User → Settings → Applications → Generate New Token, checkpackageread+write).
Run on the Unraid host (Settings → Terminal, or ssh root@unraid):
# Pull just the build script straight from Gitea (no clone needed first):
GITEA_TOKEN=<your-token>
curl -fsSL \
-H "Authorization: token $GITEA_TOKEN" \
http://localhost:3000/mward4/PXEForge/raw/branch/main/scripts/build-and-publish-unraid.sh \
-o /tmp/pxeforge-publish.sh
# Run it. ~6 min on Unraid hardware (native amd64, no QEMU).
chmod +x /tmp/pxeforge-publish.sh
GITEA_TOKEN=$GITEA_TOKEN /tmp/pxeforge-publish.sh
What it does:
- Shallow-clones the repo from local Gitea (no Cloudflare, no LAN issues).
- Runs
scripts/fetch-ipxe.shto grab the iPXE binaries from the official release URLs. docker buildagainstdeploy/docker/Dockerfile.docker login gitea.milesward.dev:3000using a tempDOCKER_CONFIGso the credential never lands in your real~/.docker/config.json.docker pushboth:0.1.0and:latest.- Logout, scrub the temp config, delete the workspace.
After it finishes, in Unraid → Docker → Add Container, set:
| Field | Value |
|---|---|
| Repository | gitea.milesward.dev/mward4/pxeforge:0.1.0 |
| Network | host |
| Extra args | --cap-add=NET_BIND_SERVICE |
Volume mounts (paths inside container in bold):
/var/lib/pxeforge/isos↔/mnt/user/appdata/pxeforge/isos/var/lib/pxeforge/work↔/mnt/user/appdata/pxeforge/work/var/lib/pxeforge/smb↔/mnt/user/appdata/pxeforge/smb
Or skip the manual UI by dropping pxeforge.xml (in this directory)
into /boot/config/plugins/dockerMan/templates-user/ and Unraid will
list it as a one-click template.
Web UI: http://<unraid-ip>/.
Path B — docker-compose up directly from cloned repo
Skip the registry entirely. Useful for "hack on it locally" iterations.
ssh root@unraid
cd /mnt/user/appdata
git clone http://localhost:3000/mward4/PXEForge.git pxeforge-src
cd pxeforge-src
bash scripts/fetch-ipxe.sh
docker compose -f docker-compose.yml up -d --build pxeforge
The bundled docker-compose.yml already wires host networking, the
right cap_add, and bind-mounts to ./data/. Edit those bind-mount
paths if you want them under /mnt/user/appdata/pxeforge/.
Path C — docker load from a tarball I built off-box
For when the build host can reach Unraid but Unraid can't reach the internet. Build the image somewhere with a cargo + buildx environment, then:
# On the build host
docker save pxeforge:0.1.0 | gzip > pxeforge-0.1.0.tar.gz
# Transfer (rsync / scp / SMB / ZFS-replicate / sneakernet)
scp pxeforge-0.1.0.tar.gz root@unraid:/tmp/
# On Unraid
gunzip -c /tmp/pxeforge-0.1.0.tar.gz | docker load
docker tag pxeforge:0.1.0 gitea.milesward.dev/mward4/pxeforge:0.1.0
If you want it pullable by tag from other Unraid templates, push to Gitea afterward (path A's last step).
Verifying it works
Once the container is up, from any LAN host:
# Should return 'ok'
curl -s http://<unraid-ip>/healthz
# Should return 'ready' if iPXE binaries are bundled
curl -s http://<unraid-ip>/readyz
Web UI: http://<unraid-ip>/. The Dashboard's top-bar pill should
read ● ready. Upload an ISO, boot a test machine PXE → it should
show up in the Dashboard's "Recent connections" table within seconds.
Common gotchas
- DHCP collision. Don't run two PXE proxies on the same broadcast domain. PXEForge runs in proxy mode and never offers IP leases, so it coexists with whatever DHCP server is already on the network — but two proxies racing each other will whichever-wins at random.
- Host networking only. Bridge mode containers don't see broadcast DHCP. There's no working bridge-mode config for a PXE server.
- Permissions on
/mnt/user/appdata/pxeforge. The container runs as uid 10001 by default. The entrypoint chowns the bind mounts to 10001 on first start, but only if the container itself has root —--user=rootisn't needed; the multi-stage Dockerfile starts as root, fixes perms, then drops to pxeforge via gosu. - NFS mounts in the Storage tab. Mounting NFS inside the container
needs
CAP_SYS_ADMIN. To enable, add--cap-add=SYS_ADMINto the Unraid template's "Extra args" — but understand that's a meaningful capability, comparable to--privileged. Skip it if you only need uploads.