Files
OpenPXE/deploy/unraid/pxeforge.xml
T
Miles Ward 083277faae Add Unraid quickstart: build-and-publish script + Docker template
Three paths from "Gitea-on-Unraid + a built repo" to "Unraid pulls
PXEForge by tag":

1. scripts/build-and-publish-unraid.sh — one-shot run on the Unraid
   host. Clones from local Gitea (http://localhost:3000), runs the
   iPXE fetch, docker build, docker login + push to Gitea's container
   registry. Token never lands in the host's ~/.docker/config.json:
   we set DOCKER_CONFIG to a tempdir and rm -rf it on exit. Token
   never lands in `ps`/bash history either: --password-stdin.

2. deploy/unraid/pxeforge.xml — Docker template for the Unraid UI.
   Forces NetworkType=host (PXE needs raw L2 broadcast — bridge mode
   doesn't work, full stop), declares the right cap-add, and surfaces
   PXEFORGE_PUBLIC_IP / PXEFORGE_LOG as configurable variables.

3. deploy/unraid/README.md — three documented paths (registry, compose
   from cloned repo, docker load from tarball) and the gotchas that
   actually bite (DHCP collision, host networking, perms on
   /mnt/user/appdata, NFS-needs-CAP_SYS_ADMIN).

The build host I'm running on can't reach Unraid right now (LAN moved
to a different subnet) and the Cloudflare WAF skip rule on
gitea.milesward.dev doesn't yet cover /v2/* or /git-{upload,receive}-pack
paths, so the publish has to happen from the Unraid host itself for now.
This commit is what makes that one-shot.
2026-04-30 00:02:29 -04:00

76 lines
3.8 KiB
XML

<?xml version="1.0"?>
<!--
Unraid Docker template for PXEForge.
Drop this file into /boot/config/plugins/dockerMan/templates-user/
on your Unraid box (or import via the Docker tab → "Add Container" →
"Template Repositories" if you publish it on a Gitea raw URL).
IMPORTANT: PXEForge needs host networking for DHCP/TFTP raw broadcasts.
Bridge mode will NOT work — clients can't see broadcast DHCP from a
bridged container. The template forces NetworkType=host below.
Required ports (already host-bound by the binary; no Unraid mapping
needed in host mode):
udp/67 DHCP proxy
udp/69 TFTP
udp/4011 PXE Boot Server
tcp/80 HTTP (web UI + iPXE scripts + ISO range streaming)
tcp/445 SMB (only when Windows boot is toggled on)
Web UI: http://<unraid-ip>/ (port 80)
-->
<Container version="2">
<Name>PXEForge</Name>
<Repository>gitea.milesward.dev/mward4/pxeforge:latest</Repository>
<Registry>https://gitea.milesward.dev/mward4/-/packages/container/pxeforge</Registry>
<Network>host</Network>
<MyIP/>
<Shell>sh</Shell>
<Privileged>false</Privileged>
<Support>https://gitea.milesward.dev/mward4/PXEForge/issues</Support>
<Project>https://gitea.milesward.dev/mward4/PXEForge</Project>
<Overview>
Air-gapped network PXE boot server. Container-native Rust
implementation — DHCP proxy + TFTP + iPXE chainload + HTTP ISO
streaming, all in one process. Web UI for ISO upload, NFS share
mounting, and Gated Deployment ("horse-race" simultaneous launch
of one ISO across many waiting clients).
NEVER touches the client OS trust store: no test-signed drivers,
no testsigning toggle, no httpdisk.sys. Windows boot uses vanilla
Microsoft-signed WinPE + SMB share.
</Overview>
<Category>Network:Other Network:Management</Category>
<WebUI>http://[IP]/</WebUI>
<TemplateURL/>
<Icon>https://gitea.milesward.dev/mward4/PXEForge/raw/branch/main/crates/webui/src/logo.svg</Icon>
<ExtraParams>--cap-add=NET_BIND_SERVICE</ExtraParams>
<PostArgs/>
<CPUset/>
<DateInstalled/>
<DonateText/>
<DonateLink/>
<Requires>
Host networking. Unraid&#39;s built-in DHCP server (if any) must
not collide with a network that already has DHCP — PXEForge runs
in proxy mode and coexists, but only one DHCP _proxy_ should reply
per broadcast domain.
</Requires>
<Config Name="ISOs" Target="/var/lib/pxeforge/isos" Default="/mnt/user/appdata/pxeforge/isos"
Mode="rw" Description="Where uploaded and seeded .iso files live."
Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/pxeforge/isos</Config>
<Config Name="Work dir" Target="/var/lib/pxeforge/work" Default="/mnt/user/appdata/pxeforge/work"
Mode="rw" Description="Settings, NFS state, and runtime scratch. Persisted across restarts."
Type="Path" Display="always" Required="true" Mask="false">/mnt/user/appdata/pxeforge/work</Config>
<Config Name="SMB share root" Target="/var/lib/pxeforge/smb" Default="/mnt/user/appdata/pxeforge/smb"
Mode="rw" Description="Where extracted Windows install media lives. Only used when Windows toggle is on."
Type="Path" Display="advanced" Required="false" Mask="false">/mnt/user/appdata/pxeforge/smb</Config>
<Config Name="Public IP" Target="PXEFORGE_PUBLIC_IP" Default=""
Mode="" Description="IP advertised to PXE clients. Leave blank to auto-detect; set explicitly on multi-homed Unraid hosts."
Type="Variable" Display="always" Required="false" Mask="false"></Config>
<Config Name="Log filter" Target="PXEFORGE_LOG" Default="info,pxeforge=debug"
Mode="" Description="tracing-subscriber EnvFilter expression."
Type="Variable" Display="advanced" Required="false" Mask="false">info,pxeforge=debug</Config>
</Container>