Roadmap infrastruttura dedicata
Step operativi per rendere Obelica una piattaforma autonoma per progetti cliente
Questa roadmap traduce l'audit del 2026-07-01 in lavoro operativo.
Obiettivo strategico: ridurre e poi rimuovere la dipendenza da Vercel, Neon e servizi equivalenti, mantenendo pero' affidabilita, rollback e documentazione superiori al modello precedente.
Principi
- Una app alla volta: niente migrazioni massive di DNS, DB o storage.
- Prima evidenza, poi cambio: ogni decisione deve avere check ripetibili.
- Ogni cliente ha un contratto operativo: domini, DB, storage, cron, backup, deploy, rollback.
- Managed e self-hosted vanno dichiarati: DigitalOcean Managed Postgres puo essere un passaggio intermedio, non va confuso con infrastruttura DB proprietaria.
- La documentazione e' parte del deploy: se cambia lo stato reale, cambia Fumadocs.
Mappa priorita
| Priorita | Tema | Perche conta |
|---|---|---|
| P0 | Stato reale e sicurezza verificabile | Non si migra produzione se non si puo provare il perimetro |
| P1 | App contract | Ogni app deve essere noiosa da deployare, monitorare e ripristinare |
| P1 | Cron contract | Le automazioni clienti devono avere stato, log e alert |
| P1 | DB decision | Uscire da Neon richiede una scelta esplicita su Postgres managed o self-hosted |
| P2 | Healthcheck e risorse | running non basta per dire healthy |
| P2 | CI/CD e rollback | Sostituisce il valore operativo oggi dato da Vercel |
| P2 | Osservabilita | Serve storia, non solo check puntuale |
| P3 | DR/HA | Necessario per clienti critici e RTO/RPO migliori |
Phase 0 - Truth and evidence
Stato: da fare subito.
Step
- Aggiornare
current-statecon snapshot 2026-07-01. - Aggiornare pagine app/Traefik con domini production gia presenti sul VPS.
- Correggere
operations/cron-jobscon crontab reale. - Tenere navigazione Fumadocs completa via
meta.json. - Creare un comando o runbook per produrre evidenza Cloud Firewall.
- Eseguire e salvare evidenza mensile per:
sshd -T;ufw status numbered;fail2ban-client status sshd;- DigitalOcean Cloud Firewall inbound rules.
Definition of done
- Fumadocs mostra audit e roadmap.
- Nessuna pagina operativa importante resta fuori navigazione.
current-statenon contraddice crontab, router e backup reali.- Esiste una procedura per provare che SSH e' limitato a IP fidati.
Phase 1 - App contract
Stato: priorita alta.
Ogni app cliente deve avere una scheda unica con campi obbligatori.
Campi scheda app
| Campo | Obbligatorio | Note |
|---|---|---|
| Repo | si | path e branch production |
| Stack | si | Next/Astro/Vite/static/monorepo |
| Container | si | nome container e compose path |
| Domini staging | si | *.vps.obelica.com |
| Domini production | si | apex, www, sottodomini |
| DNS owner | si | Vercel, DO, Wix, registrar |
| DB | si | none, DO managed, self-hosted |
| Storage | si | none, Spaces, Cloudinary, legacy Blob |
| Cron | si | job, schedule, timeout, allow-failure |
| Secrets | si | solo nomi/categorie, mai valori |
| Backup | si | cosa viene salvato e come si ripristina |
| Smoke test | si | endpoint e codici attesi |
| Rollback | si | DNS, container, DB, storage |
Step
- Creare template
content/docs/services/apps/<app>.mdxo sezione equivalente. - Compilare prima le app gia in produzione VPS:
tulpa-studio;ottica-style.
- Compilare poi app con DB e cron:
wash-dog-ferrara;sonja-trekking;macelleria;alessandro-zucchini.
- Compilare infine siti statici/senza DB.
Definition of done
- Ogni app ha una scheda production/staging.
obelica deploy liste docs raccontano la stessa realta.- Ogni cutover DNS punta a una scheda app completa.
Phase 2 - Cron contract
Stato: critico per uscire da Vercel Cron.
Problema attuale
I cron applicativi sono attivi via crontab e script shell, ma lo stato non e' ancora modellato come piattaforma: non c'e un registro per-job con ultimo run, durata, exit code, output sintetico e policy alert.
Step
- Allineare docs al crontab reale.
- Portare ogni job sotto control plane Rust:
obelica cron list;obelica cron run <job>;obelica cron status.
- Salvare per ogni run:
- timestamp start/end;
- exit code;
- durata;
- output sintetico;
- app/container target;
- alert inviato si/no.
- Convertire crontab a chiamate control plane, non script diretti.
- Definire
allow-failuresolo dove e' intenzionale e documentato. - Aggiungere alert su job critici falliti.
Definition of done
- Un cron fallito genera stato consultabile e, se critico, alert.
- Il bot Telegram mostra stato cron.
- Nessun job production usa
|| truesenza motivazione documentata.
Phase 3 - Database platform
Stato: decisione strategica aperta.
Scelta A - DigitalOcean Managed Postgres come interim
Vantaggi:
- meno rischio operativo immediato;
- backup e patch gestiti;
- uscita da Neon gia quasi completata.
Obblighi:
- documentare che non e' ancora DB self-hosted;
- per-app roles e least privilege;
- backup logici Obelica indipendenti dal managed provider;
- restore test periodico;
- monitoraggio connessioni e storage.
Scelta B - Postgres self-hosted Obelica
Vantaggi:
- massimo controllo;
- costo prevedibile;
- infrastruttura realmente personale.
Obblighi minimi prima della produzione:
- cluster Postgres dedicato, non mischiato a Forgejo;
- TLS e autenticazione per-app;
- ruoli separati per app e migration user;
- backup fisici o logici con PITR se richiesto;
- restore test automatico;
- monitoraggio storage, lock, connessioni, slow query;
- piano upgrade Postgres;
- runbook incidenti DB;
- pooler se le app lo richiedono;
- criterio chiaro per dati cliente critici.
Step consigliato
- Mantenere DigitalOcean Managed Postgres per i cutover gia in corso.
- Progettare un laboratorio Postgres self-hosted non production.
- Migrare una app non critica come prova.
- Fare restore drill.
- Solo dopo, decidere se spostare app production.
Phase 4 - Health, resources and security hardening
Stato: alta priorita.
Step
- Aggiungere endpoint
/healthzo equivalente alle app dinamiche. - Aggiungere Docker healthcheck per app e servizi interni.
- Estendere
obelica healthper distinguererunningdahealthy. - Aggiungere resource policy:
- memoria per Forgejo e app dinamiche;
pids_limit;- restart alert se un container flappa.
- Valutare
read_only: trueper static app nginx. - Introdurre Docker socket proxy per Traefik e bot.
- Ridurre privilegi del runner Forgejo docs o isolarlo per scope.
Definition of done
- Un'app rotta non passa solo perche il processo e' running.
- Un singolo container non puo saturare tutto il droplet senza alert.
- I componenti che leggono Docker socket hanno permessi minimi.
Phase 5 - CI/CD and release model
Stato: necessario per sostituire Vercel come esperienza operativa.
Step
- Standardizzare workflow Forgejo per build/test per ogni app.
- Definire artifact immagine con tag stabile:
- app;
- commit SHA;
- timestamp;
- environment.
- Aggiungere smoke test automatico post-deploy.
- Salvare ultimo deploy riuscito per rollback.
- Creare comando:
obelica app rollback <app>.
- Aggiungere scansione minima:
- lint;
- test se presenti;
- audit dipendenze;
- build Docker.
Definition of done
- Un deploy non dipende da passaggi manuali ricordati a memoria.
- Ogni release e' identificabile e rollbackabile.
- Il valore operativo di Vercel Deployments viene sostituito da Forgejo + Obelica.
Phase 6 - Observability
Stato: oggi base, da rendere piattaforma.
Step
- Rimuovere duplicazione
monitor.logse confermata. - Aggiungere metriche storiche:
- CPU/RAM/swap/disco;
- container memory/CPU;
- status endpoint;
- durata cron;
- stato backup.
- Aggiungere dashboard privata via tunnel.
- Definire SLO minimi per app production.
- Creare pagina incidenti per ogni evento production.
- Aggiungere alert multi-canale solo dopo avere stabilizzato i segnali.
Definition of done
- Si vede se un problema e' improvviso o trend.
- Ogni app production ha uptime e cron status consultabile.
- Gli alert sono pochi, utili e collegati a runbook.
Phase 7 - Backup, restore and disaster recovery
Stato: buono, con gap mirati.
Step
- Definire retention remota su Spaces.
- Cifrare
repos.tar.zsto motivare formalmente perche resta in chiaro. - Automatizzare restore verification periodica su droplet temporaneo o ambiente isolato.
- Definire RTO/RPO per classi cliente.
- Documentare rebuild completo di
obelica-prodda backup. - Tenere runbook DNS rollback per ogni app production.
Definition of done
- Un backup non e' solo verificato, e' periodicamente ripristinato.
- Si sa quanto tempo serve a tornare online.
- I dati cliente hanno RPO dichiarato.
Phase 8 - Scale-out
Stato: non urgente, ma da progettare prima del sovraccarico.
Trigger per aprire questa fase:
- piu app dinamiche critiche sullo stesso droplet;
- Forgejo o una app consumano stabilmente oltre il 60% RAM;
- RTO richiesto inferiore al tempo di restore manuale;
- necessita di separare staging e production;
- DB self-hosted production con requisiti forti.
Possibili direzioni:
- droplet separato per database;
- droplet separato per app production;
- droplet staging separato;
- registry immagini privato;
- standby restore caldo o tiepido;
- object storage policy piu rigida;
- backup cross-region.
Sequenza consigliata
- Chiudere Phase 0.
- Completare schede app per
tulpa-studioeottica-style. - Sistemare cron contract prima di migrare app con automazioni reali.
- Decidere il modello DB.
- Aggiungere healthcheck e resource policy.
- Estendere CI/CD app per app.
- Portare osservabilita e DR a livello clienti.
Stato operativo da tracciare
| Workstream | Primo artefatto |
|---|---|
| App contract | schede tulpa-studio e ottica-style |
| Cron contract | obelica cron status o file stato per-job |
| DB platform | decision log managed vs self-hosted |
| Security evidence | runbook Cloud Firewall/UFW/fail2ban |
| Observability | metriche storiche e dashboard privata |
| DR | retention remota e restore drill schedulato |
Nota finale
La piattaforma deve diventare noiosa: ogni migrazione deve sembrare una checklist ripetibile, non un evento eroico.