Due macchine, due compiti diversi
L'intera piattaforma solveiAgents — l'orchestratore, quattordici agenti specializzati e, sopra di essi, tre applicazioni verticali già in produzione (MediLog, Survey, Legal) — gira su due macchine virtuali Oracle Cloud Infrastructure (OCI), non una. La divisione non è estetica: rispecchia due esigenze opposte.
Il primo VPS è un'istanza Compute Ampere ARM64 con 24 GB di RAM, in una subnet pubblica della VCN, sempre acceso. Ospita tutto ciò che deve poter rispondere in ogni momento: il reverse proxy, l'orchestratore, i database, e la maggior parte degli agenti — avviati e fermati on-demand da un watcher di inattività, ma sul container host che li ospita, che invece non dorme mai. Il secondo è una GPU NVIDIA A10, in una subnet privata senza alcun indirizzo pubblico, che viene accesa solo quando si ha ddavvero bisogno della potenza di calcolo che l'ARM64 non ha.
Ecco come si dividono i compiti nella pratica, nel dettaglio:
VPS Pubblico
- nginx: reverse proxy e TLS per quattro domini (agents/medilog/survey.solvei.it + legal.solvei.it dietro Nginx Proxy Manager)
- Orchestratore FastAPI + quattro frontend Next.js (piattaforma, MediLog, Survey, Legal)
- Quattordici agenti on-demand + agent-call e agent-whisper, sempre attivi per videochiamate e trascrizioni
- Postgres, Redis (con persistenza AOF), MinIO, Orthanc, HAPI FHIR
- worker (coda arq) per i job pianificati
- Prometheus, Grafana, Loki, Tempo, Alertmanager
- agent-blog (sito statico Astro) e Umami per l'analytics
VPS Privato
- Nessun indirizzo IP pubblico, nessuna esposizione diretta a Internet
- Raggiungibile solo dal VPS pubblico, via IP privato della VCN
- Si accende via IAM Instance Principal quando un agente richiede inferenza pesante
- I dati sensibili restano sempre sul runner LLM Ollama locale
- Un watcher di inattività la ferma da sola; un tetto massimo di uptime la ferma comunque entro poche ore
Cosa succede quando un agente ha bisogno della GPU
Nessun agente parla direttamente con le API di OCI. Quando un task richiede un
modello che non gira comodamente sull'ARM64 chiama il gpu_manager
oppure il servizio equivalente dell'orchestratore usato
per lo start/stop indipendente dal widget GPU dei frontend. Entrambi si
autenticano verso OCI con un Instance Principal: nessuna
chiave API salvata da qualche parte, l'identità della VM pubblica stessa —
autorizzata da un Dynamic Group e da una policy IAM dedicata — è la
credenziale.
Una volta finito il task, la GPU non resta accesa "per sicurezza": un watcher di inattività la ferma da solo dopo un periodo configurabile. E se anche quel meccanismo dovesse fallire — un riavvio dell'agente che azzera un timer in memoria, un bug non ancora scoperto — un secondo controllo indipendente, un tetto massimo di uptime (di default quattro ore), la spegne comunque.
La GPU privata somiglia più a un generatore di emergenza che a un server: sta spenta la maggior parte del tempo, si accende da sola quando il carico normale non basta, e si rispegne senza che nessuno debba ricordarsene — o pagarne il conto.
Cosa fa davvero OCI (e cosa no)
Vale la pena essere precisi, perché è facile immaginare un'infrastruttura cloud come un pacchetto di servizi gestiti — object storage, API gateway, monitoring nativo — quando in realtà la maggior parte di ciò che gira su queste due macchine non è un servizio OCI: è software open source containerizzato gestito da noi. I servizi OCI realmente coinvolti sono solo quattro:
Il reverse proxy è nginx containerizzato — non un Load Balancer OCI: un unico container termina il TLS per quattro domini e instrada per path. Lo storage a oggetti è MinIO self-hosted, S3-compatibile — non OCI Object Storage. Il blog è un sito Astro statico rigenerato da un agente dedicato. E l'intero stack di osservabilità — di cui parliamo tra poco — è Prometheus, Grafana, Loki, Tempo e Alertmanager in container, non il Cloud Monitoring nativo di OCI.
Il motivo è semplice: un'istanza ARM64 Ampere basta a far girare tutto questo comodamente, e tenere lo stack open source ci lascia il controllo completo su dati che, per gli agenti che trattano informazioni sanitarie o legali, non devono mai lasciare la nostra infrastruttura.
Perché la GPU non ha un indirizzo pubblico
La subnet privata non è un dettaglio implementativo: è la scelta di design che rende accettabile tenere accesa, anche solo per pochi minuti, una macchina con un modello LLM che processa richieste reali. Nessuna porta è pubblicata verso Internet sul VPS GPU; l'unico modo per raggiungerlo è passare dal VPS pubblico, via IP privato di VCN, e solo con le credenziali IAM giuste.
La stessa disciplina vale per l'autenticazione utente: Clerk, il provider di identità usato da tutti i frontend, gira in modalità production con la verifica dei JWT centralizzata in un unico modulo condiviso consumato da cinque servizi diversi.
Log, tracce e metriche: sapere cosa succede prima che sia un problema
Log centralizzati
Ogni agente — non solo i tre o quattro "principali" — scrive i propri log su Loki tramite un modulo condiviso.
Tracce distribuite
OpenTelemetry, con esportazione verso Tempo, è ora attivo su quindici
agenti: ogni richiesta porta con sé un traceparent propagato
dall'orchestratore fin dentro l'agente che la serve, così una richiesta lenta
si può seguire end-to-end invece di dover incrociare i log a mano servizio
per servizio.
Metriche e alert
Prometheus "osserva" ogni agente attivo; due metriche pensate apposta per la
supervisione — agent_restarts_total e agent_up —
alimentano una regola di alert dedicata (AgentFlapping, un
agente che si riavvia più di tre volte in dieci minuti) accanto a quella già
esistente sul circuit breaker aperto troppo a lungo. Alertmanager chiude il
giro: prima le regole "scattavano" solo visivamente dentro Prometheus,
senza notificare nessuno.
La reportistica operativa
Concretamente, chi opera la piattaforma guarda due posti. La dashboard
Grafana Solvei Agents Overview, auto-provisionata, con throughput,
latenza p50/p95 ed error rate per servizio. E il pannello /monitoring
nel frontend, con tre sezioni: LiveSection mostra le
richieste in corso in tempo reale (stato "in classificazione" → "in
streaming" → "completata", o "abbandonata" se il client si è disconnesso a
metà); LogViewer interroga Loki per servizio, livello e
periodo senza uscire dal browser; DeployPanel esegue git
pull, build, restart e reload di nginx in streaming, direttamente dalla UI.
Backup e disaster recovery
Un backup pg_dump giornaliero copre l'intero Postgres —
schema per schema: piattaforma, cartella clinica MediLog, dati FHIR, Survey,
Legal, Umami. Accanto, tar in sola lettura per i dati binari che non vivono
nel database: MinIO, Orthanc (studi DICOM), i questionari cartacei
caricati, le wiki generate, i post del blog, i dati di Open WebUI. Una
destinazione rsync offsite è disponibile come opzione, non attivata di
default. Un runbook (scripts/restore.sh) guida il ripristino
passo per passo — per componente, non tutto insieme — con una modalità
dry-run di default che stampa i comandi prima di eseguirli davvero.
Il job di backup gira sulla coda dei job pianificati (il paragrafo successivo), non più come chiamata diretta dentro il processo dell'orchestratore: se la coda non risponde, il vecchio percorso diretto resta come rete di sicurezza — per il backup, il rischio di "non l'ha eseguito nessuno" pesa più del rischio di bypassare la coda una volta ogni tanto.
Chi tiene tutto in piedi quando nessuno guarda
Una manciata di meccanismi, tutti indipendenti tra loro, si occupano di tenere la piattaforma coerente senza intervento manuale:
Tre applicazioni verticali, una sola piattaforma
Tutto quello descritto finora non è un esercizio infrastrutturale fine a se stesso: è la base su cui girano tre prodotti verticali reali, che condividono lo stesso orchestratore, lo stesso Postgres, la stessa autenticazione Clerk e lo stesso stack di osservabilità.
Cartella clinica digitale (PHR) — dai dati anagrafici e dagli eventi clinici, cresciuta fino a FHIR R4, OCR con estrazione automatica dei valori di laboratorio, gestione DICOM con visualizzatore OHIF, videochiamate paziente-medico via mediasoup e profili familiari condivisi.
Digitalizzazione di questionari cartacei — pipeline ibrida OMR (riconoscimento ottico dei segni) più un modello vision per i casi dubbi, coda di validazione umana, dashboard statistiche.
Piattaforma legale AI — fork di un progetto open source, integrata con 214 strumenti legali italiani via protocollo MCP (Normattiva, Cassazione, CGUE, calcoli su interessi e onorari, oltre cento modelli di documenti).
Nessuna delle tre ha richiesto una nuova infrastruttura da zero: agganciarsi significa registrare un nuovo agente nel registro esistente, aggiungere uno schema al Postgres condiviso, e beneficiare gratis di tutto quello che questo articolo ha descritto — logging, tracing, backup, watchdog inclusi. È probabilmente la prova più concreta che l'architettura a due VPS non è solo economicamente sensata, ma anche quella che permette di aggiungere un prodotto verticale in settimane, non mesi.
Non serve un cloud enorme, serve un cloud onesto
Il valore di questa architettura non sta nel numero di servizi gestiti OCI che usa — sono deliberatamente pochi — ma nella chiarezza con cui separa "sempre acceso" da "on-demand" e nel lavoro che tiene entrambe le metà coerenti : un log che arriva sempre a Loki, una traccia che attraversa tutti i servizi, un backup che parte anche se la coda che dovrebbe farlo partire non risponde, un agente che si spegne da solo anche quando qualcuno l'ha acceso a mano per sbaglio.
Questa infrastruttura è stata ideata come "palestra tecnologica personale", ma adottando pratiche virtuose derivate da più di 35 anni di esperienza sul campo 🙂 e potrebbe essere una buona base per l'implementazione di progetti diversi. I dati sensibili non lasciano mai la infrastruttura ed utilizzano solo servizi locali. In ogni caso per ridurre la ipotetica superficie di attacco i singoli servizi esposti su internet possono essere attivati/disattivati tramite Nginx Proxy Manager (open source).
Probabilmente per rafforzare ulteriormente la privacy il mio prossimo passo sarà l'implementazione di un servizio privato di posta elettronica e messaggistica basato su soluzioni open source ... direi che è ora di smettere di condividere informazioni private con le big tech 🙂.
Spero che questo articolo ti sia stato utile se stai valutando un'architettura simile per i tuoi progetti.