# 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 = true` in `app.ini`; default-on in Gitea ≥ 1.18). - You have a Gitea **personal access token** with `write:package` scope (User → Settings → Applications → Generate New Token, check `package` read+write). Run on the Unraid host (Settings → Terminal, or `ssh root@unraid`): ```bash # Pull just the build script straight from Gitea (no clone needed first): GITEA_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: 1. Shallow-clones the repo from local Gitea (no Cloudflare, no LAN issues). 2. Runs `scripts/fetch-ipxe.sh` to grab the iPXE binaries from the official release URLs. 3. `docker build` against `deploy/docker/Dockerfile`. 4. `docker login gitea.milesward.dev:3000` using a temp `DOCKER_CONFIG` so the credential never lands in your real `~/.docker/config.json`. 5. `docker push` both `:0.1.0` and `:latest`. 6. 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:///`. ## Path B — `docker-compose up` directly from cloned repo Skip the registry entirely. Useful for "hack on it locally" iterations. ```bash 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: ```bash # 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: ```bash # Should return 'ok' curl -s http:///healthz # Should return 'ready' if iPXE binaries are bundled curl -s http:///readyz ``` Web UI: `http:///`. 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=root` isn'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_ADMIN` to the Unraid template's "Extra args" — but understand that's a meaningful capability, comparable to `--privileged`. Skip it if you only need uploads.