···1212- Add tarpit for vulnerability scanners hitting known exploit paths (#18)
13131414### Added
1515+- Add Traefik ingress for Spindle CI runner at spindle.sans-self.org (#59)
1616+- Add self-hosted Spindle CI runner with Podman rootless (#57)
1517- Add Zot container registry with S3 storage and CVE scanning (#56)
1618- Update PDS to use S3 for blob storage instead of filesystem (#52)
1719- Add S3 remote backend for OpenTofu state (#50)
···2325- Add Tangled knot with Spindle CI/CD to k3s cluster (#1)
24262527### Fixed
2828+- Fix Spindle CI runner provisioning for all nodes (#61)
2629- Fix knot post-receive hooks not being executable (#54)
2730- Remove deleted pds-test subdomain from TLS certificate (#48)
2831- Restore PDS and knot data from S3 backups (#34)
···3235- Update PDS to v0.4.208 for OAuth metadata support (#13)
33363437### Changed
3838+- Update tarpit response with custom message (#58)
3539- Upgrade cluster nodes from CAX11 to CAX21 for more memory headroom (#53)
3640- Remove IP allowlist restriction from kube API and SSH firewall (#49)
3741- Add health check that detects SQLite locking failures (#16)
+18-1
kube.tf
···9898 # Spindle CI runner — provision user + rootless Podman on every node.
9999 # Binary pulled from Zot registry (fails gracefully on first bootstrap when Zot isn't up yet).
100100 postinstall_exec = [
101101+ # User + subuid/subgid for rootless Podman
101102 "useradd --create-home --shell /bin/bash spindle 2>/dev/null || true",
103103+ "chown spindle:spindle /home/spindle",
102104 "grep -q '^spindle:' /etc/subuid || usermod --add-subuids 100000-165535 spindle",
103105 "grep -q '^spindle:' /etc/subgid || usermod --add-subgids 100000-165535 spindle",
104106 "loginctl enable-linger spindle",
105105- "mkdir -p /var/lib/spindle/logs && chown -R spindle:spindle /var/lib/spindle",
107107+108108+ # Directories: logs, systemd unit, podman config
109109+ "mkdir -p /var/log/spindle && chown spindle:spindle /var/log/spindle",
106110 "mkdir -p /home/spindle/.config/systemd/user && chown -R spindle:spindle /home/spindle/.config",
111111+112112+ # Disable SELinux labels in rootless containers — kernel 6.19 + SELinux prevents
113113+ # mprotect in user namespaces, causing RELRO failures in musl-based containers.
114114+ # Rootless userns isolation is the primary security boundary; labels are defense-in-depth.
115115+ # See: https://github.com/containers/podman/issues/27895
116116+ "mkdir -p /home/spindle/.config/containers && printf '[containers]\\nlabel = false\\n' > /home/spindle/.config/containers/containers.conf && chown -R spindle:spindle /home/spindle/.config/containers",
117117+118118+ # Fix SELinux contexts on home dir (provisioning runs as root, labels end up wrong)
119119+ "restorecon -R /home/spindle",
120120+121121+ # Pull spindle binary from Zot OCI image
107122 "podman pull zot.sans-self.org/infra/spindle:latest && CID=$$(podman create zot.sans-self.org/infra/spindle:latest) && podman cp $$CID:/spindle /usr/local/bin/spindle && podman cp $$CID:/spindle.service /home/spindle/.config/systemd/user/spindle.service && podman rm $$CID && chmod 755 /usr/local/bin/spindle && chown -R spindle:spindle /home/spindle/.config || echo 'WARN: spindle image not available, run make setup-spindle after cluster is ready'",
123123+124124+ # Enable podman socket for rootless container API
108125 "sleep 2 && SPINDLE_UID=$$(id -u spindle) && runuser -u spindle -- env XDG_RUNTIME_DIR=/run/user/$${SPINDLE_UID} DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$${SPINDLE_UID}/bus systemctl --user daemon-reload && runuser -u spindle -- env XDG_RUNTIME_DIR=/run/user/$${SPINDLE_UID} DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$${SPINDLE_UID}/bus systemctl --user enable --now podman.socket || true",
109126 ]
110127