16. Deployment: rootless podman units for one server, a Helm chart for Kubernetes#

Date: 2026-10-19 (#5, #24)

Status#

Accepted. Partly superseded by 18. Single-server installs listen on a Unix socket, reached only through Tailscale Serve for the single-server listener: new installs listen on a Unix socket and publish no port.

Context#

The goal was a home k3s cluster, but a canary on a single VPS was needed first, and other people should be able to run scrap with either. The design assumes exactly one writer and a loopback-only listener.

Decision#

  • One multi-arch (arm64, amd64) container image runs everything; CI builds it and the chart.

  • Single server: deploy/install.sh installs rootless podman systemd user units for a dedicated user: the service, a gated backup timer with safe retention (only run-named directories are ever deleted), a gc timer, and (added with 20. Text enrichment: Claude tags, summarises and relates text pages, apart from the text) a nightly timer for related pages (scrap-enrich-related, which runs scrap enrich --related in the service’s container). As first decided, the container publishes only to 127.0.0.1 and Tailscale Serve fronts it; that is now the SCRAP_LISTEN=tcp choice, kept for env files written before 0018, while SCRAP_LISTEN=socket (the default of a new env file) publishes no port. Docker works but is not the primary path. Updates restart onto a new image and pass ingest settings through.

  • Kubernetes: a Helm chart with exactly one replica and strategy Recreate, a restricted Pod Security profile (uid 10001, read-only root, no capabilities), no service-account token, a PVC kept on uninstall, nightly CronJobs for backup, gc and (with ingest) the related-pages pass, and an optional NetworkPolicy and Ingress. The Tailscale operator is the recommended exposure. Argo CD notes are included.

  • Restore is a CLI command that works from a read-only backup.

Consequences#