blumeops/ansible/roles/caddy/defaults/main.yml
Erich Blume 14ca0160ba Migrate devpi from minikube to indri (launchd) (#341)
## Summary

Devpi was crash-looping under memory pressure on the minikube StatefulSet, breaking the Python toolchain across the repo (`mise run docs-mikado`, `prek`, every `uv pip install`). It moves to indri as a native LaunchAgent.

## What changed

- **New ansible role** `ansible/roles/devpi/`: installs `devpi-server` + `devpi-web` into a uv-managed venv, initializes the server-dir on first run via 1Password root password, runs as a LaunchAgent (`mcquack.eblume.devpi`) bound to `127.0.0.1:3141`. Bootstraps from upstream PyPI (so devpi can install itself on a fresh box).
- **Caddy**: `pypi.ops.eblu.me` now proxies to `http://localhost:3141`.
- **Playbook**: `indri.yml` gains pre_tasks for the root password and the new role.
- **service-versions.yaml**: devpi flipped from `type: argocd` to `type: ansible`.
- **ArgoCD**: removed `apps/devpi.yaml` and `manifests/devpi/`. The in-cluster Application, namespace, and PVC have been deleted.
- **Docs**: new how-to `docs/how-to/operations/devpi-on-indri.md`; `restart-indri.md` lists devpi in the LaunchAgent stop list.

## Already deployed (live on indri)

- Service running: `launchctl list mcquack.eblume.devpi` → PID 53888
- `curl https://pypi.ops.eblu.me/+api` returns 200 
- `mise run docs-mikado` works again 
- 1.0G of cached PyPI data was migrated from the PVC to `~erichblume/devpi/server-dir/`
- Minikube namespace and PVC fully reclaimed

## Test plan

- [ ] `mise run services-check` (after merge)
- [ ] CI workflows that use devpi succeed
- [ ] No regressions in tools that depend on `pypi.ops.eblu.me` (prek, uv-script tasks, dagger pipelines)

## Context

This is the C1 prelude to a planned C2 chain (`mikado/retire-minikube-indri`) to retire minikube on indri entirely. Doing devpi as a standalone C1 was the right call because (a) it was urgent — it was breaking the toolchain — and (b) it shakes out the migration recipe before we commit to a multi-leaf chain.

Reviewed-on: #341
2026-04-29 13:38:36 -07:00

114 lines
3.8 KiB
YAML

---
# Caddy reverse proxy configuration
# Caddy is built from ~/code/3rd/caddy with Gandi DNS and Layer 4 plugins
caddy_repo_dir: /Users/erichblume/code/3rd/caddy
caddy_binary: "{{ caddy_repo_dir }}/bin/caddy"
caddy_config_dir: /Users/erichblume/.config/caddy
caddy_data_dir: /Users/erichblume/.local/share/caddy
caddy_log_dir: /Users/erichblume/Library/Logs
# Gandi API token file (written by ansible, chmod 0600)
# Caddy reads this file for ACME DNS-01 challenges
caddy_gandi_token_file: /Users/erichblume/.config/caddy/gandi-token
# Domain configuration
caddy_domain: ops.eblu.me
# HTTPS port (443 is standard)
caddy_https_port: 443
# Services to proxy
# Format: { name: "service", host: "hostname", backend: "url" }
caddy_services:
# Indri-local services
- name: forge
host: "forge.{{ caddy_domain }}"
backend: "http://localhost:3001"
- name: registry
host: "registry.{{ caddy_domain }}"
backend: "http://localhost:5050"
- name: jellyfin
host: "jellyfin.{{ caddy_domain }}"
backend: "http://localhost:8096"
# K8s services (via Tailscale Ingress)
# Caddy proxies to existing Tailscale endpoints - traffic stays local
- name: grafana
host: "grafana.{{ caddy_domain }}"
backend: "https://grafana.tail8d86e.ts.net"
- name: argocd
host: "argocd.{{ caddy_domain }}"
backend: "https://argocd.tail8d86e.ts.net"
- name: prometheus
host: "prometheus.{{ caddy_domain }}"
backend: "https://prometheus.tail8d86e.ts.net"
- name: loki
host: "loki.{{ caddy_domain }}"
backend: "https://loki.tail8d86e.ts.net"
- name: miniflux
host: "feed.{{ caddy_domain }}"
backend: "https://feed.tail8d86e.ts.net"
- name: devpi
host: "pypi.{{ caddy_domain }}"
backend: "http://localhost:3141"
- name: kiwix
host: "kiwix.{{ caddy_domain }}"
backend: "https://kiwix.tail8d86e.ts.net"
- name: torrent
host: "torrent.{{ caddy_domain }}"
backend: "https://torrent.tail8d86e.ts.net"
- name: teslamate
host: "tesla.{{ caddy_domain }}"
backend: "https://tesla.tail8d86e.ts.net"
- name: immich
host: "photos.{{ caddy_domain }}"
backend: "https://photos.tail8d86e.ts.net"
- name: navidrome
host: "dj.{{ caddy_domain }}"
backend: "https://dj.tail8d86e.ts.net"
- name: homepage
host: "go.{{ caddy_domain }}"
backend: "https://go.tail8d86e.ts.net"
- name: docs
host: "docs.{{ caddy_domain }}"
backend: "https://docs.tail8d86e.ts.net"
- name: cv
host: "cv.{{ caddy_domain }}"
backend: "https://cv.tail8d86e.ts.net"
- name: nvr
host: "nvr.{{ caddy_domain }}"
backend: "https://nvr.tail8d86e.ts.net"
- name: authentik
host: "authentik.{{ caddy_domain }}"
backend: "https://authentik.tail8d86e.ts.net"
cache_policy: spa
- name: ntfy
host: "ntfy.{{ caddy_domain }}"
backend: "https://ntfy.tail8d86e.ts.net"
- name: ollama
host: "ollama.{{ caddy_domain }}"
backend: "https://ollama.tail8d86e.ts.net"
- name: mealie
host: "meals.{{ caddy_domain }}"
backend: "https://meals.tail8d86e.ts.net"
- name: paperless
host: "paperless.{{ caddy_domain }}"
backend: "https://paperless.tail8d86e.ts.net"
- name: sifaka
host: "nas.{{ caddy_domain }}"
backend: "http://sifaka:5000"
# Layer 4 (TCP) services
# Format: { port: external_port, backend: "host:port" }
caddy_tcp_services:
- port: 2222
backend: "localhost:2200" # Forgejo SSH
- port: 5432
backend: "pg.tail8d86e.ts.net:5432" # PostgreSQL (blumeops-pg)
- port: 5433
backend: "immich-pg.tail8d86e.ts.net:5432" # PostgreSQL (immich-pg)
- port: "{{ sifaka_node_exporter_port }}"
backend: "sifaka:{{ sifaka_node_exporter_port }}" # Sifaka node_exporter
- port: "{{ sifaka_smartctl_exporter_port }}"
backend: "sifaka:{{ sifaka_smartctl_exporter_port }}" # Sifaka smartctl_exporter