Come migrare un server su un nuovo VPS
Guida al trasferimento senza interruzioni: ricostruisci il VPS, sincronizza i dati due volte, riduci prima il TTL DNS, verifica e cambia i record solo alla fine.
Migrare un server su un nuovo VPS con un passaggio pianificato e verificato
Per migrare un server su un nuovo VPS, considera il trasferimento come un passaggio pianificato e verificato, non come una semplice copia. Prepara il nuovo server da zero, sincronizza i dati due volte, verifica che il nuovo server funzioni con il proprio indirizzo IP prima di modificare il DNS, quindi cambia i record e lascia in esecuzione il vecchio server finché non hai completato tutte le verifiche. Copiare i dati è la parte più semplice. L’ordine delle operazioni determina se il trasferimento si concluderà senza problemi o con costi elevati.
Questa guida riguarda un unico server Linux che esegue un’applicazione web, un database e un certificato TLS (transport layer security). Questo scenario copre la maggior parte delle configurazioni con un singolo server. Sono coinvolti due host, quindi ogni esempio specifica in un commento su quale host deve essere eseguito. Gli indirizzi appartengono agli intervalli riservati alla documentazione: 198.51.100.10 è il vecchio server, 203.0.113.20 è il nuovo server.
Leggi l’intera procedura prima di iniziare. Il primo passaggio, cioè ridurre il TTL del DNS, deve essere eseguito diversi giorni prima del passaggio effettivo.
Fai l'inventario prima di configurare il nuovo server
Non puoi ricostruire un server che non hai descritto. Dedica un'ora a documentare le funzioni del vecchio server, perché ciò che si rompe dopo una migrazione è sempre ciò che nessuno ha ricordato: un cron job, un'eccezione del firewall o un file di ambiente che si trova fuori dalla directory dell'applicazione.
Esegui questi comandi sul vecchio server e conserva l'output in un percorso accessibile dal nuovo server.
# old server: packages you asked for, not the dependencies they pulled in
apt-mark showmanual > ~/inv-packages.txt
# old server: what runs now, and what starts at boot
systemctl list-units --type=service --state=running --no-pager > ~/inv-services.txt
systemctl list-unit-files --state=enabled --no-pager >> ~/inv-services.txt
systemctl list-timers --all --no-pager > ~/inv-timers.txt
# old server: what is listening, on which address and port
sudo ss -tulpn > ~/inv-ports.txt
# old server: human accounts, skipping the system ones
awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3, $6, $7}' /etc/passwdapt-mark showmanual è l'elenco utile da conservare, perché include tutto ciò che è stato installato come dipendenza. Un dpkg --get-selections completo su un server vecchio di cinque anni restituisce duemila righe e non fornisce alcuna informazione sull'intento.
Le attività pianificate possono trovarsi in due posizioni, quindi controllale entrambe. Un job eseguito solo ogni mese è quello che scoprirai sei settimane dopo la migrazione.
# old server: per-user crontabs, then the system drop-ins
for u in $(cut -d: -f1 /etc/passwd); do sudo crontab -lu "$u" 2>/dev/null | sed "s/^/$u: /"; done
sudo ls -la /etc/cron.d /etc/cron.daily /etc/cron.hourlyControlla quindi gli elementi che non sono normali file: regole del firewall, certificati, database e quantità effettiva di dati da trasferire.
# old server
sudo ufw status verbose # or: sudo nft list ruleset
sudo certbot certificates
sudo -u postgres psql -c '\l' # or: sudo mysql -e 'SHOW DATABASES;'
sudo du -xh --max-depth=1 / | sort -hcertbot certificates stampa il nome di ogni certificato, i domini coperti, la data di scadenza e i percorsi dei file su disco. Questo output costituisce la checklist TLS. du -x resta nello stesso filesystem, quindi non attraversa un volume di backup montato e non restituisce una quantità dieci volte superiore a quella reale.
Due elementi risiedono all'esterno del server e vengono dimenticati ogni volta. Il primo riguarda tutti i soggetti terzi che inseriscono in una allowlist l'indirizzo IP del server: un gateway di pagamento, un database gestito, un relay SMTP o un'API di un partner. Il nuovo server ha un indirizzo diverso, quindi devi aggiungere il nuovo IP a queste allowlist prima del cutover, non dopo. Il secondo riguarda i record DNS che non hai creato direttamente, ad esempio un record MX o un record SPF che contiene il vecchio IP.
Perché ricreare il sistema invece di clonare il vecchio filesystem root
Clonare un intero filesystem root sul nuovo VPS sembra più rapido, e lo è, finché non smette di esserlo. Un filesystem root rimasto in produzione per anni contiene configurazioni modificate manualmente e mai documentate, pacchetti provenienti da un repository che non esiste più e una configurazione di avvio progettata per l'hardware virtuale della vecchia piattaforma. Importi tutto, compreso il motivo per cui stai migrando.
La ricostruzione richiede più tempo il primo giorno, ma riduce i costi ogni giorno successivo. Installa la release corrente, applica il tuo hardening di base, quindi copia solo i dati: la directory dell'applicazione, le configurazioni dei siti, il dump del database, i certificati e gli upload degli utenti. Tutto ciò che non sai spiegare resta fuori. Configura il nuovo server come configureresti qualsiasi altro server, seguendo i primi dieci minuti su un nuovo VPS, quindi aggiungi i servizi uno alla volta dall'inventario e verifica ciascuno prima di aggiungere il successivo.
Quando è opportuno ripristinare un'immagine o uno snapshot
Esiste un'unica eccezione concreta alla ricostruzione. Se il vecchio server non si avvia oppure l'applicazione non può più essere ricompilata dal codice sorgente, il ripristino di un'immagine o di uno snapshot del provider è la scelta più pratica. Questa soluzione ha limiti precisi: funziona all'interno di un singolo provider e spesso soltanto all'interno della stessa famiglia di piani, perché il disco ripristinato si aspetta i dispositivi virtuali e la denominazione di rete di quella piattaforma.
Anche lo snapshot di un sistema in esecuzione presenta lo stesso problema di coerenza di qualsiasi altra copia a livello di file di un database attivo. Considera il ripristino di un'immagine una procedura di recupero, non un piano di migrazione, e leggi perché uno snapshot non equivale a un backup prima di basare un piano su questa soluzione.
Come si spostano i file: rsync tramite SSH
Eseguire rsync dal vecchio server, inviando i dati al nuovo. L'invio è di solito più semplice, perché il vecchio server contiene già i dati e può leggerli tutti tramite sudo.
# old server: dry run first, and read what it says it will do
sudo rsync -aHAX --dry-run --itemize-changes \
-e 'ssh -i /root/.ssh/id_ed25519' \
/srv/app/ deploy@203.0.113.20:/srv/app/
# old server: the real bulk pass
sudo rsync -aHAX --info=progress2 \
-e 'ssh -i /root/.ssh/id_ed25519' \
/srv/app/ deploy@203.0.113.20:/srv/app/I flag sono importanti. -a conserva permessi, timestamp, collegamenti simbolici e proprietà. -H mantiene i collegamenti fisici come tali, invece di espanderli in copie separate. -A copia le ACL POSIX (liste di controllo degli accessi) e -X copia gli attributi estesi. Senza questi ultimi due flag, un file che sembra identico può comportarsi in modo diverso, perché le etichette SELinux e le ACL sono memorizzate negli attributi estesi e nessun altro elemento le registra.
Due dettagli causano la maggior parte dei problemi.
La barra finale determina la destinazione dei dati. /srv/app/ indica il contenuto di quella directory. /srv/app indica la directory stessa. Se si sbaglia, sul nuovo server ci si ritrova con /srv/app/app. L'applicazione si avvia, ma segnala file mancanti, perché i percorsi configurati ora sono più corti di un livello.
In sudo, la tilde indica la directory home di root. Scrivere -e 'ssh -i ~/.ssh/id_ed25519' all'interno di un sudo rsync cerca la chiave in /root/.ssh, non nella propria directory home. Se la chiave non si trova lì, SSH stampa Permission denied (publickey), mentre rsync stampa rsync: connection unexpectedly closed e termina con un codice diverso da zero. Specificare il percorso completo della chiave. Se il messaggio di autenticazione continua a comparire dopo aver corretto il percorso, il problema publickey ha un elenco ristretto di cause e le autorizzazioni delle directory sul nuovo server sono il controllo successivo da eseguire.
Per la proprietà dei file serve una decisione. Eseguendo rsync come root, per impostazione predefinita rsync associa proprietario e gruppo in base al nome. Un file di proprietà di www-data sul vecchio server diventa quindi di proprietà di www-data sul nuovo, anche se l'UID numerico (ID utente) è diverso. Questo è il comportamento desiderato durante una ricostruzione. Aggiungere --numeric-ids solo quando si copia un filesystem i cui account non esistono sulla destinazione. In quel caso, controllare il risultato con ls -ln, perché un file associato a un UID senza un account corrispondente viene visualizzato come semplice numero e l'accesso viene negato a ogni servizio che tenta di leggerlo.
Eseguire la copia principale con alcuni giorni di anticipo, mentre il vecchio server continua a gestire il traffico. Ripeterla tutte le volte necessarie: rsync invia solo ciò che è cambiato, quindi la seconda esecuzione richiede minuti anziché ore. L'esecuzione finale, durante la finestra di cutover, aggiunge --delete, in modo che i file rimossi dal vecchio server vengano rimossi anche dal nuovo.
# old server: final pass, inside the window, after the app has stopped writing
sudo rsync -aHAX --delete --info=progress2 \
-e 'ssh -i /root/.ssh/id_ed25519' \
/srv/app/ deploy@203.0.113.20:/srv/app/--delete rimuove dalla destinazione i file che non esistono più nella sorgente. Di conseguenza, un percorso sorgente errato insieme a --delete può svuotare la directory di destinazione. Eseguire prima --dry-run, ogni volta, senza eccezioni. I trasferimenti lunghi terminano inoltre quando cade la sessione SSH del laptop. Avviarli quindi all'interno di tmux o screen sul vecchio server. Aggiungere --bwlimit=20M se la copia satura il collegamento mentre il vecchio server continua a gestire gli utenti.
Come si sposta il database: un dump nativo
Un database non è una directory di file, anche se può sembrare tale. È un insieme di file, stato in memoria e write-ahead log, coerente soltanto negli istanti definiti dal database stesso. Usate lo strumento previsto dal database.
PostgreSQL richiede 2 dump, perché i ruoli sono globali per il cluster e pg_dump non li include:
# old server
sudo -u postgres pg_dumpall --globals-only -f /var/backups/globals.sql
sudo -u postgres pg_dump -Fc -f /var/backups/appdb.dump appdb# new server: restore in this order
sudo -u postgres psql -f /var/backups/globals.sql
sudo -u postgres createdb -O appuser appdb
sudo -u postgres pg_restore -d appdb --no-owner /var/backups/appdb.dumpSe si omette globals.sql, vengono ripristinate tutte le tabelle, ma nessun ruolo dell'applicazione può leggerle, perché le istruzioni GRANT fanno riferimento a un utente inesistente. -Fc scrive il formato di archivio custom, che solo pg_restore può leggere e che consente di ripristinare in seguito tabelle selezionate. Eseguite il ripristino sulla stessa major version o su una versione più recente. Il ripristino a ritroso, ad esempio da 17 a 16, non è supportato e pg_restore rifiuta l'archivio con un errore di versione non supportata nell'header del file, prima di scrivere qualsiasi dato.
MySQL e MariaDB usano un solo comando, con 4 opzioni che non sono attive per impostazione predefinita:
# old server
sudo mysqldump --single-transaction --routines --triggers --events \
--databases appdb > /var/backups/appdb.sql# new server
sudo mysql < /var/backups/appdb.sql--single-transaction acquisisce uno snapshot coerente senza bloccare le scritture, ma soltanto per le tabelle InnoDB. Una tabella MyISAM nello stesso database viene copiata senza questa garanzia. Controllate quindi i motori di archiviazione prima di considerare affidabile il dump. --routines, --triggers e --events sono disattivate per impostazione predefinita. Un dump semplice ripristina quindi i dati, ma lascia silenziosamente nel database le stored procedure e gli eventi pianificati. Gli utenti del database e i relativi grant si trovano nel database di sistema mysql. Un dump --databases appdb non lo include mai. Ricreate quindi gli utenti sul nuovo server con CREATE USER e GRANT. MariaDB 11 distribuisce lo stesso strumento con il nome mariadb-dump e mantiene mysqldump come collegamento simbolico. Ad agosto 2026, entrambi i nomi funzionano.
SQLite è costituito da un singolo file. Copiarlo mentre l'applicazione esegue scritture produce un file incoerente. Usate il percorso sicuro previsto dal database:
# old server
sqlite3 /var/lib/app/app.db ".backup '/var/backups/app.db'"Indipendentemente dal motore, verificate il dump prima di considerarlo affidabile. Un dump interrotto perché il disco si è riempito viene ripristinato senza segnalare errori, fino al punto in cui è stato troncato.
# old server: a complete mysqldump ends with a line reading "-- Dump completed on ..."
tail -n 3 /var/backups/appdb.sql
# new server: after restore, count rows in a table whose size you know
sudo mysql -e 'SELECT COUNT(*) FROM appdb.orders;'Perché non puoi usare rsync con un database in esecuzione
rsync copia i file uno alla volta. Un database in esecuzione scrive contemporaneamente in più file. Quando rsync raggiunge l'ultimo file, il primo è già obsoleto. La copia contiene pagine corrispondenti a momenti diversi, una condizione che il database non ha mai avuto. Il risultato è un server che rifiuta di avviarsi oppure, nel caso peggiore, un server che si avvia, restituisce risposte corrette per una settimana e poi si arresta quando una query raggiunge infine la pagina danneggiata. Nel frattempo non viene visualizzato alcun avviso.
Esistono due metodi sicuri per trasferire direttamente i file. Arresta il database, esegui la copia e riavvialo: è corretto e semplice, ma il downtime dura quanto la copia. In alternativa, usa lo strumento progettato per copiare fisicamente un server in esecuzione. Per PostgreSQL è pg_basebackup, che si coordina con il server per mantenere la coerenza della copia:
# new server: pull a physical copy from the old one
pg_basebackup -h 198.51.100.10 -U replicator -D /var/lib/postgresql/16/main -X stream -PSono necessari un ruolo con l'attributo REPLICATION e una voce pg_hba.conf corrispondente sul vecchio server. La configurazione richiede quindi più passaggi rispetto a un dump. Questa soluzione è utile quando il database è abbastanza grande da rendere impossibili dump e ripristino all'interno della finestra di manutenzione. Per una normale migrazione tra server singoli, è preferibile il dump.
Ricrea i certificati prima del passaggio, non dopo
Un certificato TLS è associato al nome di dominio, non all'indirizzo IP, quindi il file del certificato può essere trasferito senza problemi. Il rinnovo, invece, non viene trasferito automaticamente. La challenge HTTP-01 predefinita di Certbot chiede all'autorità di certificazione di scaricare un file sulla porta 80 usando il nome per cui viene richiesto il certificato. Finché il DNS non punta al nuovo server, la richiesta arriva al vecchio server e il rinnovo sul nuovo server non riesce.
La prima opzione consiste nel copiare i certificati esistenti e il relativo stato di rinnovo. Restano validi fino alla data di scadenza, indipendentemente dal server che li contiene.
# old server
sudo rsync -aHAX -e 'ssh -i /root/.ssh/id_ed25519' \
/etc/letsencrypt/ root@203.0.113.20:/etc/letsencrypt/Ogni file in /etc/letsencrypt/renewal/ indica il plugin di autenticazione che ha emesso il certificato. Installa quindi lo stesso plugin sul nuovo server, ad esempio python3-certbot-nginx, altrimenti il primo rinnovo fallisce con un messaggio relativo a un autenticatore sconosciuto. Verifica che il rinnovo funzioni prima di dipendere da questa configurazione:
# new server, after DNS has moved
sudo certbot renew --dry-runLa seconda opzione consiste nell'emettere un nuovo certificato sul nuovo server usando la challenge DNS-01. Questa challenge dimostra il controllo del dominio tramite un record TXT e non usa mai la porta 80. Funziona prima della migrazione, mentre il nome risolve ancora verso il vecchio server. È quindi la scelta più semplice se puoi automatizzare il provider DNS. Emissione dei certificati con la challenge DNS-01 descrive la configurazione del plugin e delle credenziali.
In entrambi i casi, verifica quale certificato presenta effettivamente il nuovo server, senza modificare il DNS:
# your laptop
echo | openssl s_client -connect 203.0.113.20:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -dates -issuer-servername invia SNI (server name indication), che consente al web server di selezionare il virtual host corretto. Se lo ometti, ottieni il certificato predefinito per quell'indirizzo IP e una mancata corrispondenza che sembra un problema reale, ma non lo è.
Riduci il TTL DNS nei giorni precedenti al cutover
Il DNS è uno dei punti in cui anche una migrazione pianificata con attenzione può non andare a buon fine, perché il ritardo è intrinseco e non può essere ridotto il giorno del cutover. Un resolver che ha memorizzato nella cache il record A continua a servirlo per l'intera durata del TTL (time to live) ricevuto. Ridurre ora il TTL non ha alcun effetto su un resolver che ha memorizzato il record dieci minuti fa con il valore precedente: mantiene il vecchio valore per il resto del vecchio TTL e solo dopo apprende quello nuovo, più breve. Riduci quindi il TTL almeno un intero periodo pari al vecchio TTL prima del cutover. Anticipare di un giorno è la scelta più prudente. Se questi passaggi sono nuovi per te, la guida introduttiva a record, resolver e caching fornisce il contesto.
I numeri riportati di seguito sono calcolati a partire dal TTL, non derivano da una misurazione.
The data behind this chart
[
{
"label": "TTL 3600 s (common default)",
"ttl_seconds": 3600,
"worst_case_stale_minutes": 60
},
{
"label": "TTL 900 s",
"ttl_seconds": 900,
"worst_case_stale_minutes": 15
},
{
"label": "TTL 300 s (lowered for cutover)",
"ttl_seconds": 300,
"worst_case_stale_minutes": 5
},
{
"label": "TTL 60 s (short window)",
"ttl_seconds": 60,
"worst_case_stale_minutes": 1
}
]Un record A pubblicato con un TTL di 3600 secondi può continuare a indirizzare gli utenti al vecchio IP per 60 minuti dopo la modifica. Riducilo a 300 secondi e il caso peggiore scende a 5 minuti. Considera queste cifre come un limite minimo, non come una garanzia. Alcuni resolver applicano un TTL minimo proprio e ignorano valori inferiori, mentre alcuni runtime applicativi memorizzano nella cache un indirizzo risolto per tutta la durata del processo. Di conseguenza, un client avviato prima della modifica potrebbe non eseguire una nuova risoluzione fino al riavvio.
Quando verifichi che il TTL ridotto sia attivo, leggi la risposta autorevole e non la cache locale:
# your laptop: ask the zone's own nameserver, so no cache is involved
dig +short NS example.com
dig +noall +answer @$(dig +short NS example.com | head -n1) example.com AIl secondo campo della riga di risposta è il TTL espresso in secondi. Controlla poi i record che vengono spesso dimenticati: il record AAAA se il vecchio server aveva IPv6, il nome www quando è un record A separato anziché un CNAME, gli eventuali record MX che puntano al server stesso, un record SPF che include il vecchio IP e il record DNS inverso (PTR) sul nuovo indirizzo. Se il server invia posta, imposta il PTR tramite il pannello di controllo del provider prima del cutover, perché i server di posta riceventi lo verificano e un PTR mancante può causare il rifiuto dei messaggi ore dopo che tutto il resto sembrava funzionare correttamente.
Verifica il nuovo server sul relativo indirizzo IP prima di modificare il DNS
Puoi testare l'intera applicazione sul nuovo server mentre il DNS continua a puntare a quello precedente. Sostituisci la risoluzione del nome per una singola richiesta:
# your laptop: force one name to the new IP, for this request only
curl -sS --resolve example.com:443:203.0.113.20 \
-o /dev/null -w '%{http_code} %{ssl_verify_result}\n' https://example.com/--resolve modifica soltanto la destinazione della connessione. Il certificato TLS viene comunque verificato rispetto al nome reale, quindi questo test convalida sia il certificato sia il servizio. %{ssl_verify_result} stampa 0 quando la catena dei certificati è stata verificata.
Per usare il sito in un browser, sostituisci la risoluzione del nome per l'intero computer aggiungendo una riga a /etc/hosts sul laptop oppure a C:\Windows\System32\drivers\etc\hosts su Windows:
203.0.113.20 example.com www.example.comQuindi usa l'applicazione come farebbe un utente. Accedi. Carica una pagina che legge dati dal database. Invia un modulo che scrive nel database. Carica un file e verifica che venga salvato sul disco. Attiva una funzione che invia email e verifica che il messaggio arrivi, perché l'SMTP in uscita da un nuovo indirizzo IP spesso causa problemi inattesi. Rimuovi la riga dal file hosts appena hai terminato. Se la lasci, rischi di passare un'ora a eseguire il troubleshooting di un sito che tutti gli altri visualizzano correttamente.
Il passaggio, passo dopo passo
- Alcuni giorni prima: riduci il TTL, esegui il
rsynccompleto, configura il nuovo server e testalo tramite un override del filehosts. - Il giorno dell'intervento, prima della finestra: aggiungi il nuovo IP a ogni allowlist di terze parti e verifica che il job di backup del nuovo server sia configurato e punti al tuo repository.
- All'inizio della finestra: attiva la modalità di manutenzione sull'applicazione del vecchio server, in modo che smetta di accettare scritture.
- Crea il dump finale del database, quindi esegui il passaggio finale di
rsynccon--delete. - Ripristina il dump sul nuovo server e avvia i servizi.
- Esegui di nuovo i test tramite
--resolvee l'override del filehosts, includendo una scrittura reale. - Modifica i record A e AAAA impostandoli sul nuovo IP.
- Monitora entrambi i server. Il log degli accessi del vecchio server mostra chi continua a raggiungerlo; il numero dovrebbe scendere verso zero durante il TTL.
- Disattiva la pagina di manutenzione.
- Lascia il vecchio server in esecuzione senza modificarlo per almeno una settimana.
La modalità di manutenzione è il passaggio che spesso viene saltato, ma è quello che offre la protezione principale. Dopo che il nuovo database ha accettato una scrittura, il rollback comporta la perdita di quella scrittura oppure l'esportazione del nuovo database e il successivo caricamento su quello vecchio. Una finestra di sola lettura di alcuni minuti ha un costo operativo ridotto. Due database che hanno entrambi accettato scritture richiedono giorni di riconciliazione manuale.
Il piano di rollback
Il rollback consiste in una sola operazione: riportare i record DNS a 198.51.100.10. Funziona soltanto perché in precedenza hai eseguito quattro operazioni.
- Il vecchio server è ancora in esecuzione, con i servizi attivi e i dati intatti. Hai interrotto le scritture su quel server, ma non lo hai dismesso.
- Il TTL è ancora basso, quindi il ritorno indietro è rapido quanto lo è stato il passaggio al nuovo server.
- Hai aggiunto il nuovo IP alle allowlist di terze parti invece di sostituire quello precedente. Se rimuovi il vecchio indirizzo, il rollback non funzionerà presso il gateway di pagamento.
- Il nuovo server non ha ricevuto scritture che non puoi identificare, perché finora le uniche scritture sono state le tue transazioni di test.
Stabilisci prima dell'inizio della finestra di intervento quali condizioni attivano il rollback. Sono sufficienti due condizioni: un errore che non riesci a diagnosticare entro un numero prestabilito di minuti e qualsiasi perdita di dati. Metterle per iscritto in anticipo evita l'ora di tentativi casuali che trasforma un'interruzione di dieci minuti in un'interruzione molto più lunga.
Verificare che la migrazione sia riuscita
Una migrazione non è conclusa quando il sito si carica. Verificate gli aspetti che possono funzionare all'inizio e fallire in seguito.
# new server
systemctl --failed
journalctl -p err -b --no-pager | tail -n 40
sudo certbot certificates
sudo systemctl list-timers --all --no-pagersystemctl --failed la generazione dei report 0 loaded units listed è il risultato che dovete ottenere. certbot certificates deve mostrare le date di scadenza previste e list-timers deve mostrare tutti i job pianificati presenti nel vostro inventario, con un orario effettivo della prossima esecuzione, non un campo vuoto.
Riavviate quindi una volta il nuovo server, intenzionalmente, mentre controllate il comportamento del sistema. Un servizio avviato manualmente e mai abilitato funziona correttamente fino al primo riavvio imprevisto, alle tre di notte.
# new server
sudo reboot
# your laptop, once it comes back
curl -sS -o /dev/null -w '%{http_code}\n' https://example.com/Se l'applicazione viene eseguita in container, lo stesso problema si presenta in modo diverso, perché uno stack Compose richiede una restart policy esplicita per ripartire dopo un riavvio.
L'ultimo controllo è quello più facile da rimandare e più importante: il job di backup. Una migrazione che si conclude con un server senza backup sostituisce un rischio con un altro. Eseguite manualmente il backup sul nuovo server, quindi ripristinate un singolo file in una directory temporanea. Un repository restic con un ripristino effettivamente testato è la configurazione utile quando serve. Se mantenete in esecuzione il vecchio e il nuovo server affiancati per una settimana, un metodo coerente per raggiungere e configurare ciascun host impedisce che i due sistemi divergano mentre sono entrambi attivi.
Dopo il passaggio: il vecchio server e le ultime operazioni
Mantieni il vecchio server per una o due settimane. Pagherai un mese del piano che stavi per annullare, ma sarà l'unico rollback disponibile. Poi completa le operazioni rimanenti.
- Riutilizzare lo stesso hostname nel tuo
~/.ssh/configper il nuovo server generaWARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!alla prima connessione, perché quel nome ora restituisce una host key diversa. Rimuovi la voce obsoleta conssh-keygen -R example.comdopo aver verificato il motivo del cambiamento, non automaticamente: lo stesso avviso può indicare un attacco di intercettazione. Una migrazione è anche un buon momento per verificare quali chiavi possono raggiungere quali sistemi; a questo serve Gestione delle chiavi SSH in una piccola flotta. - Crea un ultimo snapshot o backup del vecchio server e conservalo in una posizione che non appartenga al vecchio provider.
- Rimuovi il vecchio indirizzo IP dai controlli di monitoraggio, dai record SPF e dagli allowlist di terze parti, in quest'ordine e solo come ultima operazione.
- Annulla il vecchio piano solo dopo aver verificato che l'ultima copia sia leggibile in un'altra posizione.
FAQ
Quanto tempo serve per migrare un server verso un nuovo VPS?
L'indisponibilità visibile agli utenti coincide di solito con il dump finale del database, l'ultimo passaggio di rsync e l'avvio del servizio: per una piccola applicazione servono in genere da dieci a trenta minuti. Il tempo complessivo è maggiore, perché il TTL DNS deve essere ridotto almeno un periodo pari al vecchio TTL prima dello switch; anticipare di un giorno è più prudente. Pianifica con alcuni giorni di anticipo anche la copia dei dati principali. Questa operazione viene eseguita mentre il server è attivo e, se la ripeti in seguito, trasferisce soltanto le modifiche dall'ultimo passaggio.
Posso usare rsync su un database MySQL o PostgreSQL in esecuzione invece di eseguire un dump?
No. rsync copia i file uno alla volta mentre il database scrive contemporaneamente su più file. La copia contiene quindi pagine appartenenti a momenti diversi e rappresenta uno stato che il database non ha mai avuto. Il database potrebbe rifiutarsi di avviarsi oppure avviarsi e fallire in seguito quando una query raggiunge una pagina danneggiata. Usa pg_dump con pg_dumpall --globals-only oppure mysqldump --single-transaction, oppure arresta prima il database e poi copia i file. Per un cluster PostgreSQL di grandi dimensioni, pg_basebackup crea una copia fisica coerente di un server in esecuzione.
Come posso testare il nuovo VPS prima di modificare il DNS?
Sovrascrivi la risoluzione del nome sul tuo computer. Per una singola richiesta, curl --resolve example.com:443:203.0.113.20 https://example.com/ invia la connessione al nuovo IP, continuando però a verificare il certificato rispetto al nome reale. Per eseguire test nel browser, aggiungi 203.0.113.20 example.com a /etc/hosts sul laptop, verifica un accesso, una lettura dal database, l'invio di un modulo e il caricamento di un file, quindi rimuovi la riga. Per esaminare soltanto il certificato, esegui openssl s_client -connect 203.0.113.20:443 -servername example.com.
Quale TTL devo impostare e quando devo ridurlo?
Riduci i record A e AAAA a 300 secondi e fallo almeno un intero periodo pari al vecchio TTL prima dello switch. Un resolver che ha memorizzato il record prima della modifica conserva il vecchio valore per il tempo rimanente del vecchio TTL. Pertanto, ridurlo con un'ora di anticipo non serve a nulla se il vecchio TTL era 86400. Riportalo al valore normale alcuni giorni dopo la migrazione, quando il log degli accessi del vecchio server non registra più attività.
Devo copiare il certificato TLS o generarne uno nuovo sul nuovo server?
Entrambe le opzioni funzionano. Copiare /etc/letsencrypt/ mantiene valido il certificato fino alla scadenza attuale, ma devi installare sul nuovo server lo stesso plugin di autenticazione di certbot. In caso contrario, il primo rinnovo fallisce. Esegui quindi certbot renew --dry-run dopo lo switch DNS per verificare il rinnovo. Generare un nuovo certificato è più semplice quando puoi usare la challenge DNS-01, perché dimostra il controllo tramite un record TXT e funziona prima che il DNS punti al nuovo server. La challenge HTTP-01 non può essere usata sul nuovo server finché il DNS non è stato spostato, perché la richiesta di validazione raggiungerebbe il vecchio server.