Files
PythagorasGoal/docs/diary/2026-07-09-traefik-cert-book-offline.md
T
Adriano Dal Pastro b691f48f43 docs(diary): incident 2026-07-09 — "BOOK LIVE conto offline" = cert Traefik di default
Traefik auto-upgrade (latest+Watchtower -> 3.7.7) ha scartato il resolver ACME
per acme.json a 660 (3.x pretende 600) -> cert self-signed su tutto il VPS ->
DeribitRead SSLError -> book online=False. Zero trade persi (target flat, gate
di sicurezza OK). Fix: chmod 600 acme.json + restart; pin traefik:3.7 nel compose.
Diario con diagnosi, verifica end-to-end e runbook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 20:09:41 +00:00

5.5 KiB

2026-07-09 — Incident infra: "BOOK LIVE conto offline" = cert Traefik di default (non un problema del conto)

Tipo: incident operativo (infra VPS), non ricerca. Nessun edge, nessun cambio a strategie/pesi/config di trading. Documentato qui perché ha bloccato la lettura del conto del book live e ha prodotto l'alert Telegram ⚠️ BOOK LIVE — conto offline.

Sintomo

Alert dal cron_book orario (scripts/live/book_execute.py --execute):

⚠️ BOOK LIVE — conto offline
  nota: salto l'esecuzione, non opero a cieco

Nel log (logs/cron_book.log) le run recenti mostravano conto non leggibile (offline) -> stop, non eseguo a cieco. 10 run offline su 382 totali → regressione recente, non uno stato storico.

Diagnosi (catena completa)

Il book legge il conto Deribit mainnet in sola lettura via Cerbero MCP (DeribitRead, src/live/deribit.pyhttps://cerbero-mcp.tielogic.xyz). book_report marca online=False quando DeribitRead.mark_price(BTC) lancia. Riproduzione diretta:

mark_price BTC: FAIL -> SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] self-signed certificate

Il proxy presentava il cert self-signed di default di Traefik (CN = TRAEFIK DEFAULT CERT, notBefore Jul 9 19:55 2026) al posto del vero Let's Encrypt. curl -k → HTTP 401 (backend cerbero-mcp healthy, routing OK): solo la presentazione del cert TLS era rotta. requests verifica il cert → fallisce → online=False → il book salta l'esecuzione (comportamento di sicurezza corretto: non opera a cieco).

Causa a monte (log di avvio Traefik, 11:37:16Z, container traefik-traefik-1):

ERR The ACME resolve is skipped from the resolvers list
    error="unable to get ACME account: permissions 660 for /acme.json are too open, please use 600"
    resolver=mytlschallenge
→ (a cascata) Router uses a nonexistent certificate resolver certificateResolver=mytlschallenge
  routerName=cerbero-mcp@docker   [+ ~14 altri router: git, vault, portfolio, budget, cerbero-bite, ...]

Sequenza:

  1. Immagine traefik:latest + Watchtower (com.centurylinklabs.watchtower.enable=true) → auto-upgrade a Traefik 3.7.7 con restart alle 11:37 di oggi.
  2. Traefik 3.x rifiuta acme.json con permessi più larghi di 600; il file era 660 (-rw-rw---- root:adriano) → resolver mytlschallenge scartato.
  3. Tutti i ~15 router che lo referenziano → "nonexistent certificate resolver" → Traefik serve il cert di default self-signed a ogni host HTTPS del VPS (non solo cerbero-mcp).
  4. I cert veri erano già dentro acme.json (14 domini, incl. cerbero-mcp.tielogic.xyz) → nessuna ri-emissione necessaria, zero rischio rate-limit Let's Encrypt.

Impatto

  • VPS-wide: ogni servizio HTTPS dietro Traefik serviva un cert invalido (warning browser, fallimento di ogni client che verifica il TLS). Non solo il trading.
  • Trading: nessun trade perso. Target del book flat (TP01/SKH01 risk-off) + conto reale ~$598 (non finanziato al livello nominale): anche online il book avrebbe fatto HOLD. Il doppio gate di sicurezza ha lavorato come previsto.

Fix

Immediato (eseguito dall'utente):

sudo chmod 600 /opt/docker/traefik/acme.json
docker restart traefik-traefik-1

Il resolver ricarica i cert già presenti in acme.json e li ripresenta subito.

Durevole (pin dell'immagine, /opt/docker/traefik/docker-compose.yml):

-    image: "traefik"        # = traefik:latest → Watchtower salta ai major (causa dell'incident)
+    image: "traefik:3.7"    # Watchtower resta su 3.7.x: patch sì, salto a 3.8+ breaking no

Applicato con docker compose up -d (container ricreato su traefik:3.7, 20:05:05Z).

Verifica (end-to-end, post-fix)

Check Risultato
acme.json perms 600
Cert cerbero-mcp.tielogic.xyz issuer Let's Encrypt (fino 2026-09-27)
Traefik log nessun ACME resolve is skipped / too open
Container image traefik:3.7 (running)
DeribitRead.mark_price BTC 63.193 / ETH 1.746
book_report.online True · eq_basis=mainnet USDC · real_equity=$598.06 · pos_error=None

Lezioni

  • traefik:latest + Watchtower = auto-upgrade non deterministico. Un bump di major (qui il giro di vite sui permessi di acme.json) diventa un'interruzione TLS di tutto il VPS senza intervento umano. Pinnare la minor (3.7) rende i restart prevedibili pur ricevendo le patch.
  • Traefik 3.x pretende acme.json a 600 (non solo warning: scarta il resolver). Se il file è group/other-readable, tutti i router cadono sul cert di default.
  • Il gate online del book ha fatto il suo lavoro: un problema infra di lettura non ha prodotto ordini a cieco. L'alert "conto offline" va letto prima come possibile problema di connettività/cert al Cerbero MCP, non del conto Deribit.
  • Runbook rapido per "BOOK LIVE conto offline":
    1. python -c "from src.live.deribit import DeribitRead; DeribitRead().mark_price('BTC-PERPETUAL')" → se SSLError/CERTIFICATE_VERIFY_FAILED è il cert del proxy, non il conto.
    2. openssl s_client -connect cerbero-mcp.tielogic.xyz:443 -servername cerbero-mcp.tielogic.xyz | openssl x509 -noout -issuer → se TRAEFIK DEFAULT CERT, Traefik non serve il cert reale.
    3. docker logs traefik-traefik-1 | grep -iE "ACME resolve is skipped|too open|nonexistent" → conferma resolver scartato; controlla stat -c %a /opt/docker/traefik/acme.json (deve essere 600).

Nessun file di trading toccato; config/live.json, sleeve e pesi invariati.