tunnel-sync — declarative routing (cloudflared + Caddyfile)¶
⚠️ Histórico:
tunnel-sync.pyfue reemplazado porhomelab-ctl.py(ver services-routing). Se conserva como referencia.
/home/monxas/scripts/tunnel-sync.py
Reconcilia las labels tunnel.* de containers Docker con:
- cloudflared tunnel ingress — siempre formato unificado https://192.168.0.208:443 + noTLSVerify + originServerName
- Caddyfile — bloques dentro de # BEGIN tunnel-sync managed ... # END (no toca lo de fuera)
- Sablier middleware opcional con tunnel.lazy=true
Bloques manuales fuera de la sección managed se respetan (e.g., los hostnames lazy añadidos a mano).
Comandos¶
python3 ~/scripts/tunnel-sync.py status # ver desired vs estado actual + colisiones
python3 ~/scripts/tunnel-sync.py sync # aplicar (pregunta confirmación)
python3 ~/scripts/tunnel-sync.py sync --yes # aplicar sin confirmación
python3 ~/scripts/tunnel-sync.py remove HOST # quitar HOST de tunnel + Caddyfile managed
Labels¶
| Label | Required | Default | Notas |
|---|---|---|---|
tunnel.hostname |
sí | — | FQDN. Comma-sep para varios hostnames apuntando al mismo container (e.g., krawl). |
tunnel.port |
no | primer puerto host publicado | Puerto host del container. |
tunnel.lazy |
no | false |
Si true, mete sablier middleware. |
tunnel.lazy.names |
no | nombre del container | Comma-sep, containers que sablier debe arrancar juntos. |
tunnel.lazy.theme |
no | shuffle |
ghost / hacker-terminal / matrix / shuffle. |
tunnel.lazy.session_duration |
no | 30m |
Tiempo idle antes de parar. |
tunnel.lazy.display_name |
no | nombre del container | Texto en la waiting page. |
Ejemplos¶
Servicio simple¶
Servicio lazy (Sablier)¶
services:
paperless:
image: paperlessngx/paperless-ngx
ports:
- 8000:8000
labels:
- tunnel.hostname=paperless.monxas.casa
- tunnel.lazy=true
- tunnel.lazy.names=paperless,paperless-db,paperless-redis
- tunnel.lazy.display_name=Paperless
paperless-db:
image: postgres:16
paperless-redis:
image: redis:7
Multi-hostname (krawl honeypot)¶
services:
krawl:
labels:
- tunnel.hostname=admin.monxas.casa,panel.monxas.casa,login.monxas.casa
- tunnel.port=5050
Workflow nuevo servicio¶
- Añadir labels al
compose.yamldel stack. docker compose up -dpara que el container arranque con las labels.python3 ~/scripts/tunnel-sync.py statuspara ver el cambio detectado.python3 ~/scripts/tunnel-sync.py syncpara aplicar (tunnel + Caddyfile + reload).
Garantías¶
- Idempotente:
synccon mismas labels no hace cambios. - Caddyfile validate tras escribir: si falla, revierte automáticamente al backup.
- Backup Caddyfile en
Caddyfile.bak-<timestamp>antes de cada cambio. - Tunnel API: PUT solo si hay drift detectado.
- Restart vs reload Caddy: si el sync introduce sablier middleware nuevo, hace
compose down + up(el plugin Sablier cachea estado ycaddy reloadno lo recoge). Resto de cambios usancaddy reload.
Colisiones¶
status reporta hostnames que tienen bloque manual fuera de la sección managed. sync los elimina y los regenera dentro (migración one-time, idempotente desde entonces).
Troubleshooting¶
| Problema | Solución |
|---|---|
❌ Caddyfile validation failed; reverted |
Revisa la última edición + label malformada. Backup en Caddyfile.bak-*. |
Status muestra container con no published port |
Añade tunnel.port=<host_port> o publica el puerto en compose. |
| Tunnel drift no se aplica | Verifica CF_API_TOKEN en .env y permisos Account:Cloudflare Tunnel:Edit. |
| Cambios sablier no surten efecto | Sablier plugin cachea: cd ~/stacks/reverse-proxy && docker compose down && up -d. |
Anteriormente¶
tunnel-sync.sh (bash, 428 líneas, 2026-01) — emitía ingress directo http://208:port, contradice arquitectura unificada. Movido a .deprecated-20260425 el día del replace. Si necesitas referencia:
/home/monxas/scripts/archive-20260428/tunnel-sync.sh.deprecated-20260425.
Reference¶
- Arquitectura completa → services-routing.md