I siti si preparano su web1, che è un server di sviluppo: in produzione vanno su un server di produzione presso un fornitore, con uno o più siti, anche di clienti diversi (ognuno isolato come su web1), (prima Hetzner e DigitalOcean, poi gli altri quando servono), sul dominio scelto dal cliente. La sezione Produzione del menu raccoglie questi server. È in costruzione: oggi ci sono l’elenco dei server con l’aggiunta di un server creato a mano, gli strumenti firmati, la messa in sicurezza, la pubblicazione dei siti con l’apertura al cambio del DNS, la cassaforte e la guida dei passi. La creazione dei server dalla dashboard arriva nei prossimi passi.
La Guida
La scheda Produzione → Guida mette in fila tutti i passi per portare un sito su un server di produzione nuovo: la preparazione, una volta sola; il server; il collegamento e la messa in sicurezza; la pubblicazione. Per ogni passo dice dove si fa (pannello, PC, server di sviluppo, console del fornitore, DNS) e, quando la dashboard lo sa, a che punto sei: la prova delle notifiche, la chiave di rilascio, gli strumenti da firmare o da rifirmare, la cassaforte aperta o chiusa, lo stato di ogni server. I comandi si copiano con un clic; agli amministratori i passi portano direttamente alla pagina giusta. In fondo, cosa fare quando un passo si ferma. La vedono tutti.

Server e Pubblicazioni
Server elenca i server di produzione gestiti da questo server di sviluppo: fornitore, cliente, regione, indirizzo, numero di siti, stato e costo stimato al mese. Pubblicazioni mostra per ogni cliente i siti pubblicati, su quale server e in che stato (in anteprima, in attesa del DNS, aperto). Le vedono tutti, anche i lettori. Finché non c’è un server, sono vuote.
Aggiungere un server esistente
Un server creato a mano nella console del fornitore si collega alla dashboard in tre passi, da Produzione → Server → Aggiungi un server esistente (solo amministratori):
- Dati del server: nome, cliente, fornitore e regione. Il cliente è chi intesta il server presso il fornitore: l’agenzia, se ospiterà siti di più clienti. La dashboard prepara le chiavi del server: quella di
deploy, per le modifiche, va nella cassaforte; quella diesercizio, per i controlli, resta sul server di sviluppo. - Configurazione d’avvio: un testo da incollare quando si crea il server (in Hetzner «Cloud config», in DigitalOcean «Add initialization scripts»). Crea gli utenti deploy ed esercizio, che accettano solo questo server di sviluppo, e una chiave host provvisoria, con cui al primo collegamento la dashboard riconosce il server giusto. Si vede una volta sola e vale 24 ore.
- Collega il server: con la cassaforte aperta si scrive l’indirizzo IPv4 del server. Parte un lavoro, seguito nella sua pagina.

Il lavoro:
- si collega solo se il server presenta la chiave host provvisoria: un server diverso viene rifiutato;
- installa
site-remoto, lo strumento che sul server esegue soltanto un elenco chiuso di operazioni; - rifiuta un server con l’accesso a password attivo o con accessi SSH di altri: va reinstallato;
- blocca gli accessi: deploy ed esercizio eseguono solo site-remoto, e sudo non permette altro;
- mette una chiave host definitiva al posto di quella provvisoria e ne cancella le copie.
Un cambio degli accessi o della chiave host torna indietro da solo dopo 5 minuti, se la dashboard non riesce a ricollegarsi per confermarlo: un errore non chiude fuori nessuno.
Dopo il collegamento il server è «da mettere in sicurezza»: il passo seguente è la messa in sicurezza, con gli strumenti firmati.
Strumenti firmati
I server di produzione ricevono da questo server di sviluppo i loro script: site-remoto, il bootstrap del profilo di produzione, site.sh, i controlli, i backup e wp-cli. Li installano solo se sono firmati con la chiave di rilascio, che è dell’amministratore: la privata sta nel suo password manager e si usa sul suo PC, mai su un server. Così uno script cambiato sul server di sviluppo, da chiunque, non arriva in produzione senza una firma nuova.

La scheda Produzione → Strumenti (la vedono tutti; preparano e firmano gli amministratori):
- Chiave di rilascio, una volta sola: sul PC
ssh-keygen -t ed25519 -C rilascio -f rilascio, la privata nel password manager, la pubblica sul server di sviluppo in/etc/site-remote/rilascio.pub(da shell). La pagina mostra l’impronta da confrontare con quella del password manager. - Prepara una versione: copia gli script di questo server e ne scrive il manifesto, con lo sha256 di ogni file. Se gli script non sono cambiati dall’ultima versione non ne fa un’altra.
- Firma: «Scarica il manifesto», sul PC
ssh-keygen -Y sign -f rilascio -n site-remoto manifesto.txt, poi si incolla il filemanifesto.txt.signella pagina. Il server di sviluppo verifica la firma con la chiave pubblica, e la verifica di nuovo ogni server di produzione prima di installare.
La tabella «Strumenti sui server» dice quale versione ha ogni server e quali sono da aggiornare.
Mettere in sicurezza
Nella pagina del server, con la cassaforte aperta, Metti in sicurezza chiede il nome Linux dell’amministratore umano, un indirizzo per gli avvisi e, facoltativa, la sua chiave SSH pubblica (diversa da quella dei server di sviluppo; senza, entra solo dalla console del fornitore).

Il lavoro:
- porta sul server gli strumenti dell’ultima versione firmata e la chiave pubblica di rilascio;
- applica il profilo di produzione: SSH solo da questo server di sviluppo e dagli amministratori, firewall che chiude anche i metadati del fornitore ai siti, aggiornamenti automatici con riavvio a un orario suo, PHP, MariaDB, nginx e fail2ban, niente di ciò che serve solo allo sviluppo (dashboard, phpMyAdmin, storia git);
- crea il riferimento dei controlli del server;
- porta l’elenco delle vulnerabilità note, che poi arriva ogni notte;
- prova da qui un elenco breve e fisso di porte (22, 25, 80, 443, 3306, 8080, 8443), una alla volta: mai una scansione.
Se dopo il cambio la dashboard non riesce a ricollegarsi, accessi e firewall tornano come prima entro 5 minuti dalla fine del profilo. La password di sudo dell’amministratore nasce nel lavoro: si vede una volta nella sua pagina, da copiare nel password manager, e resta nella cassaforte leggibile solo con la chiave di deposito.

Rilanciata non cambia nulla e non rigenera la password: serve dopo un intervento a mano. Se da fuori risponde una porta che non dovrebbe, il server passa in «allarmi».

La pagina del server mostra indirizzi, chiave host intera, sistema, strumenti firmati, messa in sicurezza, porte provate da fuori e ultimo controllo. Controlla ora, anche per i lettori, legge lo stato con l’utente esercizio, senza cassaforte. In Gestione, Aggiorna gli strumenti porta l’ultima versione firmata: sul server il controllo accetta da solo i programmi che coincidono con il manifesto firmato, e segnala ogni altro cambio.
Pubblicare un sito
Un sito di sviluppo va su un server messo in sicurezza dalla sua pagina Messa in produzione, con Pubblica il sito… (solo amministratori). Si sceglie il server, si scrive il dominio del cliente e si risponde alla domanda «il dominio serve oggi un sito?»; poi Controlla.
Il controllo preliminare guarda il sito e il server senza cambiare nulla: codice bloccato e uguale all’impronta approvata, nessun allarme nell’ultimo controllo di integrità, niente multisito, dominio libero (non già pubblicato, diverso da quello di sviluppo e che non lo contiene), server raggiungibile, in produzione e con gli strumenti di adesso, la versione di PHP del sito con le sue estensioni, spazio per tre volte file e database. Se una voce è da risolvere la pubblicazione non parte.

Con la cassaforte aperta e il dominio scritto per conferma, Pubblica il sito avvia un solo lavoro:
- una copia del sito sul server di sviluppo, con l’etichetta «prima della produzione», che resta anche oltre le ultime 10 copie;
- l’esportazione, la stessa di La messa in produzione: il dominio di sviluppo diventa quello del cliente nel database e nei file;
- l’invio al server, a pezzi, con l’impronta controllata all’arrivo;
- sul server, il sito nuovo dietro l’anteprima: utente, PHP, database con una password nuova, chiavi e salt nuovi, password nuove per gli amministratori di WordPress, sessioni tolte, codice bloccato e riferimento dei controlli. Se si ferma a metà, il sito incompleto si toglie da solo e si può ripubblicare.
L’esportazione sul server di sviluppo si cancella comunque vada. Alla fine la pagina del lavoro mostra una volta sola le password nuove degli amministratori di WordPress e quella dell’anteprima: sul server resta solo quella dell’anteprima.

DNS e apertura al pubblico
Il sito pubblicato ha una sua pagina, da Produzione → Pubblicazioni: lo stato (in anteprima, in attesa del DNS, aperto), i record DNS da impostare e quelli che il server di sviluppo trova adesso, e la riga per il file hosts del PC, per provare il sito con la password dell’anteprima prima del cambio. I record li cambia il cliente presso il fornitore del dominio; il giorno prima conviene portare il TTL a 300 secondi.
Apri appena pronto, con il dominio scritto, lascia il resto al server: ogni 5 minuti, per 72 ore, controlla se il dominio punta a lui; quando succede chiede il certificato di Let’s Encrypt, toglie l’anteprima e riaccende i motori di ricerca, anche a cassaforte chiusa. Se il DNS punta già al server, apre subito. Richiudi rimette l’anteprima; Annulla l’attesa ferma un’apertura non ancora avvenuta.

La cassaforte
Per creare e gestire i server servono le credenziali dei fornitori e le chiavi SSH. Stanno nella cassaforte, cifrate con age:
- nessuna pagina, comando o registro mostra un valore: si salva, si usa nei lavori, si sostituisce o si revoca;
- a cassaforte chiusa non ne ricavano un segreto né root, né i backup, né una copia del disco;
- la vede e la apre solo un amministratore: non l’amministratore con riserva, non il lettore.

Le due chiavi
La cassaforte si apre con la chiave personale di un amministratore o con la chiave di deposito, quella di riserva. Si generano sul proprio PC con age-keygen, lontano dal server e dall’assistente. Della chiave personale la parte privata (la riga che inizia con AGE-SECRET-KEY-1) va nel password manager; quella della chiave di deposito anche su carta, in un altro posto. Al server arriva solo la parte pubblica, che inizia con age1.
Crearla
Una volta sola, da shell:
sudo site-vault.py init --admin mario --chiave age1…personale --deposito age1…deposito
Il comando stampa l’impronta della cassaforte, SHA256: seguito da 43 caratteri, da salvare nel password manager. La pagina la mostra sempre intera. Se un giorno non coincide, la cassaforte è stata sostituita: non va usata.
Aprirla
Servono la propria password del pannello, la chiave personale, la durata (da 15 minuti a 4 ore) e per cosa: tutti i server, un cliente o un server. Poi:
- si apre solo se negli ultimi 30 giorni una notifica di prova è arrivata (Utenti, «Manda una notifica di prova») e se arriva la notifica dell’apertura: un’apertura che nessuno vede non c’è;
- arrivano come notifica anche ogni apertura non riuscita, chiusura, salvataggio, revoca e cambio d’identità;
- resta aperta solo per chi l’ha aperta, e solo per ciò che ha scelto: per un altro amministratore è chiusa;
- si richiude da sola alla scadenza e a ogni riavvio dell’agente; Chiudi la cassaforte la chiude subito.
Conviene aprirla da un profilo del browser senza estensioni, e chiuderla appena finito.
Credenziali
Aggiungi una credenziale salva il token di un fornitore per un cliente, anche a cassaforte chiusa. C’è una credenziale per fornitore e cliente. Ruota prepara il modulo per il token nuovo, che prende il posto di quello di prima: il vecchio resta in revocati/ e va revocato anche nella console del fornitore. Revoca toglie una credenziale dall’uso. Un token senza scadenza va ruotato entro un anno. Il controllo notturno avvisa delle scadenze: con una nota a 30 giorni, con un allarme a 7. Tra 7 e 30 giorni dopo una rotazione ricorda di revocare la versione vecchia.
I segreti solo deposito, come le password di console e le seconde chiavi dei backup, il server non li sa leggere: si recuperano solo con la chiave di deposito.
Il deposito
Scarica il deposito dà un archivio con i soli file cifrati e le istruzioni: si custodisce fuori dal server, e con la chiave di deposito restituisce ogni segreto anche se il server non c’è più. La pagina dice quando è stato scaricato e quanti segreti sono più nuovi.
Prova il recupero verifica che la chiave di deposito funzioni davvero:
- si scarica
prova-recupero.age, un testo a caso cifrato verso il deposito; - sul proprio PC si decifra con
age -d -i - prova-recupero.age, incollando la chiave di deposito quando age la chiede; - si incolla nella pagina la riga che compare, che inizia con «recupero-».
La chiave di deposito non va mai incollata nella pagina, che la rifiuterebbe. Il controllo notturno ricorda di riscaricare il deposito quando ci sono segreti nuovi, e di rifare la prova dopo 180 giorni.
Chi può aprirla
A cassaforte aperta si aggiunge un altro amministratore del pannello con la sua chiave personale, quella pubblica: la privata l’ha generata lui, sul suo PC. Togliere un amministratore cambia anche l’identità della cassaforte, perché la sua chiave potrebbe aprire copie vecchie. Cambia l’identità si usa anche dopo un’apertura sospetta e una volta l’anno: i segreti si ricifrano, l’impronta cambia e il deposito va riscaricato.
Prova ed esercizio
Oggi la cassaforte è in modalità di prova: contiene solo segreti di prova, e se qualcuno ha sudo senza password sul server lo segnala ma si apre lo stesso. Prima della produzione vera si passa all’esercizio con «Passa all’esercizio…», confermando per scritto. Si può solo se nessuno ha sudo senza password su qualsiasi comando, e porta tre cambiamenti:
- la cassaforte prende un’identità nuova;
- i segreti di prova vanno in
revocati/; - i privilegi del server (file di sudo e membri dei gruppi sudo, sshadmins, docker, siteagent, adm) diventano quelli attesi.
Da lì, se cambiano, la cassaforte non si apre e, se è aperta, si chiude subito con una notifica. Un cambio voluto si riapprova solo da shell.
Sorvegliata dal server
Il controllo del server tiene nel riferimento le chiavi pubbliche della cassaforte e i programmi in /usr/local. Chi sostituisce la chiave della cassaforte riceverebbe i segreti salvati dopo: per questo un loro cambio dalla dashboard non si accetta. Si verifica l’impronta e si accetta solo da shell.
Da shell
sudo site-vault.py status # stato, impronta e interblocco, mai i valori
sudo site-vault.py salva api.hetzner.studio-bianchi --tipo token --fornitore hetzner --cliente "Studio Bianchi"
# chiede il valore senza mostrarlo
sudo site-vault.py revoca api.hetzner.studio-bianchi
sudo site-vault.py rekey # identità nuova: chiede la chiave personale senza mostrarla
sudo site-vault.py amministratore aggiungi marco --chiave age1…
sudo site-vault.py esercizio --conferma # passaggio all'esercizio
sudo site-vault.py attesi --conferma # in esercizio: riapprova i privilegi dopo un cambio voluto
sudo site-vault.py deposito /root/deposito.tar.gz
sudo site-remote.py list # server e siti pubblicati
sudo site-remote.py controlla prod-studio-bianchi # stato di un server, con l'utente esercizio
sudo site-remote.py strumenti stato # chiave di rilascio e versioni
sudo site-remote.py strumenti prepara # versione nuova, se gli script sono cambiati
sudo site-remote.py strumenti manifesto 20261005-151200 > manifesto.txt
sudo site-remote.py strumenti firma 20261005-151200 < manifesto.txt.sig
sudo site-remote.py indice # elenco delle vulnerabilità ai server messi in sicurezza
sudo site-remote.py controlli prod-studio-bianchi studio-bianchi.it studio-bianchi.esempio.it # prima di pubblicare
sudo site-remote.py sito studio-bianchi.esempio.it # stato sul server e DNS visto da qui
sudo site-remote.py apertura studio-bianchi.esempio.it arma # apre appena il DNS punta al server