#!/usr/bin/env bash # build-and-publish-unraid.sh — one-shot: clone OpenPXE, build the image, # push it to your local Gitea container registry. Run this ON the Unraid # box (or any host that can reach Gitea on http://localhost:3000 or its # LAN IP). No Cloudflare in the way; the proxy doesn't matter for this # path. # # Inputs (env vars, all optional except GITEA_TOKEN): # GITEA_TOKEN personal access token with `write:package` scope # GITEA_HOST default: localhost:3000 (use 192.168.1.49:3000 if # you're on the LAN but not on the Unraid host) # GITEA_OWNER default: mward4 # GITEA_REPO default: OpenPXE # IMAGE_TAG default: 0.1.0 (also tagged :latest) # PLATFORM default: linux/amd64 (Unraid is x86_64) # WORKDIR default: /tmp/openpxe-build (deleted on success) # # What it does: # 1. git clone /mward4/OpenPXE.git into WORKDIR # 2. fetch iPXE binaries (scripts/fetch-ipxe.sh) # 3. docker build deploy/docker/Dockerfile -> openpxe:$TAG (and :latest) # 4. docker login to GITEA_HOST using the token # 5. docker push to //openpxe: and :latest # 6. docker logout, scrub creds, clean WORKDIR # # After this, on any Unraid Docker template, set: # Repository: /mward4/openpxe:0.1.0 (or :latest) # Network: host (DHCP/TFTP need raw L2) set -euo pipefail GITEA_HOST=${GITEA_HOST:-localhost:3000} GITEA_OWNER=${GITEA_OWNER:-mward4} GITEA_REPO=${GITEA_REPO:-OpenPXE} IMAGE_TAG=${IMAGE_TAG:-0.1.0} PLATFORM=${PLATFORM:-linux/amd64} WORKDIR=${WORKDIR:-/tmp/openpxe-build} # Lowercase the image name — OCI distribution rejects uppercase paths. IMAGE_NAME="$(printf '%s' "$GITEA_REPO" | tr '[:upper:]' '[:lower:]')" FULL_TAG="$GITEA_HOST/$GITEA_OWNER/$IMAGE_NAME:$IMAGE_TAG" LATEST_TAG="$GITEA_HOST/$GITEA_OWNER/$IMAGE_NAME:latest" if [[ -z "${GITEA_TOKEN:-}" ]]; then echo "ERROR: set GITEA_TOKEN to a token with write:package scope." >&2 echo " Gitea -> Settings -> Applications -> Generate New Token." >&2 exit 2 fi # Required tools — fail loudly upfront so the operator doesn't wait # 20 minutes on a build that was going to fail at `docker push`. for tool in git docker; do command -v "$tool" >/dev/null 2>&1 \ || { echo "ERROR: '$tool' not found in PATH" >&2; exit 2; } done # Use a private docker config so the credential never lands in # ~/.docker/config.json on the Unraid box. We blow it away in the # trap below. DOCKER_CONFIG="$(mktemp -d)" export DOCKER_CONFIG trap 'rm -rf "$DOCKER_CONFIG"; rm -rf "$WORKDIR"' EXIT echo echo "==> Workspace : $WORKDIR" echo "==> Gitea host : $GITEA_HOST" echo "==> Image to push : $FULL_TAG" echo "==> Platform : $PLATFORM" echo # Step 1: clone (shallow — we don't need history for a build). rm -rf "$WORKDIR" git -c "http.extraHeader=Authorization: token $GITEA_TOKEN" \ clone --depth 1 \ "http://$GITEA_HOST/$GITEA_OWNER/$GITEA_REPO.git" "$WORKDIR" cd "$WORKDIR" # Step 2: fetch iPXE binaries. The Dockerfile's first stage will also do # this, but doing it once here means a re-run with a hot Docker cache # skips the apt-get install + GitHub fetch entirely. bash scripts/fetch-ipxe.sh # Step 3: build. We don't need buildx for a same-arch build on Unraid, # but we use --pull so a stale cached `rust:1.82-bookworm` doesn't bake # in a CVE that's been fixed upstream. docker build \ --pull \ --platform "$PLATFORM" \ --file deploy/docker/Dockerfile \ --tag "$FULL_TAG" \ --tag "$LATEST_TAG" \ . # Step 4: login. --password-stdin keeps the token out of `ps` output and # bash history. The token still lands in $DOCKER_CONFIG/config.json # (base64-encoded) but that dir is ours and gets nuked by the trap. printf '%s' "$GITEA_TOKEN" | docker login \ --username "$GITEA_OWNER" \ --password-stdin \ "$GITEA_HOST" # Step 5: push both tags. docker push "$FULL_TAG" docker push "$LATEST_TAG" # Step 6: logout (best-effort; if it fails the trap still scrubs). docker logout "$GITEA_HOST" || true echo echo "==> Done. Pull from Unraid templates with:" echo " $FULL_TAG" echo " $LATEST_TAG" echo