Skip to content

Lana (VPS)

The cloud VPS. Public IP 66.179.210.123, SSH-reachable at the vps host alias. Also on the tailnet as vps1 (100.115.215.23) — the only host in the tailnet that also offers itself as a Tailscale exit node.

  • ~7.7 GB RAM, shared across every service below — worth keeping in mind before adding anything heavy.
  • Docker Compose for everything, one directory per service, all defined in the docker-infra repo. Pushing to main deploys automatically via Gitea Actions (SSH over Tailscale, git pull, docker compose up -d per service) - no manual step on the host. See that repo’s own README for the full workflow breakdown, including the one exception: monitoring deploys to Pam instead, since that’s where Grafana/InfluxDB actually run. A second exception is gitea-runner: it’s in Compose like everything else, but deliberately left out of the deploy loop, because recreating the runner would kill the job running the deploy. Deploy it by hand.

Every image is pinned to an exact version, or to a digest where the running build has no matching release tag (Windmill and Open WebUI both track :main). Nothing floats on :latest or :main any more, and pull_policy: always is gone from Windmill — before that, every push to docker-infra silently upgraded Windmill to whatever had just been built upstream.

Upgrades are proposed by the update-agent, a scheduled Gitea Actions workflow. It compares each pin against its registry, has Claude read the release notes in between against the service’s own compose file, and pushes a summary to ntfy. It is report-only: it applies nothing. Major-version jumps are never proposed automatically — those are planned migrations (a Postgres dump/restore, MySQL 8.4 → 26) and are reported separately.

Everything public-facing goes through one of two paths:

  1. Docker apps behind a Cloudflare Tunnel — Gitea, LiteLLM, Open WebUI, Leantime, FlowViz, Windmill, Authentik, knowledge-mcp, and a few smaller services. No inbound ports are open for any of these; the Tunnel connects out to Cloudflare, and Access gates who can reach them.
  2. Static sites via Cloudflare Pages — spelvin.dev itself (this wiki’s landing page) and nothingwilts.com are not Docker containers here at all; they build and deploy straight to Cloudflare Pages from their own Gitea repos via Actions. Lana doesn’t serve their traffic.

There used to be a legacy path here too: a few services sat behind an on-box Caddy + Authelia SSO stack instead of the Tunnel. That’s gone now

  • the migration to Cloudflare Access is fully done, not partial. See Services for how that was confirmed, the current per-app auth model, and what’s been retired along the way (Outline, Plane, n8n, Jupyter, and Caddy/Authelia themselves).

Full current service list, ports, and auth model: Services.