Wave 1 indri→ringtail migration: paperless, teslamate, mealie #363

Merged
eblume merged 12 commits from migrate-wave1-ringtail into main 2026-06-03 10:34:01 -07:00
Owner

Migrate paperless, teslamate, and mealie off the OOM-saturated minikube-indri node onto ringtail k3s, shedding ~1.1 GiB of resident load. Second chain in the indri-k8s decommission after immich.

Containers ported to Nix (default.nix), build-verified on ringtail:

  • paperless → wraps nixpkgs paperless-ngx 2.20.15 (pinned unstable); runs as web/worker/beat/consumer
  • mealie → wraps nixpkgs mealie 3.16.0 (forward 4-minor bump, breaking-change reviewed); single gunicorn, SQLite
  • teslamate → from-scratch beamPackages mixRelease (not in nixpkgs); erlang_27+elixir_1_18, npm assets, ex_cldr locales pre-fetched

Data: cold downtime-tolerant cutover. paperless+teslamate postgres dump/restore from quiesced source into a new ringtail blumeops-pg CNPG cluster; mealie SQLite PVC copied. Source DBs untouched until verified (rollback = repoint).

Also: ringtail blumeops-pg cluster + ExternalSecrets scaffold; fixes pre-existing shower version-check drift.

Runbook: docs/how-to/ringtail/migrate-wave1-ringtail.md. Deploy-from-branch + cutover happens before merge; container images rebuilt from main after merge.

Migrate paperless, teslamate, and mealie off the OOM-saturated minikube-indri node onto ringtail k3s, shedding ~1.1 GiB of resident load. Second chain in the indri-k8s decommission after immich. **Containers ported to Nix (default.nix), build-verified on ringtail:** - paperless → wraps nixpkgs paperless-ngx 2.20.15 (pinned unstable); runs as web/worker/beat/consumer - mealie → wraps nixpkgs mealie 3.16.0 (forward 4-minor bump, breaking-change reviewed); single gunicorn, SQLite - teslamate → from-scratch beamPackages mixRelease (not in nixpkgs); erlang_27+elixir_1_18, npm assets, ex_cldr locales pre-fetched **Data:** cold downtime-tolerant cutover. paperless+teslamate postgres dump/restore from quiesced source into a new ringtail blumeops-pg CNPG cluster; mealie SQLite PVC copied. Source DBs untouched until verified (rollback = repoint). **Also:** ringtail blumeops-pg cluster + ExternalSecrets scaffold; fixes pre-existing shower version-check drift. Runbook: docs/how-to/ringtail/migrate-wave1-ringtail.md. Deploy-from-branch + cutover happens before merge; container images rebuilt from main after merge.
Docs-first for the C1 migration of paperless, teslamate, and mealie off
minikube-indri (OOM-saturated, kernel OOM-killer thrashing apiserver)
onto k3s-ringtail. Cold, downtime-tolerant cutover; postgres preserved
via dump/restore from a quiesced source, mealie SQLite PVC copied.
Linked as the next chain from [[migrate-immich-to-ringtail]].

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrap nixpkgs paperless-ngx in dockerTools.buildLayeredImage, replacing
the s6-overlay Dockerfile build. The package bundles the full OCR/imaging
closure (tesseract, qpdf, jbig2enc, unpaper, pngquant, ocrmypdf, pikepdf)
and nltk data, so the image stays lean. Unlike the s6 image, this runs as
four containers on ringtail sharing one image (web/worker/beat/consumer);
the web wrapper mirrors the NixOS module's granian + PYTHONPATH invocation.

Self-pins nixos-unstable (stable lags at 2.19.6) for paperless-ngx 2.20.15
-- a same-minor forward patch bump from the v2.20.13 Dockerfile build.
Build verified on ringtail (nix-build, exit 0, version assert passes).

Also fixes pre-existing shower version drift (service-versions 1.1.2 ->
1.1.3 to match its default.nix) so container-version-check passes; the
paperless service-versions edit widens that check to all containers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Wrap nixpkgs mealie in dockerTools.buildLayeredImage, replacing the
Node+Python Dockerfile build. nixpkgs ships a single `mealie` gunicorn
entrypoint serving the prebuilt frontend, so this is a clean single-
process wrap; the run wrapper mirrors the NixOS module (init_db Alembic
migrations, then gunicorn). DB stays SQLite on the mealie-data PVC.

Self-pins nixos-unstable (stable lags at 3.9.2) for mealie 3.16.0 -- a
forward 4-minor bump from v3.12.0 (the previously-deferred upgrade).
Breaking-change review v3.13-v3.16: no schema breaks, SQLite auto-migrates
forward; remaining changes minor (see service-versions.yaml notes). Source
PVC retained for rollback. Build verified on ringtail (exit 0, assert ok).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
teslamate is not in nixpkgs, so this is a from-scratch beamPackages
mixRelease: an Elixir/Phoenix release with npm-built assets. Replaces
container.py (+ entrypoint.sh, now inlined as the image Entrypoint).

Pins erlang_27 + elixir_1_18 from the shared nixos-unstable rev (teslamate
needs elixir ~> 1.17; stays off the default OTP 28). Source from the forge
mirror, pinned by the v3.0.0 tag commit. Assets build in-release via npm ci
(esbuild + sass are devDeps; esbuild platform binary is optional) + the
custom node scripts/build.js, then mix phx.digest. ex_cldr locale data is
pre-fetched and pointed at via LOCALES to avoid compile-time GitHub
downloads the build sandbox blocks. Version unchanged (v3.0.0). Build
verified on ringtail (exit 0, ~134 MB image).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CNPG Cluster on ringtail to receive the paperless + teslamate databases
migrated off the minikube blumeops-pg via cold pg_dump/pg_restore. Mirrors
the minikube cluster (managed roles eblume/borgmatic/paperless/teslamate,
scram pg_hba) on ringtail's local-path storage, scoped to wave-1 roles
(miniflux + authentik stay put for later waves). Apps reach it in-cluster
at blumeops-pg-rw.databases.svc.cluster.local — same name as on minikube.

Database creation is deferred to cutover: paperless restores into the
bootstrap database; teslamate's DB is created by the eblume superuser at
its cutover (the dump's earthdistance extension is untrusted). The four
ExternalSecrets reuse the same 1Password items as the minikube cluster.
Not yet synced; deploy waits for review. kustomize build verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Staging deployments on ringtail k3s, in parallel with the minikube apps
until per-service cutover. Each uses the Nix image built at 1d4cbbf
(paperless v2.20.15, mealie v3.16.0, teslamate v3.0.0, all -nix tags) and
points postgres at the in-cluster ringtail blumeops-pg.

- paperless: redesigned as web/worker/beat/consumer + redis in one pod
  (Nix image has no s6 supervisor); media on a ringtail-suffixed NFS PV
  (needs a sifaka rule for ringtail).
- mealie: single gunicorn; SQLite PVC (local-path) copied at cutover.
- teslamate: stateless; DATABASE_HOST already in-cluster, unchanged.

ArgoCD apps target ringtail (https://ringtail.tail8d86e.ts.net:6443).
Not synced yet; deploy-from-branch + cutover is the next step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Nix mixRelease strips releases/COOKIE by default and expects
RELEASE_COOKIE at runtime, but teslamate's start script reads the file
and crash-loops without it. teslamate is single-node (no distributed
Erlang exposed beyond :4000), so keeping the build-generated cookie in
the release is the simplest self-contained fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These migrated to ringtail. Set replicas: 0 (prevents resurrecting the old
instances and double-writing the now-ringtail-owned databases) and remove the
tailscale Ingress from each (the names tesla/meals/paperless were handed off
to the -ringtail ingresses at cutover; a re-created minikube ingress would
steal them back). Service/PVC/ExternalSecrets retained for rollback. Manifest
deletion + source-DB drop come in a later decommission PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
eblume merged commit fcac8e5a72 into main 2026-06-03 10:34:01 -07:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
eblume/blumeops!363
No description provided.