Todos os sistemas operacionais Amsterdã · Paris · Reykjavík +5 Pagar com Criptomoeda
Redes e auto-hospedagemIntermediário33 min de leituraAtualizado em 2026-09-06

Migre um VPS para um novo host sem downtime

Todo servidor muda de host pelo menos uma vez. A mecânica é a parte fácil — as falhas vivem nas lacunas entre três relógios que não estão sincronizados: DNS, dados, e as sessões já em trânsito. Veja como fechar essas lacunas numa terça-feira que você escolheu.

Migre um VPS para um novo host sem downtime
Nesta página
  1. Os três relógios, e por que “zero downtime” é o alvo errado
  2. O que o host antigo guarda depois que você vai embora
  3. O relógio do TTL começa a correr uma semana antes da mudança
  4. Dimensionando a nova máquina, e o que verificar antes de se comprometer com ela
  5. Passo a passo
  6. O e-mail não migra junto com o resto
  7. Revertendo sem piorar as coisas
  8. Desativação: rotacione, apague, verifique, depois cancele
  9. Uma linha do tempo que funciona
  10. Perguntas frequentes

Todo servidor que você roda vai mudar de host pelo menos uma vez. O provedor aumenta os preços, ou começa a pedir um documento que você preferiria não enviar, ou recebe uma reclamação de abuso sobre um vizinho e derruba um /24 inteiro por uma tarde. A pergunta nunca foi se você ia migrar — só se isso aconteceria numa manhã de terça-feira escolhida por você, ou num sábado à noite que outra pessoa escolheu por você.

A mecânica não é a parte difícil. Copiar arquivos é rsync, e você já sabe disso. O que faz as migrações darem errado é o tempo: três relógios separados rodam durante uma mudança, eles não estão sincronizados, e toda falha real acontece nas lacunas entre eles. Este guia é sobre essas lacunas — o TTL de DNS que você deveria ter baixado uma semana atrás, o banco de dados que você copiou enquanto ele ainda estava sendo escrito, o certificado que só existe numa máquina que você acabou de desligar, e as credenciais que o host antigo conseguiu ler o tempo todo.

Os comandos presumem Debian ou Ubuntu nas duas pontas e uma aplicação web com banco de dados, porque é isso que a maioria das pessoas está migrando. Um Nextcloud, um servidor de jogo, um bot ou uma instância do BTCPay seguem todos a mesma estrutura — só o passo de dados muda.

Os três relógios, e por que “zero downtime” é o alvo errado

Uma migração não é um evento único. São três cronômetros correndo em velocidades diferentes, e toda a técnica está em impedir que eles se sobreponham mal:

  • O relógio do DNS. A partir do momento em que você muda um registro A, os resolvedores continuam respondendo com o endereço antigo até que a cópia em cache deles expire. Você não controla esse relógio na hora do corte — você o controlou quando definiu o TTL, dias antes.
  • O relógio dos dados. Sua última cópia dos dados é uma fotografia de um momento. Tudo que for escrito depois desse momento vive só na máquina antiga, e vai se perder a menos que você o reproduza ou impeça que aconteça.
  • O relógio das sessões. Uploads em andamento, WebSockets abertos, um callback de pagamento que vai chegar em quarenta segundos vindo de um processador que resolveu o seu hostname há dois minutos. Eles pousam em qualquer máquina que o remetente resolveu, não na que você preferiria.

Perseguir o zero downtime literal significa manter as três coisas rodando simultaneamente, o que na prática significa rodar a aplicação em dois servidores escrevendo em dois bancos de dados ao mesmo tempo. Isso é um problema genuinamente difícil, e é o errado para resolver num único VPS. A meta honesta é mais estreita e muito mais fácil de acertar:

Nenhum visitante vê um erro, e nenhuma escrita se perde. Uma janela de noventa segundos em que o site está no ar mas somente leitura satisfaz as duas coisas, e quase ninguém vai perceber. Um corte ao vivo sem janela de manutenção que silenciosamente perde os últimos quarenta minutos de envios de formulário não satisfaz nenhuma das duas, e você vai descobrir isso por um cliente.

Então o plano é: torne a janela de somente leitura o mais curta possível, torne-a monótona, e torne-a reversível. Tudo abaixo está a serviço dessas três coisas.

O que o host antigo guarda depois que você vai embora

Essa parte costuma ser pulada, e é o motivo pelo qual muita gente migra logo de cara, então vale a pena ser preciso sobre isso. Enquanto o seu servidor viveu no hardware de outra pessoa, esse provedor estava em posição de ver:

  • O disco, por inteiro. A menos que o volume estivesse criptografado com LUKS e desbloqueado só por você, o hypervisor conseguia ler cada byte dele — chaves, tokens, conteúdo do banco de dados, tudo. Mesmo com criptografia, a memória de uma VM em execução contém a chave desbloqueada.
  • Toda credencial que a máquina usou. Tokens de API em arquivos de ambiente, senhas de SMTP, segredos de RPC do daemon da carteira, suas chaves públicas de SSH e, se você algum dia colou uma numa console de resgate, bem mais do que isso.
  • Tudo o que a conta exigiu. Um nome, um cartão, um endereço, um número de telefone para verificação por SMS, os endereços IP de onde você fez login. Esse conjunto não diminui quando você fecha a conta, e na maioria das jurisdições o provedor é obrigado a guardar partes dele por anos.

Nada disso é sinistro — é o que rodar uma máquina virtual no metal de outra pessoa significa, em qualquer lugar, inclusive aqui. O que importa é que uma migração é o único ponto de corte limpo que você tem. A máquina nova começa com chaves novas, tokens novos e um IP novo; se você carregar os segredos antigos junto, você carrega a exposição antiga junto com eles, e o corte foi só cosmético.

Então trate todo segredo na máquina antiga como comprometido por padrão e reemita-o durante a mudança. Isso custa uma hora, uma vez. Fazer isso depois, separadamente, é uma tarefa que ninguém nunca chega a fazer. E se parte do motivo de você estar se mudando é que a própria conta é o vazamento, pagar a nova em Monero contra uma conta no-KYC é o passo que torna o corte real em vez de simbólico — embora seja bom ser honesto consigo mesmo sobre o que isso compra e o que não compra, o que é um assunto à parte.

O relógio do TTL começa a correr uma semana antes da mudança

Time to live é o número de segundos que um resolvedor tem permissão de guardar o seu registro antes de perguntar de novo. Se o seu registro A tem o TTL padrão de 3600, então no instante em que você o muda, um resolvedor que perguntou um segundo atrás vai continuar mandando visitantes para o servidor antigo pelos próximos cinquenta e nove minutos e cinquenta e nove segundos. Com o 86400 que muitos registradores ainda usam como padrão, isso vira um dia inteiro.

Confira o que você realmente tem — não o que você acha que configurou:

dig +noall +answer example.com A
dig +noall +answer www.example.com A
dig +noall +answer example.com MX
dig +noall +answer example.com NS

A segunda coluna de cada resposta é o TTL, contando regressivamente. Baixe todo registro envolvido na mudança para 300 segundos, e faça isso pelo menos duas vezes o TTL atual antes do seu corte: se o registro está em 86400, a própria mudança leva um dia para ficar universalmente visível, o que é a piada recursiva no centro das migrações de DNS.

Dois detalhes que pegam as pessoas:

  • Os registros NS têm o seu próprio TTL, geralmente um longo, e ele é definido no registrador, não na sua zona. Isso só importa se você também estiver trocando de nameservers — o que você deveria evitar fazer na mesma semana de uma mudança de servidor. Troque de host, estabilize, depois troque de provedor de DNS se quiser. Duas variáveis, dois fins de semana.
  • “Propagação de DNS” não existe. Nada se propaga; caches expiram. Não há fila para esperar nem botão que empurre uma atualização mais rápido. A única alavanca é o TTL, e na hora do corte ela já foi puxada.

Enquanto você está no arquivo de zona, anote todo registro que aponta para o endereço IP do servidor em vez de para um nome. Geralmente há mais um do que você lembra: mail, webmail, um @ sozinho, um staging antigo, o registro SPF com um literal ip4: nele, e o registro AAAA que você adicionou quando ganhou um bloco IPv6 pela primeira vez e depois esqueceu. Cada um deles precisa de um plano, e o AAAA é a clássica falha silenciosa — você vira o registro A, tudo parece bem no seu notebook, e todo visitante com IPv6 funcionando continua caindo num servidor que você já apagou.

Dimensionando a nova máquina, e o que verificar antes de se comprometer com ela

Resista ao impulso de pedir a mesma especificação que você tem hoje. Você está comprando pelos números de uma fatura, não pelo que a carga de trabalho realmente usa. Gaste dois minutos medindo primeiro:

# peak RAM actually in use, not allocated
free -m
# what has been paging, if anything
vmstat -s | grep -i swap
# real disk consumption, biggest first
du -xh --max-depth=2 / 2>/dev/null | sort -rh | head -20
# load relative to core count
uptime; nproc

Duas regras práticas se sustentam bem. Se a sua load average fica abaixo do número de núcleos e o swap nunca foi tocado, a máquina não é limitada por CPU ou memória e você pode migrar para o lado ou para baixo. Se o disco está acima de setenta por cento, dimensione a nova pelo que você vai precisar daqui a um ano, não pelo que usa hoje — crescer um volume depois é uma migração em miniatura, e você está fazendo uma dessas agora mesmo.

Do nosso lado isso mapeia direitinho: o Pup (1 vCPU, 1 GB, 25 GB) roda um site estático, uma VPN ou um bot pequeno; o Cub (1 vCPU, 2 GB, 40 GB) é a menor máquina que hospeda uma aplicação mais o seu próprio banco de dados sem paginar; o Scout (2 vCPU, 4 GB, 70 GB) é o padrão confortável para um site de verdade com tráfego de verdade; o Hunter (4 vCPU, 8 GB, 140 GB) e acima é onde contêineres, CI ou vários serviços numa única máquina começam a fazer sentido. Todos eles são all-NVMe com tráfego ilimitado, então excedente de banda — um motivo comum para migrar, logo de cara — deixa de ser uma variável. Tabela completa aqui.

Então, antes de mover um único byte, verifique três coisas sobre a máquina que você acabou de receber. Cada uma delas é barata agora e cara depois do corte:

  • A reputação do IP. Um endereço reciclado com o histórico de outra pessoa vai fazer o seu e-mail ser recusado e os seus visitantes serem desafiados. Os nossos são triados e segmentados por risco antes de serem emitidos, mas o serviço no endereço agora é seu, então verifique você mesmo — a versão de cinco minutos está aqui. Faça isso antes da virada do DNS, quando a resposta ainda não custa nada.
  • DNS reverso. Se a máquina algum dia for mandar e-mail, o registro PTR precisa resolver para um hostname que resolve de volta para o mesmo IP. rDNS personalizado está disponível sob pedido; peça agora para que esteja estabilizado até o corte.
  • A rota a partir de onde os seus usuários estão. Um mtr de uma máquina na região dos seus usuários te diz mais sobre a escolha de jurisdição do que qualquer ficha técnica. Latência que você mede vence latência que você presumiu.

Passo a passo

  1. Baixe todo TTL, dias antes de planejar a mudança

    Este é o primeiro porque é o único passo com um período de espera obrigatório. Tudo o mais pode ser feito numa tarde; este não pode ser apressado, e pulá-lo é o que transforma um corte de cinco minutos num de dois dias.

    Faça login onde quer que a sua zona viva e defina o TTL para 300 em todo registro que vai mudar: o ápice A, o AAAA, www, mail, e qualquer outra coisa apontando para um IP literal. Depois confirme de fora, porque painéis de controle e a realidade às vezes discordam:

    dig +noall +answer example.com A @1.1.1.1
    dig +noall +answer example.com AAAA @1.1.1.1
    dig +noall +answer www.example.com A @8.8.8.8

    O número antes de IN é o TTL restante. Consulte de novo um minuto depois: ele deveria estar contando regressivamente a partir de 300, não de algo maior. Se ainda estiver contando a partir de 3600, o valor antigo está em cache e você só espera passar — o que é exatamente por que isso acontece no dia menos sete, e não na manhã da mudança.

    Deixe o TTL em 300 durante a migração e por uma semana depois, para que o seu rollback também seja rápido. Coloque-o de volta em algo sensato — 3600 está bom — assim que a máquina antiga se for.

  2. Faça o inventário do servidor antigo antes de copiar qualquer coisa

    Você não está migrando um disco, está migrando um sistema em execução, e as partes que as pessoas esquecem nunca estão em /var/www. São o cron job que roda no dia quatro do mês, a regra de firewall adicionada durante um incidente, o pacote instalado de um repositório de terceiros há dois anos. Capture o estado da máquina como texto, e copie esse texto junto com tudo o mais:

    mkdir -p /root/mig
    dpkg --get-selections > /root/mig/packages.txt
    systemctl list-units --type=service --state=running --no-pager > /root/mig/services.txt
    systemctl list-timers --all --no-pager > /root/mig/timers.txt
    crontab -l > /root/mig/cron-root.txt 2>/dev/null
    for u in $(cut -d: -f1 /etc/passwd); do crontab -lu "$u" 2>/dev/null | sed "s/^/[$u] /"; done > /root/mig/cron-users.txt
    ss -tlnp > /root/mig/listening.txt
    nft list ruleset > /root/mig/firewall.txt 2>/dev/null || iptables-save > /root/mig/firewall.txt
    cp -a /etc/hosts /etc/fstab /root/mig/
    du -xh --max-depth=2 / 2>/dev/null | sort -rh | head -40 > /root/mig/disk.txt

    Agora leia o listening.txt linha por linha e dê conta de cada porta. Esse arquivo é a resposta definitiva para “o que esse servidor realmente faz”, e rotineiramente é uma surpresa — um exportador de métricas, uma cópia de staging esquecida, um banco de dados escutando numa interface pública que nunca deveria ter estado ali.

    Escreva sua lista de exclusão ao mesmo tempo, para que a primeira sincronização não gaste uma hora em dados que você não quer:

    cat > /root/mig/excludes <<'EOF'
    /dev
    /proc
    /sys
    /run
    /tmp
    /var/tmp
    /var/cache
    /var/lib/apt/lists
    /swapfile
    /var/lib/docker/overlay2
    /var/lib/mysql
    /var/lib/postgresql
    **/node_modules
    **/.cache
    EOF

    Note que os diretórios do banco de dados são excluídos deliberadamente. Eles têm o seu próprio passo, e copiá-los aqui é o erro que o passo seis existe para evitar.

  3. Implante o novo servidor e proteja-o antes de ele guardar qualquer coisa

    Peça a máquina, escolha a localização e mantenha a mesma versão principal do sistema operacional da antiga, se puder. Migrar de host e trocar de Debian 12 para Debian 13 na mesma operação significa que, quando algo quebrar, você não vai saber qual mudança causou isso. Migre primeiro, atualize depois.

    Antes de qualquer coisa sensível chegar nela, dê à máquina os dez minutos de hardening: SSH somente por chave, login root desabilitado, firewall com negação por padrão, atualizações de segurança automáticas. Isso leva dez minutos agora e é genuinamente tedioso de fazer depois, em torno de um serviço já no ar.

    Depois crie uma chave que existe só para esta migração, no servidor antigo, para que revogar o acesso de migração depois nunca signifique mexer no seu próprio login:

    # on the OLD server
    ssh-keygen -t ed25519 -f /root/.ssh/id_migrate -C 'migration' -N ''
    cat /root/.ssh/id_migrate.pub

    Coloque essa chave pública em /root/.ssh/authorized_keys no servidor novo, depois confirme a direção do envio — a antiga empurra para a nova, então a credencial mora na máquina que você está deixando para trás e morre com ela:

    ssh -i /root/.ssh/id_migrate root@NEW_IP 'hostname; df -h /; free -m'

    Por fim, coloque o novo IP no /etc/hosts do servidor antigo, sob um nome como newbox. Todo comando que vem a seguir fica mais curto e, mais útil ainda, mais difícil de apontar para a máquina errada à uma da manhã.

  4. Verifique o novo IP antes de confiar qualquer coisa a ele

    Agora você tem um endereço que ninguém nunca usou para o seu serviço, e este é o último momento em que encontrar um problema nele é de graça. Três verificações, cinco minutos:

    Blocklists. Passe o endereço pelas checagens multi-RBL — o procedimento completo e como ler os resultados está aqui. Um acerto numa lista de política como a Spamhaus PBL é normal para um IP de datacenter e significa pouco para tráfego web. Um acerto na SBL ou XBL é um de verdade, e a hora de resolver isso é agora, não depois que os seus usuários já estiverem nele.

    DNS reverso. Verifique o que o endereço responde hoje:

    dig +short -x NEW_IP

    Se a máquina for mandar e-mail, peça o registro PTR que você quer e garanta que ele corresponda a um hostname cujo registro A aponte de volta para o mesmo IP. Direto e reverso precisam concordar; uma incompatibilidade é pior do que um nome genérico.

    Alcance e rota. Confirme que as portas que você precisa estão realmente abertas de ponta a ponta, de fora, em vez de presumir que o seu firewall é a única coisa no caminho:

    # from a third machine, or your laptop
    nc -vz NEW_IP 22
    mtr -rwc 20 NEW_IP

    A saída do mtr é a que vale a pena guardar. Perda no salto final importa; perda num salto intermediário geralmente é um roteador despriorizando ICMP e não significa nada. Se a latência a partir de onde os seus usuários estão for consideravelmente pior do que no host antigo, é melhor descobrir isso agora, enquanto mudar de ideia ainda custa um pedido e nenhum dado.

  5. Copie o sistema de arquivos com rsync — e faça um dry-run primeiro

    Agora a transferência em massa. Faça em duas passadas: uma primeira cópia completa, dias antes, levando o tempo que precisar levar, depois passadas de delta curtas mais tarde que só movem o que mudou. Sempre faça um dry-run primeiro — a saída é uma lista exata do que está prestes a acontecer, e lê-la uma vez já salvou mais migrações do que qualquer outro hábito aqui.

    # on the OLD server, dry run
    rsync -aHAXx --numeric-ids --info=progress2 --dry-run \
      --exclude-from=/root/mig/excludes \
      -e 'ssh -i /root/.ssh/id_migrate' \
      /var/www/ root@newbox:/var/www/

    Depois o mesmo comando sem --dry-run. Repita para cada diretório que importa: /etc seletivamente em vez de por inteiro, /home, /srv, /opt, e onde quer que a sua aplicação realmente guarde os uploads dela.

    As flags merecem o seu lugar. -a preserva permissões, dono, timestamps e symlinks; -H mantém hard links; -A e -X carregam ACLs e atributos estendidos, que é o que o seu diretório de uploads precisa se algum dia alguém os definiu; -x impede que o rsync vagueie para outros sistemas de arquivos montados. --numeric-ids é o que as pessoas deixam de fora e depois se arrependem: sem ele, o rsync mapeia posse por nome, e se o www-data tem um UID diferente nas duas máquinas, todo arquivo chega pertencendo ao usuário errado, de um jeito tedioso de desfazer.

    Dois avisos. Copiar o /etc por inteiro para um sistema em execução vai sobrescrever a configuração de rede da máquina nova, o seu fstab e as suas chaves de host SSH — copie a configuração específica que você precisa, não o diretório. E guarde o --delete só para a passada final: ele é correto para fazer a máquina nova bater exatamente com a antiga, e destrutivo se você já criou alguma coisa no destino.

    Quando a primeira passada completa terminar, compare os dois lados para saber se ela fez o que você acha que fez:

    du -sh /var/www
    ssh -i /root/.ssh/id_migrate root@newbox 'du -sh /var/www'
  6. Mova o banco de dados com um dump, nunca com uma cópia de arquivo

    Este é o passo que decide se a sua migração vai ser monótona ou memorável. O diretório de dados de um banco de dados só é consistente quando o servidor está parado. Copie-o ao vivo e você ganha um conjunto de arquivos que parecem bem, transferem bem, e restauram para um banco de dados sutil e permanentemente corrompido — muitas vezes sem erro nenhum até semanas depois.

    Faça o dump direito. Para MySQL ou MariaDB, o --single-transaction é o que te dá um snapshot consistente sem travar tudo inteiro:

    mysqldump --single-transaction --quick --routines --triggers --events \
      --default-character-set=utf8mb4 --databases appdb \
      | zstd -T0 > /root/mig/appdb.sql.zst

    Para PostgreSQL, o formato custom vale a pena — ele comprime, e permite restaurar seletivamente se você precisar:

    pg_dump -Fc -Z6 appdb > /root/mig/appdb.dump

    Envie para o outro lado e restaure:

    scp -i /root/.ssh/id_migrate /root/mig/appdb.sql.zst root@newbox:/root/
    # on the NEW server
    zstd -dc /root/appdb.sql.zst | mysql
    # postgres equivalent
    pg_restore -d appdb -j4 /root/appdb.dump

    Depois verifique, porque “a restauração terminou” e “os dados estão lá” são afirmações diferentes. Compare a contagem de linhas nas tabelas que importam, dos dois lados:

    mysql -N -e "SELECT COUNT(*) FROM appdb.orders; SELECT COUNT(*) FROM appdb.users;"

    Duas coisas que se escondem em dumps: o conjunto de caracteres e a collation, que é de onde vêm os caracteres acentuados corrompidos — se o banco antigo está em utf8 em vez de utf8mb4, decida deliberadamente se a mudança também é o momento de consertar isso; e os usuários do banco de dados e privilégios, que o mysqldump --databases não inclui. Recrie o usuário e a senha da aplicação na máquina nova explicitamente, e depois lembre-se de que a connection string na sua configuração precisa bater.

    Se a sua aplicação usa SQLite, o arquivo é o banco de dados, e a mesma regra se aplica — não o copie ao vivo. Use sqlite3 app.db ".backup /root/mig/app.db", que faz uma cópia consistente com segurança.

  7. Suba a stack e ensaie com o truque do arquivo hosts

    O servidor novo agora tem os arquivos e os dados. Suba tudo e teste sob o hostname real dele — enquanto o resto do mundo ainda está usando a máquina antiga tranquilamente. Este é o truque mais valioso de todo o procedimento, e custa uma linha.

    No seu próprio notebook, adicione o IP do servidor novo ao /etc/hosts (ou C:\Windows\System32\drivers\etc\hosts):

    203.0.113.10   example.com www.example.com

    O seu navegador agora resolve o domínio real para o servidor novo, e o de mais ninguém faz isso. Toda URL está correta, todo domínio de cookie bate, todo redirecionamento e caminho de callback se comporta do jeito que vai se comportar depois do corte — que é precisamente o que testar contra um subdomínio temporário new.example.com não consegue capturar, porque metade do que quebra numa migração depende do hostname.

    Para uma checagem rápida única, sem editar nada, o curl pode fazer a mesma coisa embutido:

    curl -sSI --resolve example.com:443:203.0.113.10 https://example.com/
    curl -sS --resolve example.com:80:203.0.113.10 http://example.com/ -o /dev/null -w '%{http_code}\n'

    Percorra a aplicação inteira, não só a página inicial: faça login, envie um formulário, suba um arquivo, dispare um e-mail de redefinição de senha, carregue uma página de admin, acerte o endpoint que um processador de pagamentos chama. Depois leia os logs de erro mesmo que tudo tenha parecido bem — extensões do PHP faltando, um modo de arquivo errado num diretório de cache e um usuário de banco de dados que ainda não existe, tudo isso aparece lá antes de aparecer na tela.

    Lembre-se de remover a linha do hosts depois. Todo mundo esquece uma vez, e depois passa vinte minutos se perguntando por que o rollback parece não ter funcionado.

  8. Deixe o TLS funcionando na máquina nova antes de virar qualquer coisa

    Certificados são vinculados a nomes, não a endereços IP, então nada numa migração invalida um certificado que você já tem. O que quebra é a emissão: o desafio HTTP-01 de sempre pede para o Let's Encrypt buscar um arquivo na porta 80 no nome sendo certificado, e esse nome ainda aponta para o servidor antigo. O ovo e a galinha é toda a dificuldade, e há três saídas limpas.

    Copie os certificados existentes. O mais simples e geralmente o certo. A chave privada e a cadeia se movem como qualquer outro arquivo:

    rsync -aHAX -e 'ssh -i /root/.ssh/id_migrate' \
      /etc/letsencrypt/ root@newbox:/etc/letsencrypt/

    O servidor novo consegue servir TLS válido imediatamente, e a renovação começa a funcionar sozinha assim que o DNS apontar para ele. Confirme que o timer está habilitado lá: systemctl list-timers | grep certbot.

    Use um desafio DNS-01. Prova o controle do domínio através de um registro TXT em vez de uma requisição HTTP, então funciona a partir de um servidor para o qual nada aponta ainda. Ideal se você quer um certificado genuinamente independente na máquina nova antes do corte, e a única opção para um wildcard.

    Emita depois da virada. Válido, mas deixa uma brecha em que o site está no ar no IP novo sem certificado nenhum, o que para qualquer coisa com HSTS não é um aviso que os seus visitantes conseguem clicar para atravessar. Só faz sentido para um domínio novinho em folha que ninguém visitou ainda.

    Qualquer que você escolher, verifique contra o IP novo diretamente antes do corte, usando o mesmo truque do --resolve:

    curl -sSI --resolve example.com:443:203.0.113.10 https://example.com/ | head -1
    echo | openssl s_client -connect 203.0.113.10:443 -servername example.com 2>/dev/null \
      | openssl x509 -noout -subject -dates

    Confira as datas e que o subject cobre todo nome que você serve, www incluído. E se você usa HSTS com um max-age longo, trate o certificado como a única coisa que precisa estar certa antes da virada, não depois dela — esse header é uma promessa que você já fez a todo visitante que retorna.

  9. O corte: congele as escritas, delta final, vire o registro

    Dez minutos de trabalho de verdade, e a única parte com um relógio correndo. Faça isso de manhã, no seu próprio fuso horário, num dia em que você não esteja ocupado com outra coisa. Nunca numa sexta-feira.

    Congele. Coloque a aplicação antiga em modo de manutenção ou somente leitura. Pare os workers, os consumidores de fila e os cron jobs — qualquer coisa que escreva sem um navegador atrelado. A partir daqui, nada novo é escrito na máquina antiga, o que é o que torna tudo depois disso seguro:

    # on the OLD server
    systemctl stop app-worker.service
    systemctl stop cron
    touch /var/www/maintenance.flag

    Delta final. Mais um rsync, agora com --delete para que o destino bata exatamente, e mais um dump. Com a primeira passada feita dias atrás, isso move muito pouco e leva segundos:

    rsync -aHAXx --numeric-ids --delete --exclude-from=/root/mig/excludes \
      -e 'ssh -i /root/.ssh/id_migrate' /var/www/ root@newbox:/var/www/
    mysqldump --single-transaction --quick --routines --triggers --events \
      --default-character-set=utf8mb4 --databases appdb | zstd -T0 \
      | ssh -i /root/.ssh/id_migrate root@newbox 'zstd -dc | mysql'

    Verifique. Contagem de linhas dos dois lados, mais uma passada pela aplicação usando o truque do arquivo hosts, e tire a flag de manutenção da máquina nova.

    Vire. Mude o registro A para o IP novo. Mude o registro AAAA também — esta é a forma mais comum de um corte funcionar só pela metade. Confirme a partir de um resolvedor que você não controla:

    dig +short example.com A @1.1.1.1
    dig +short example.com AAAA @1.1.1.1

    Depois observe as duas máquinas. O tráfego deve aparecer na nova dentro de um ou dois minutos e desaparecer da antiga ao longo dos cinco minutos seguintes:

    tail -f /var/log/nginx/access.log        # on both, side by side

    Deixe a aplicação antiga em modo de manutenção em vez de desligá-la. Um retardatário que chegar até ela vê uma página educada em vez de um erro de conexão, e você mantém a máquina disponível para o rollback que você provavelmente não vai precisar.

  10. Observe por uma semana, depois desative direito

    A migração não está terminada quando o DNS resolve. Ela está terminada quando um ciclo completo de cobrança e cron passou sem nenhuma surpresa.

    Nas primeiras horas, observe as taxas de erro em vez do uptime — um servidor pode estar perfeitamente no ar e retornando 500 para um terço das requisições:

    journalctl -u nginx -u php8.4-fpm -f
    awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head

    Depois percorra uma lista curta, porque essas são as coisas que realmente quebram depois de uma mudança e nenhuma delas se anuncia: cron jobs e timers do systemd rodando na máquina nova (systemctl list-timers contra o inventário que você fez no passo dois); e-mail de saída chegando e não caindo no spam; backups agendados apontando para o servidor novo em vez de ainda arquivar o antigo; qualquer terceiro com o seu endereço IP numa allowlist — um processador de pagamentos, uma API, o firewall de um parceiro; e o job mensal que só se prova no primeiro dia do mês.

    Deixe o servidor antigo rodando, em modo de manutenção, intocado, por pelo menos uma semana. Ele é o seu rollback e a sua cópia de referência, e vale mais do que os poucos dólares que custa. Depois encerre-o em ordem: rotacione todo segredo que ele podia ter lido, faça um último arquivo criptografado para um terceiro local, sobrescreva os diretórios da aplicação e do banco de dados, rode a rotina de destruição ou reinstalação do provedor, e só então cancele — depois de conferir a data de renovação, porque um mês extra de seguro de rollback costuma ser a troca melhor.

    Por último, coloque o TTL de volta em 3600 agora que você não precisa mais de reversibilidade de cinco minutos, e atualize qualquer documentação que você mantenha com o endereço novo. Você do futuro, em alguma 2h da manhã mais adiante, vai ficar extremamente grato que o runbook bate com o servidor.

O e-mail não migra junto com o resto

Se o servidor antigo mandava e-mail — mesmo que só redefinições de senha — trate isso como uma segunda migração, mais lenta, rodando ao lado da primeira. Entregabilidade é um sistema de reputação, e a reputação está presa ao endereço IP e ao domínio, não ao software que você copiou.

Quatro registros decidem se o seu e-mail é lido ou descartado, e três deles contêm coisas que mudam quando o servidor muda:

  • SPF lista quem pode enviar pelo seu domínio. Se o seu contém um literal ip4:, ele agora está errado. Adicione o novo IP antes do corte e remova o antigo uma semana depois — os dois endereços autorizados por alguns dias não custa nada e cobre a sobreposição.
  • DKIM assina a mensagem com uma chave privada. Copie a chave junto com o resto da configuração e o seletor continua funcionando. Gerar uma chave nova em vez disso significa que você precisa publicar o novo seletor e esperar por ele, então copie a menos que tenha um motivo para não fazer isso.
  • DMARC diz aos receptores o que fazer quando os dois primeiros falham. Se você está em p=reject, um SPF quebrado durante a janela não é um aviso, é uma exclusão silenciosa. Considere baixar para p=none durante a semana da migração e voltar depois.
  • PTR é o registro reverso acima. Um IP novo tem um genérico até você pedir, e vários provedores grandes recusam e-mail de nomes reversos genéricos sem pestanejar.

A expectativa honesta: um IP novinho em folha começa sem reputação nenhuma, o que não é o mesmo que uma boa reputação. O volume aumenta ao longo de dias, não de horas. Se o e-mail é essencial para você, mantenha o servidor antigo vivo e enviando por uma semana depois da mudança em vez de trocar de uma vez só — e se ele é essencial para o negócio, um relay dedicado é uma resposta melhor do que qualquer uma das duas máquinas.

Revertendo sem piorar as coisas

O objetivo de um plano de rollback não é que você espere usá-lo. É que tê-lo permite fazer o corte com calma às 10h em vez de nervosamente às 2h da manhã, e calma é o que realmente evita erros.

Seu rollback é simples, e continua simples por exatamente o tempo em que o banco de dados antigo ainda for a fonte de verdade: volte o registro A. Com um TTL de 300 segundos você está recuperado em cinco minutos. Essa janela — entre a virada e a primeira escrita que só existe na máquina nova — é o seu desfazer de graça, e é por isso que o servidor antigo continua rodando, intocado e não apagado, por pelo menos uma semana.

O que estraga tudo é o split-brain: escritas caindo nas duas máquinas. Agora nenhum dos dois bancos de dados está correto, e reconciliá-los na mão é pior do que qualquer downtime que você estava tentando evitar. Três hábitos evitam isso por completo:

  • Coloque a aplicação antiga em modo somente leitura ou de manutenção no início da janela, em vez de confiar que o DNS parou de mandar tráfego. DNS é uma dica; um serviço parado é um fato.
  • Depois da virada, observe o log de acesso do servidor antigo, não o do novo. Requisições que ainda chegam lá são os seus retardatários, e quando esse resquício de tráfego secar, a migração está de fato terminada. tail -f /var/log/nginx/access.log é a ferramenta inteira.
  • Assim que você aceitar a primeira escrita real na máquina nova, reverter deixa de ser uma mudança de DNS — passa a ser uma restauração. Decida conscientemente quando cruzar essa linha, e diga isso em voz alta se vocês forem duas pessoas.

Estabeleça uma regra de parada antes de começar: se a nova stack não estiver servindo corretamente dentro de, digamos, trinta minutos, você reverte o registro, recupera a noite, e conserta sem nenhum relógio correndo. Migrações vão mal quando as pessoas continuam insistindo porque voltar atrás parece fracasso. Não é; é a opção barata, e ela fica disponível por um tempo estritamente limitado.

Desativação: rotacione, apague, verifique, depois cancele

Uma semana depois do corte, o servidor antigo é uma cópia completa, rodando, sem supervisão, dos seus dados, numa infraestrutura à qual você parou de prestar atenção. Nesse ponto, ele também é a máquina menos atualizada que você tem. Termine o trabalho nesta ordem:

  • Rotacione tudo que a máquina antiga podia ler. Segredos da aplicação, tokens de API, senhas de banco de dados, credenciais de SMTP, segredos de assinatura de webhook, qualquer senha de RPC de carteira. Presuma exposição, porque você não pode provar o contrário. Se você gerou uma chave SSH nova para a migração, é agora que as chaves autorizadas antigas saem.
  • Faça um arquivo final — um snapshot criptografado do restic ou Borg para um destino que não seja nenhuma das duas máquinas. Você vai querer isso exatamente uma vez, seis semanas depois, por causa de um arquivo que ninguém lembrava.
  • Sobrescreva os dados. Num VPS você não consegue verificar o meio físico, então faça o que puder: shred ou sobrescreva os diretórios da aplicação e do banco de dados, e depois deixe rodar a rotina de reinstalação ou destruição do provedor. Criptografia em repouso desde o início é o que torna isso barato; sem ela, você está confiando na política de exclusão de outra pessoa.
  • Verifique, depois cancele. Confirme que a máquina nova está servindo tudo há uma semana inteira, incluindo o cron mensal em que ninguém pensa, e confirme que nada na máquina antiga ainda está resolvendo. Depois cancele — e confira a data de renovação primeiro, porque pagar por um mês extra de seguro de rollback costuma ser mais esperto do que economizar oito dólares.

Apague a conta antiga em si por último, e só quando tiver certeza. Chamados de suporte, faturas e algum sub-serviço esquecido tendem a viver lá, e uma conta em que você não consegue fazer login é um lugar incômodo para descobrir um registro de DNS que você esqueceu de mover.

Uma linha do tempo que funciona

Espalhado ao longo de uma semana, nada disso é estressante. Comprimido numa única noite, tudo é.

  • Dia −7. Baixe todo TTL para 300. Faça o inventário do servidor antigo. Peça o novo e verifique o seu IP, o seu rDNS e a sua rota.
  • Dia −5. Proteja a máquina nova. Instale a stack. Primeiro rsync completo, que é o lento — toda passada seguinte só move o delta.
  • Dia −3. Restaure um dump do banco de dados na máquina nova e suba a aplicação. Teste tudo através do truque do arquivo hosts. Conserte o que estiver quebrado enquanto nada está em jogo, porque algo vai estar.
  • Dia −1. Emita o TLS no servidor novo. Confirme a cadeia do certificado e, se você usa, que o HSTS não vai transformar um pequeno erro em algo em que ninguém consegue clicar. Adicione o novo IP ao SPF. Reconfirme que todo TTL realmente baixou.
  • Dia 0, de manhã. Modo de manutenção na máquina antiga. Sincronização final do delta. Dump e restauração finais. Verificação de contagem de linhas. Vire o registro A — e o AAAA. Observe os dois logs de acesso.
  • Dia +1 a +7. Servidor antigo continua no ar, intocado. Observe os logs, o e-mail e a reputação do novo IP. Deixe os jobs mensais rodarem pelo menos uma vez, se puder.
  • Dia +7. Rotacione os segredos, faça o arquivo final, apague, verifique, cancele.

O melhor indicador de uma migração monótona é que o passo um aconteceu uma semana antes do passo cinco. Quase tudo que dá errado numa mudança de servidor é um TTL que ainda estava em 86400 às onze da noite.

Perguntas frequentes

Uma migração de VPS pode realmente ter zero downtime?

Literalmente zero, com escritas aceitas continuamente nas duas máquinas, exige replicação e um banco de dados compartilhado ou em cluster — um problema genuinamente difícil, e o errado para resolver num único servidor. O que é alcançável, de forma confiável, é que nenhum visitante veja um erro e nenhuma escrita se perca: uma janela curta de somente leitura durante a sincronização final, com o DNS já num TTL de 300 segundos para que a troca em si leve minutos. Na prática isso é de um a cinco minutos de página de manutenção, o que para quase todo site é indistinguível de zero e muito mais seguro do que a alternativa.

Quanto tempo a propagação de DNS realmente leva?

Não existe propagação. Nada é empurrado para lugar nenhum — os resolvedores simplesmente guardam o seu registro em cache pelo número de segundos que o seu TTL especifica, e perguntam de novo quando ele expira. Então a resposta honesta é “pelo tempo do TTL que estava em vigor quando você fez a mudança”. Com um TTL de 300 definido uma semana antes, essencialmente todo mundo está no endereço novo dentro de cinco minutos. Com o 86400 que muitos registradores ainda usam como padrão, alguns resolvedores continuam mandando tráfego para o servidor antigo por um dia inteiro. É por isso que baixar o TTL é o passo um, e não o passo nove.

Posso manter o meu endereço IP quando troco de host?

Não, a menos que você seja dono do próprio bloco de endereços e consiga fazer o novo provedor anunciá-lo, o que significa ser membro da RIPE ou da ARIN com a sua própria alocação — realista para uma empresa, não para um único servidor. Para todo mundo mais, um host novo significa um IP novo, o que é precisamente por que você verifica a reputação e o DNS reverso dele antes do corte, não depois. Do nosso lado, os endereços são triados contra a Spamhaus e mais de cem outras listas, e emitidos a partir de pools segmentados por risco em vez de reciclados de quem os teve por último, mas verificar isso você mesmo leva cinco minutos e sempre vale a pena.

Devo usar uma imagem de disco ou uma ferramenta de migração do provedor em vez disso?

Se as duas pontas são o mesmo provedor e o mesmo hypervisor, restaurar uma imagem é tranquilo e muito mais rápido. Entre provedores diferentes, geralmente é uma armadilha: a imagem carrega a configuração de rede da máquina antiga, os módulos de kernel, os drivers e as suposições de hardware, e você passa a noite depurando um sistema que inicializa numa máquina que não existe mais. Uma instalação limpa mais uma cópia bem pensada dos seus dados e configuração te dá um servidor que você entende, e descarta a sujeira acumulada da máquina antiga. Migrar é a oportunidade mais barata que você jamais vai ter de deixar coisas para trás.

E um banco de dados que está sendo escrito constantemente?

Duas opções, em ordem crescente de esforço. A simples é a janela de somente leitura do passo nove: um dump com --single-transaction de um banco ocupado mas de tamanho normal leva de segundos a alguns minutos, e uma página de manutenção por esse tempo é uma troca justa. A completa é replicação — configure o servidor novo como uma réplica dias antes, deixe-o se manter sincronizado, depois promova-o durante a janela. Isso reduz o congelamento a segundos, ao custo de uma configuração genuinamente mais complexa. Escolha a segunda só se a primeira não for aceitável, e nunca a improvise na noite.

Trocar de host vai prejudicar o meu ranking de busca?

Não por si só. O Google indexa hostnames, não endereços IP, e uma mudança em que as URLs e o conteúdo continuam idênticos é efetivamente invisível. O que custa caro é o que costuma acompanhar uma migração malfeita: páginas retornando 5xx enquanto os crawlers visitam, um erro de certificado, um robots.txt que chegou de uma cópia de staging com Disallow: / nele, ou redirecionamentos que mudaram de forma silenciosamente. Confira o robots.txt, as suas tags canônicas e um punhado de URLs reais imediatamente depois da virada. Se o site serve as mesmas respostas no IP novo e no antigo, não há nada do que se recuperar.

Meus certificados TLS ainda funcionam no servidor novo?

Sim — certificados são emitidos para nomes de domínio, não endereços IP, então copiar o /etc/letsencrypt te dá um certificado válido na máquina nova imediatamente. A complicação é a renovação, não a validade: um desafio HTTP-01 precisa que o domínio aponte para a máquina que está renovando, então até você virar o DNS, a renovação vai falhar lá. Copie os certificados antes do corte, vire, depois confirme que o timer de renovação roda com sucesso no servidor novo. Se você precisar de um certificado independente antes da virada — ou de um wildcard — use um desafio DNS-01 em vez disso.

Implante um VPS offshore em cerca de um minuto

Sem KYC, pago em cripto, tudo NVMe. Escolha um plano, pague em Monero ou qualquer moeda principal e receba root em cerca de 60 segundos.

Fenrir em guarda