ACFS Server: un server nostro, a zero euro, per il BGS di Elite Dangerous
Un sito statico aggiornato da GitHub Actions ha retto due settimane. Poi le domande dello squadrone sono diventate più veloci dei dati. In un fine settimana, con Claude Code, è nato un server tutto nostro: ascolta la galassia in diretta, ricorda quello che vede e lo racconta a chi ne ha bisogno.
Due settimane fa ho raccontato l’ACFS BGS Tool, lo strumento con cui l’Alto Comando Flotta Stellare, lo squadrone di Elite Dangerous di cui faccio parte, decide dove lavorare dopo ogni tick. Era un sito statico su GitHub Pages, con i dati scaricati da Spansh ogni mezz’ora. Finiva così: “nella roadmap ci sono un report automatico su Discord dopo ogni tick…”.
Il report è arrivato, ma non nel modo previsto. Nel frattempo è arrivato un server.
- Dove un sito statico non arriva
- Da dove arrivano i dati
- L’ascoltatore, una notte di prova
- Dove farlo girare
- Com’è fatto
- Le cose che non si vedono
- Eventi: il report che è arrivato da un’altra parte
- Un’API per più strumenti
- Come ho lavorato
- E adesso
Dove un sito statico non arriva
Il tool funzionava, e lo squadrone lo usava ogni giorno. Proprio per questo i suoi limiti hanno cominciato a vedersi:
- I cron di GitHub saltano. Sulla carta 48 aggiornamenti al giorno; in pratica GitHub esegue le pianificazioni quando ha tempo, e in certi giorni ne faceva tre.
- Spansh arriva dopo. Si alimenta dal flusso dei giocatori, ma lo elabora con il suo ritmo: un cambio di controllo poteva comparire nel tool ore dopo.
- Il punteggio dei conflitti non c’era. Spansh non lo conserva, EliteBGS ce l’ha ma il suo database cade di continuo (segnalato a mano, rimesso in piedi a mano, giù di nuovo dopo poche ore), Inara blocca le richieste automatiche.
- Le password stavano nel browser. La pagina degli Ordini era protetta da una frase condivisa controllata in JavaScript: un deterrente, non una protezione. Di questo parlo nel prossimo articolo.
La spinta finale è venuta dai Canonn, gli stessi da cui il tool era partito. Il 17 ottobre ci hanno girato un messaggio del loro bot Discord: “Canonn lost control of Lyncis Sector CL-Y d68”, con influenze, architetto e fazione preferita. Leggendo i loro repository pubblici si ricostruiva la catena: dall’11 ottobre avevano un ascoltatore sempre acceso, un database proprio, un’API e una tabella di eventi. La strada c’era, e qualcuno l’aveva già percorsa.
Da dove arrivano i dati
Il gioco non ha un’API pubblica per la galassia. I dati li portano i giocatori: programmi come EDMC leggono il diario di volo (il journal) e, se il pilota lo permette, inviano ogni salto a EDDN, l’Elite Dangerous Data Network. È un flusso pubblico, in tempo reale, a cui chiunque può collegarsi. Spansh, Inara ed EliteBGS si alimentano da lì.
Ogni salto in un sistema popolato porta con sé l’elenco delle fazioni, con influenze, stati e conflitti. E nei conflitti c’è un campo, WonDays, con i giorni vinti da ciascuna parte: il punteggio che cercavamo da settimane. Bastava ascoltare.
L’ascoltatore, una notte di prova
La sera del 17 ottobre, con Claude Code, è nato un ascoltatore in Node, poche centinaia di righe: si collega al flusso con ZeroMQ e tiene solo i messaggi dei circa 390 sistemi in cui è presente la nostra fazione, salvandoli in SQLite. Per quel volume di dati, qualche megabyte all’anno, un database server non serve: Node 24 ha SQLite integrato.
Prime misure: circa 1.300 messaggi al minuto da tutta la galassia, una settantina di salti in sistemi popolati. In una prova di due minuti, tutti i messaggi con un conflitto avevano il punteggio.
Poi l’ho lasciato acceso sul PC tutta la notte, quasi dieci ore. La mattina dopo il confronto con Spansh: nello stesso intervallo Spansh aveva aggiornato 57 dei nostri sistemi, l’ascoltatore 59, compresi tutti i 57 di Spansh. In più, il punteggio di sette conflitti, fra cui l’elezione di Crowfor: 4-0 per noi. Crowfor è passata a Flotta Stellare, e la cronaca della conquista è sul sito dello squadrone.
Una notte di dati ha deciso la cosa più importante: valeva la pena di metterlo su un server.
Dove farlo girare
Il traffico non era un problema: poche decine di utenti e un flusso in entrata gratuito ovunque. Servivano una CPU e un gigabyte di memoria, sempre accesi. Il confronto, fatto con Claude in una sessione di analisi, ha messo in fila VPS a pagamento (OVH, Hetzner, Hostinger), i piani gratuiti dei grandi cloud, le piattaforme a container (che spengono il container quando nessuno lo visita, cioè fermerebbero l’ascoltatore) e un Raspberry Pi a casa.
La scelta è stata Oracle Cloud Free: una macchina ARM a Francoforte, gratis senza scadenza. Con i suoi rischi, scritti nella roadmap prima di cominciare: niente assistenza, istanze gratuite poco usate che Oracle può recuperare, account chiusi senza preavviso. Oracle offre di evitare il recupero passando al piano a consumo, gratis entro i limiti, ma chiedeva un’autorizzazione di 93 euro sulla carta, e ho preferito di no. Il rimedio è un altro: tutto sta in un docker-compose.yml con i backup fuori dalla macchina, quindi ricominciare su una VPS qualsiasi è questione di un’ora o due.
Com’è fatto
Il 18 ottobre il server era in produzione. Oggi sono cinque container:
| Container | Cosa fa |
|---|---|
listener | Ascolta EDDN, salva le osservazioni, ricava gli eventi, manda gli avvisi su Discord |
api | L’API in sola lettura su api.flottastellare.it
|
auth | L’accesso con Discord (nel prossimo articolo) |
tally | La ricezione dei dati del plugin BGS-Tally (anche questa nel prossimo articolo) |
caddy | HTTPS davanti a tutti, con i certificati Let’s Encrypt rinnovati da soli |
Il codice sta in un repository privato, separato da quello del tool. La decisione era precisa: il server deve poter servire anche altro, non solo il BGS.
Il tool legge dall’API fazioni, influenze, stati, controllo e punteggi, quando il server li ha visti dopo Spansh. Se il server non risponde entro sei secondi, usa i dati di sempre. È la regola che ha guidato tutto il resto: un server fermo deve rendere il tool meno fresco, non rotto.
Le cose che non si vedono
Un servizio sempre acceso ha bisogno di cure che un sito statico non chiede. Sono la parte meno spettacolare, ed è quella che mi fa dormire tranquillo:
- Ricollegamento. Con ZeroMQ una connessione può restare aperta senza ricevere più niente. Dopo due minuti di silenzio l’ascoltatore la chiude e ne apre un’altra. L’idea viene dai contatori pubblici dei Canonn, che fanno lo stesso.
- Battito. Ogni cinque minuti l’ascoltatore avvisa healthchecks.io, ma solo se sta davvero ricevendo messaggi. Se il battito manca arriva un’email. Non su Discord: quel canale è dello squadrone, e un avviso tecnico lì sarebbe solo rumore.
- Backup. Ogni notte una copia compressa del database, sette giorni sul server e una nel bucket di Oracle, caricata con un link di sola scrittura. Il ripristino l’ho provato prima di fidarmi.
- Aggiornamento da GitHub. Ogni cinque minuti il server controlla se il ramo principale ha un commit nuovo e, se sì, ricostruisce i container. Se la ricostruzione fallisce, i vecchi restano accesi. Il server legge GitHub con una chiave di sola lettura, e su GitHub non c’è nessuna chiave che apra il server.
-
bgslogs. Un comando per guardare il server dal vivo dopo l’accesso SSH: l’ascoltatore che riceve, gli eventi, gli scarichi da Spansh, gli aggiornamenti. Conbgslogs statola salute di tutto in una schermata, conbgslogs cerca Crowfortutto quello che i servizi hanno scritto su un sistema. Legge soltanto i log, senza toccare niente.
Eventi: il report che è arrivato da un’altra parte
Il report su Discord previsto nella roadmap del tool doveva partire da GitHub Actions, confrontando due scarichi di Spansh. Con il server la strada è cambiata: l’ascoltatore confronta ogni osservazione nuova di un sistema con la precedente e ne ricava gli eventi. Controllo preso o perso, conflitto in arrivo, iniziato o finito, con vincitore e punteggio, la nostra fazione entrata o uscita da un sistema, influenza sotto la soglia della ritirata.
Quelli che ci riguardano partono come riquadri colorati nel canale del BGS dello squadrone, pochi secondi dopo il salto del giocatore che li ha rivelati, invece che ore dopo con Spansh. Su quel canale c’è stata una sola regola: niente rumore. Gli stati globali come l’espansione, per esempio, non si mandano: comparirebbero in tutti i sistemi insieme.
Un’API per più strumenti
Fin dal primo giorno l’API è stata pensata per più utilizzatori, non solo per il tool: versione nel percorso (/v1/…), formato documentato, sistemi identificati dal loro id64 come testo, perché come numero supera gli interi sicuri di JavaScript.
Il secondo utilizzatore è arrivato oggi: la mappa 3D di flottastellare.it. Prima si aggiornava lanciando a mano uno script Python. Ora il server scarica da sé Spansh ogni ora e pubblica /v1/site, con i sistemi già uniti: coordinate, popolazione e servizi delle stazioni da Spansh, controllo e fazioni da chi li ha visti più di recente. La mappa lo legge dal browser; se il server non risponde, ripiega sul file del tool e poi sull’ultima copia salvata. La stessa regola di prima.
Nella prova, il totale degli abitanti dei sistemi controllati è venuto identico, al singolo abitante, a quello della pagina dello squadrone calcolato con lo script vecchio: 25.822.439.448. È il tipo di controllo che dà fiducia nel passaggio.
Come ho lavorato
Lo stesso metodo del tool, con una differenza. Il tool è un sito: se sbaglio, pubblico una pagina sbagliata. Il server è una macchina accesa su Internet, con chiavi, porte aperte e dati dei piloti. Ogni passo è passato da una decisione scritta nella roadmap, con la data e le alternative scartate, prima di diventare codice. Claude Code ha scritto il codice, proposto le architetture e letto i repository dei Canonn per capire come avevano fatto loro. Dove riprendere, riscrivere o lasciare stare l’abbiamo deciso guardando le licenze.
Le decisioni che contano, però, non erano tecniche. Quanto rumore accettare su Discord. Se rischiare la carta di credito con Oracle. Che cosa un ufficiale deve poter fare senza conoscere una password. Sono le domande che un assistente può aiutare a formulare, ma a cui risponde chi conosce lo squadrone.
E adesso
Il server è in produzione da cinque giorni, e ha già cambiato il modo in cui il tool e il sito ricevono i dati. Il prossimo articolo racconta come è diventato dello squadrone: l’accesso con Discord, i dati del plugin BGS-Tally e quello che c’è nella roadmap.
Voi avete un progetto personale che a un certo punto ha avuto bisogno di un server sempre acceso? Dove lo fate girare, e cosa vi ha fatto scegliere?