~/ziphub — zsh
ZipHub·~/catalog~/articles~/feed~/sellers~/hire
auth login
[article]category · network

Como migrei de cinco VPS para um único servidor dedicado com Proxmox

@dignezzz · author17 min read2026-05-05free

TL;DR: Resumo: Infraestrutura fragmentada de cinco VPS de três provedores → um servidor dedicado Ryzen 7 9700X / 64GB ECC / espelho ZFS de 2x NVMe, com Proxmox VE. Dentro – VMs/LXCs por função, malha NetBird em vez de encaminhamento de portas, um nó de saída em uma VPS separada para contornar bloqueios e terminação TLS, PBS para backups. Mais dinheiro, mais controle, menos estresse. Este artigo explica porquê, como e onde encontrei problemas para que você não os encontre.

Como migrei de cinco VPS para um único servidor dedicado com Proxmox e parei de alimentar os hospedadores

Resumo: Infraestrutura fragmentada de cinco VPS de três provedores → um servidor dedicado Ryzen 7 9700X / 64GB ECC / espelho ZFS de 2x NVMe, com Proxmox VE. Dentro – VMs/LXCs por função, malha NetBird em vez de encaminhamento de portas, um nó de saída em uma VPS separada para contornar bloqueios e terminação TLS, PBS para backups. Mais dinheiro, mais controle, menos estresse. Este artigo explica porquê, como e onde encontrei problemas para que você não os encontre.

Por que eu comecei tudo isso

Até o final do ano passado, descobri que estava pagando por cinco VPS diferentes de três provedores. Uma – para o fórum Discourse, a segunda – para o fórum legado em PHP com MySQL, a terceira – para faturamento e bots do Telegram, a quarta – VPN/proxy, a quinta – estática e várias pequenas ferramentas. E também rodava n8n em algum lugar, e Vaultwarden, e alguns Uptime Kuma, que se monitoravam mutuamente (como poderia ser de outra forma).

O que era ruim:

  • Dinheiro. No total, saía aproximadamente o mesmo que custa um servidor dedicado decente com as mesmas características juntas (mas era compartilhado, e aqui é dedicado).
  • Nenhuma isolação. Se a memória de um cliente de bot começa a vazar – meu fórum começa a ficar lento. No mesmo servidor. Maravilhoso.
  • Backups – uma bagunça. Em cada VPS, um rsync-cron próprio para S3, retenções diferentes em todos os lugares, nenhuma incrementalidade, restaurar – uma aventura inteira.
  • Rede como um salada. SSH através de diferentes portas, encaminhadas através de Cloudflare Tunnels, através de WireGuard manualmente configurado entre duas VPS, com configurações em três lugares. Toda vez que eu adicionava uma nova máquina – um dia era gasto na integração.
  • Apocalipse de atualização. Em cinco diferentes Ubuntu/Debian com diferentes versões e pacotes, as atualizações precisam ser feitas manualmente e nunca ao mesmo tempo. Uma vez a cada seis meses, eu heroicamente passava pela missão "atualizar tudo, não quebrar nada".
  • CPU e RAM ociosos. Cada VPS é reservada "para o pico", mas em média é utilizada em 15-20%. Dinheiro voando pelo ralo.

Em suma – um caso clássico de infraestrutura que cresceu sob o princípio "oh, preciso de mais um serviço – vou comprar uma VPS". Era hora de consolidar tudo isso.

O que eu escolhi e porquê

Hardware

Peguei um servidor dedicado:

  • CPU: AMD Ryzen 7 9700X (8 núcleos / 16 threads, Zen 5)
  • RAM: 64 GB DDR5 ECC 5200 MHz
  • Discos: 2× NVMe 512 GB enterprise → espelho ZFS
  • Rede: 1 Gbps ilimitado
  • Preço: aproximadamente o mesmo que duas VPS médias do mesmo OVH

Hipervisor

Proxmox VE 9.x. Considerei alternativas, mas brevemente:

  • Docker puro – sem isolamento, sem snapshots normais, backup apenas com recursos do compose, disco – um lixo único.
  • VMware ESXi – não é mais gratuito, a licença Broadcom é maravilhosa, obrigado.
  • XCP-ng – bom, mas pessoalmente eu conheço Proxmox de cor e a comunidade é mais viva.
  • Kubernetes – não, eu sou uma pessoa só, não preciso montar um avião para ir à loja.

Proxmox me dá tudo o que preciso: máquinas virtuais KVM para tudo onde o isolamento é necessário (Docker, kernels específicos, diferentes distribuições); contêineres LXC onde os recursos podem ser economizados (bancos de dados, monitoramento, pequenos serviços); PBS integrado para backups; ZFS pronto para uso; snapshots; migração ao vivo (se um segundo servidor dedicado aparecer um dia); interface web onde você pode clicar com o mouse quando não quer escrever no terminal.

Arquitetura: esquema geral

Primeiro mostrarei o que resultou, depois contarei como cheguei a isso.

A lógica é a seguinte:

  1. No servidor dedicado vive o Proxmox. Ele possui o IP público Y.Y.Y.Y em vmbr0.
  2. Dentro, foi criado um segundo bridge vmbr1 com a rede privada 10.10.10.0/24. Este é o análogo de "LAN interna" – todas as VMs e LXCs estão lá, saindo para a internet via NAT do host, elas não têm portas públicas de entrada.
  3. No próprio host rodam apenas três coisas: Caddy (reverse proxy interno), nftables (firewall) e NetBird (agente VPN). Nenhum Docker no host, nenhuma lógica de aplicação no host. O host é uma vaca sagrada, sua tarefa é ser um hipervisor e não cair.
  4. As máquinas virtuais são divididas por função: uma para o fórum, uma para serviços em segundo plano e bots, uma para Dokploy com aplicações do usuário, etc. Entre elas há visibilidade direta via 10.10.10.x, para fora – apenas através do Caddy do host.
  5. Contêineres LXC – para tudo "leve": instâncias Postgres de diferentes versões, Proxmox Backup Server, painéis de monitoramento. Eles também estão em vmbr1.
  6. Um nó de saída separado ("Peer Caddy") – é uma pequena VPS de outro provedor, em uma rede adequada para meu público. Nele está o Caddy, que termina TLS (Let's Encrypt) e faz proxy HTTP para dentro do servidor dedicado através da malha NetBird. O DNS de todos os domínios públicos aponta para esta VPS, não para o servidor dedicado.
  7. A malha NetBird conecta o servidor dedicado, o nó de saída e meu laptop (além de alguns servidores antigos dos quais nem tudo migrou ainda). É WireGuard sobre autenticação SSO, sem portas abertas para o exterior.

Por que tal isolamento através de um nó de saída – é uma conversa separada, à qual voltarei.

Instalação do Proxmox: como eu o configurei

Pedi o servidor dedicado, no primeiro boot instalei o Proxmox via modo rescue/KVM (OVH tem ambos – KVM é mais conveniente para mim, mostra todo o processo). Durante a instalação:

  • ZFS RAID1 em ambos os NVMe (ashift=12, compressão=lz4 ativada imediatamente)
  • particionamento padrão, Proxmox cria rpool/ROOT, rpool/data, swap

Em seguida – limpeza básica após a instalação. Isso é essencial, sem isso o Proxmox mostra erros de assinatura e não funciona de forma otimizada.

bash
1# 1. Remover o repositório enterprise (sem assinatura)
2sed -i 's/^deb/#deb/' /etc/apt/sources.list.d/pve-enterprise.list
3echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" \
4  > /etc/apt/sources.list.d/pve-no-subscription.list
5apt update && apt full-upgrade -y
6
7# 2. Remover a janela de aviso "No valid subscription"
8sed -Ezi.bak "s/(Ext\.Msg\.show\(\{[^}]+?title: gettext\('No valid sub)/void\(\{ \/\/\1/g" \
9  /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
10systemctl restart pveproxy
11
12# 3. Hostname / timezone
13hostnamectl set-hostname dedik-waw
14timedatectl set-timezone Europe/Warsaw

Fortalecimento do SSH

Imediatamente. Não "depois". Depois – nunca acontece.

bash
1cat > /etc/ssh/sshd_config.d/hardening.conf << 'EOF'
2Port 22222
3PermitRootLogin prohibit-password
4PasswordAuthentication no
5MaxAuthTries 3
6ClientAliveInterval 300
7ClientAliveCountMax 2
8EOF
9
10mkdir -p ~/.ssh
11echo "ssh-ed25519 AAAA... sua-chave" >> ~/.ssh/authorized_keys
12chmod 600 ~/.ssh/authorized_keys
13systemctl restart sshd

Porta 22 no firewall fechada, deixei apenas a não padrão. Isso não é segurança por obscuridade, é redução de ruído de fundo nos logs – na porta 22 na primeira hora chegam 50 mil tentativas de brute force, nos logs não se vê nada. Na 22222 – silêncio e é possível monitorar anomalias reais.

ZFS – configuração para NVMe e 64GB RAM

Por padrão, o ZFS quer consumir metade da RAM para o ARC. Isso é normal para um servidor de arquivos e absolutamente contraindicado para um hipervisor, onde a RAM é necessária para as máquinas virtuais. Reduzimos o ARC para um valor razoável de 16 GB:

bash
1cat > /etc/modprobe.d/zfs.conf << 'EOF'
2options zfs zfs_arc_max=17179869184
3options zfs zfs_arc_min=4294967296
4EOF
5update-initramfs -u

Distribuição da minha memória:

  • ~16 GB — ZFS ARC
  • ~44 GB — VM/LXC
  • ~4 GB — sistema, buffers, overhead

Configurações úteis do próprio pool:

bash
1zfs set compression=lz4 rpool
2zfs set atime=off rpool
3zfs set xattr=sa rpool
4zfs set dnodesize=auto rpool
5zfs set relatime=on rpool
6
7zfs set recordsize=64K rpool/data    # para discos de VM
8zfs set sync=standard rpool/data
9
10zpool set autotrim=on rpool          # crítico para NVMe

compression=lz4 economiza 20-30% de espaço quase de graça em termos de CPU. recordsize=64K para dispositivos de bloco de VM – o melhor compromisso entre desempenho e amplificação de gravação.

Rede interna e firewall

Criei um segundo bridge para a rede privada com NAT para a saída:

1auto vmbr1
2iface vmbr1 inet static
3    address 10.10.10.1/24
4    bridge-ports none
5    bridge-stp off
6    bridge-fd 0
7    post-up   echo 1 > /proc/sys/net/ipv4/ip_forward
8    post-up   iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o vmbr0 -j MASQUERADE
9    post-down iptables -t nat -D POSTROUTING -s 10.10.10.0/24 -o vmbr0 -j MASQUERADE

Agora qualquer VM/LXC na bridge vmbr1 recebe um endereço local 10.10.10.x e sai para a internet através do host, mas não é visível do exterior.

nftables com policy drop. Apenas o que deve ser aberto é aberto, o resto é descartado silenciosamente. Conjunto mínimo:

nft
1table inet filter {
2    chain input {
3        type filter hook input priority 0; policy drop;
4
5        iif lo accept
6        ct state established,related accept
7        ip protocol icmp accept
8        ip6 nexthdr icmpv6 accept
9
10        tcp dport 22222 accept           # SSH
11        tcp dport 8006 accept            # UI do Proxmox (apenas de NetBird, veja abaixo)
12        tcp dport { 80, 443, 8080 } accept   # Caddy
13        udp dport 29899 accept           # NetBird
14
15        iif vmbr1 accept                 # rede interna – tudo permitido
16        iif wt0 accept                   # interface NetBird – também confiável
17    }
18
19    chain forward {
20        type filter hook forward priority 0; policy drop;
21        iif vmbr1 oif vmbr0 accept
22        ct state established,related accept
23    }
24}

O acesso à UI do Proxmox (porta 8006) está fisicamente fechado da internet via CF/firewall e acesso a ele apenas via NetBird. Pelo IP público, a interface não responde de forma alguma. O mesmo vale para a UI do PBS, painéis e toda a administração – apenas via malha. Do exterior, apenas as portas realmente públicas dos serviços estão abertas.

Malha NetBird: por que não o WireGuard clássico

Eu usei o WireGuard normal por muito tempo, e funcionou bem, até que tive mais de três servidores. Depois – gerenciar as configurações tornou-se doloroso: cada adição de peer se transforma em "atualizar a configuração em todos os nós, não esquecer allowed_ips, reiniciar o daemon, verificar se não quebrou a rota para outro peer".

NetBird é um plano de gerenciamento sobre o WireGuard. Tecnicamente, por baixo dos panos, é tudo o mesmo wg, mas:

  • os nós se encontram através de um servidor de sinalização, NAT-traversal é automático
  • autenticação via SSO (no meu caso – via Authentik), sem compartilhamento de chaves
  • o acesso é gerenciado na interface web através de políticas, você pode criar grupos de máquinas e regras entre eles
  • proxy SSH integrado: você pode acessar via ssh user@machine.netbird.cloud e obter autenticação SSO (com aprovação no Authentik). Na nó, nem precisa abrir a porta 22 para o exterior.

Instalei o agente NetBird:

  • no host Proxmox
  • em cada VM que deve ser visível para o administrador ou outras VMs
  • no nó de saída
  • no meu laptop

Como resultado, acesso qualquer máquina do meu laptop com um único comando, sem encaminhamento de portas, sem buracos no firewall, sem hosts de bastião adicionais. E não há SSH aberto em nenhuma das VMs privadas – elas estão todas apenas em vmbr1 mais a malha wt0.

Máquinas Virtuais vs Contêineres: como eu decidi isso para mim

Uma regra simples que funciona quase sempre:

QuandoO que escolher
Cargas de trabalho DockerVM (Docker em LXC pode ser caprichoso, especialmente com overlay2)
Bancos de dados sem DockerLXC (mais leve, mais rápido, acesso direto ao disco via ZFS)
Serviços de sistema (PBS, monitoramento, pequenas ferramentas)LXC
Aplicações que precisam de seu próprio kernel / truques de redeVM
Nós VPN (WG, AmneziaWG)LXC (overhead mínimo)

No final, consegui algo assim:

Máquinas Virtuais (KVM):

  • forum – Discourse no contêiner launcher padrão. Docker dentro.
  • services – um monte de pequenas coisas: bots webhook, bot de IA, painel de faturamento, Vaultwarden, Uptime Kuma. Tudo em Docker compose, por pasta para cada serviço.
  • legacy – fórum antigo PHP (IPS) com PHP-FPM nativo e Caddy na VM. Não queria empacotar em Docker – muita coisa legada, mais fácil deixar como estava.
  • dokploy – Docker Swarm + Dokploy para aplicações de usuário (Next.js, Postgres, Redis), deploy via Git.

LXC:

  • pbs – Proxmox Backup Server (veja abaixo).
  • pg16, pg17, pg18 – três instâncias Postgres separadas de diferentes versões principais. Detalhe: diferentes aplicações querem versões principais diferentes, e eu não quero lidar com cada uma.
  • dashboards – um contêiner com Homarr (página inicial), Uptime Kuma e Beszel hub. Todos os três no mesmo compose, porque eles são logicamente sobre a mesma coisa – observar.

Cada VM recebe um IP estático em 10.10.10.x (por faixa, é mais fácil de encontrar), 2-8 vCPUs e 2-8 GB de RAM dependendo da carga. Os núcleos podem ser superprovisionados com segurança – no total, tenho mais núcleos alocados para as VMs do que físicos, e isso funciona perfeitamente, enquanto ninguém atingir o limite de CPU ao mesmo tempo.

Reverse proxy: Caddy de dois andares

Dentro do Proxmox, instalei o Caddy no host, e não em uma VM. Por quê? Porque ele precisa escutar as portas públicas do servidor dedicado e rotear por Host-header para a VM correta, e criar uma VM separada para isso com encaminhamento de porta é uma camada extra sem benefício. Caddy é leve, escrito em Go, unidade systemd, configuração em um arquivo.

Este Caddy do host escuta apenas na porta 8080 HTTP e roteia para os backends em 10.10.10.x. Não há TLS nele.

caddy
1:8080 {
2    @forum host forum.example.com www.forum.example.com
3    handle @forum {
4        reverse_proxy http://10.10.10.111:80 {
5            header_up X-Forwarded-Proto https
6            header_up X-Real-IP {header.X-Real-IP}
7            header_up Host {host}
8        }
9    }
10
11    @panel host panel.example.com api.panel.example.com
12    handle @panel {
13        reverse_proxy http://10.10.10.111:8081 {
14            header_up X-Forwarded-Proto https
15            header_up X-Real-IP {header.X-Real-IP}
16            header_up Host {host}
17        }
18    }
19
20    @dokploy host app1.example.com app2.example.com
21    handle @dokploy {
22        reverse_proxy http://10.10.10.114:80 {
23            header_up X-Forwarded-Proto https
24            header_up X-Real-IP {header.X-Real-IP}
25            header_up Host {host}
26        }
27    }
28}

E a terminação TLS e os certificados – em um nó de saída separado, no Docker, com o mesmo princípio:

caddy
1{
2    email me@example.com
3}
4
5forum.example.com {
6    reverse_proxy http://100.x.y.z:8080 {
7        header_up X-Forwarded-Proto {scheme}
8        header_up X-Forwarded-For {remote_host}
9        header_up X-Real-IP {remote_host}
10        header_up Host {host}
11    }
12}

100.x.y.z – este é o endereço NetBird do servidor dedicado. A solicitação chega ao nó de saída via HTTPS, é descriptografada, vai para a malha NetBird em HTTP para o servidor dedicado, lá o Caddy do Proxmox combina pelo Host e roteia para a VM interna. Entre o nó de saída e o servidor dedicado, o HTTP é por design – confiamos na malha, não há tráfego externo aqui.

Por que um nó de saída?

Várias razões:

  1. Contornar bloqueios. Parte das sub-redes OVH na Rússia são bloqueadas. O nó de saída está com um provedor cujo IP não é bloqueado. O DNS dos domínios públicos aponta para lá.
  2. Terminação TLS em um só lugar. Apenas ela emite certificados, o Let's Encrypt tem apenas o IP dela no desafio. Isso simplifica todas as verificações DNS e permite que o servidor dedicado seja completamente invisível da internet nas portas 80/443.
  3. Camada de isolamento adicional. Se alguém começar um ataque DDoS – ele ataca o nó de saída, não o servidor dedicado. Tenho dados mínimos no nó de saída, recriá-lo leva 10 minutos.
  4. Separação do front público do backend. Posso tranquilamente executar atualizações do Caddy / experimentar no servidor dedicado, enquanto a interface real com a internet está separada e estável.

Uma desvantagem: adiciona ~5-15 ms a cada solicitação devido a um salto extra. Para a web, isso é imperceptível.

Também para alguns serviços, há um Caddy direto no host nas portas 80/443 sem o nó de saída – para aqueles domínios que não preciso encaminhar através do ponto de saída (por exemplo, endpoints de status, monitoramento, serviço onde o DNS já aponta para o servidor dedicado). Isso funciona em paralelo: o Caddy no host escuta tanto :8080 (interno do nó de saída) quanto :80/:443 (direto da internet), os roteamentos são diferentes.

Migração: como eu migrei sem lágrimas e quase sem downtime

Esta foi a etapa mais assustadora. Cinco servidores, cerca de trinta serviços, um fórum de produção com usuários ativos, faturamento com assinaturas ativas, bancos de dados que de forma alguma poderiam ser perdidos.

Estratégia – migração de um serviço por vez, na ordem "do menos crítico para o mais crítico":

  1. Primeiro migraram pequenas ferramentas e sites estáticos (se algo acontecer – ninguém notará).
  2. Em seguida, bots e serviços em segundo plano (também toleram um minuto de downtime).
  3. Em seguida, bancos de dados (com restauração verificada previamente).
  4. Em seguida, aplicações que dependem desses bancos de dados.
  5. Por último – o fórum principal com uma longa rodada final de sincronização e troca de DNS.

Canal de migração

Primeiro, eu simplesmente configurei o NetBird nos servidores antigos. Isso resolveu duas coisas imediatamente: posso acessar com segurança via SSH nas redes internas, e rsync passa pelo WireGuard via NetBird, sem expor dados à internet aberta.

O comando de batalha para cada serviço foi aproximadamente:

bash
1# Do novo servidor dedicado, via IP NetBird do servidor antigo:
2rsync -avzP --delete \
3  -e "ssh -p 5322" \
4  root@100.76.108.210:/var/discourse/shared/standalone/ \
5  /target/discourse/shared/standalone/

Para bancos de dados – dump + restore, não cópia de arquivos. Nunca copie arquivos Postgres/MySQL "quentes", isso é um bilhete para o inferno.

bash
1# No antigo
2docker exec -it shm-vsem-mysql mysqldump -u root -p shm-vsem | \
3  gzip > /tmp/shm-vsem.sql.gz
4
5# No novo, via NetBird
6scp -P 5322 root@100.76.108.210:/tmp/shm-vsem.sql.gz /tmp/
7zcat /tmp/shm-vsem.sql.gz | docker exec -i shm-vsem-mysql mysql -u root -p shm-vsem

Para o Discourse – discourse backup / discourse restore nativo via ./launcher enter app. Dentro, ele mesmo coleta corretamente o dump do Postgres + uploads + configurações, e restaura da mesma forma.

Troca de DNS

Depois que o serviço foi configurado no novo local e verificado que ele funciona no endereço interno – eu executei ambas as instalações em paralelo por 5-15 minutos, para observar a sincronização dos dados, e então troquei o DNS para o novo servidor. Eu reduzi o TTL dos registros para 60-300 segundos um dia antes da troca.

Para o Discourse, que tem usuários ativos postando constantemente, fiz assim:

  1. Configurei tudo no novo local.
  2. Executei a validação (login, postagem, upload de arquivos para S3, busca).
  3. Na instalação antiga, ativei o read_only_mode (Discourse faz isso pronto para uso).
  4. Fiz o rsync final dos uploads + dump final do banco de dados.
  5. Configurei no novo, desliguei o read-only.
  6. Troquei o DNS.
  7. Na instalação antiga, não mexi em nada por mais uma semana – caso "e se".

Downtime real para os usuários – cerca de dois minutos por serviço.

Surpresas no caminho

  • Permissões com pct restore. O LXC sob unprivileged 1 mapeia UIDs com um deslocamento de 100000. Se no servidor antigo seus arquivos estavam sob UID 1000 – no novo eles estarão sob UID 101000, e a aplicação não os verá. Isso é resolvido com chown após o restore, ou com --unprivileged 0 se você entender os riscos.
  • Docker ipv6 nas VMs OVH às vezes configurava incorretamente – resolvi desativando o ipv6 no daemon Docker ("ipv6": false).
  • Tempo nas VMs. Algumas vezes peguei desvios no tempo do sistema entre o host e a VM, o que quebrava TLS e assinaturas. Remédio – systemd-timesyncd ou chrony em cada VM, e host.use-time no agente Proxmox.
  • Migração do Discourse entre duas versões. Se o Discourse no servidor antigo for mais recente do que o que você configurou no novo – o restore não funcionará. A versão deve ser igual ou superior na nova instalação.
  • Registro de imagens para Dokploy. Quando migrei os metadados do Dokploy através do dump dokploy-postgres, no banco de dados permaneceram links para o registro local antigo no IP antigo. As aplicações ao tentar iniciar acessavam 100.76.117.115:5000 e falhavam com No such image. Solução – reconstruir cada aplicação na UI do Dokploy novamente; a compilação local coloca a imagem já no novo servidor.

Backups: PBS dentro do mesmo servidor dedicado + offsite

Houve uma discussão filosófica separada comigo mesmo: fazer backup no mesmo hardware ou não. Resposta: sim e não.

Nível 1 – ZFS snapshots no próprio pool. São quase gratuitos (copy-on-write), feitos instantaneamente, restaurados instantaneamente. Eu mantenho snapshots automáticos de rpool/data a cada 15 minutos com retenção de 24 horas, mais diários com retenção de uma semana. Usa-se zfs-auto-snapshot. Proteção contra "ops, acabei de apagar o BD de produção":

bash
1apt install zfs-auto-snapshot
2# Depois disso, ele mesmo cria frequent/hourly/daily/weekly/monthly via cron

Nível 2 – Proxmox Backup Server em um LXC separado no mesmo host. São backups incrementais completos de VM/LXC via vzdump, deduplicados no nível de blocos. O PBS armazena os snapshots em um dataset ZFS separado, os vê como um repositório, cada VM tem sua própria cadeia de incrementos.

Configuração no Proxmox: Datacenter → Backup → Add. Horário: todos os dias às 4 da manhã, retenção keep-daily=7 keep-weekly=4 keep-monthly=3. Tudo isso com o mouse.

Colocar o PBS em um LXC no mesmo host – um compromisso. Vantagem: não precisa de hardware separado, o backup vai via localhost, a velocidade é como a de um SSD local, retenção/deduplicação funciona perfeitamente. Desvantagem: se o servidor dedicado inteiro morrer – os backups também morrem. Por isso existe...

Nível 3 – sincronização do repositório PBS para S3 offsite. O PBS tem a capacidade de sync job para armazenamento compatível com S3. Todas as noites, eu copio os snapshots para um bucket separado no S3 da Selectel (pode ser qualquer um – Backblaze, Wasabi, Cloudflare R2). A retenção lá é de duas semanas, porque não é necessário mais: para longo prazo, há o PBS local, e o offsite – é um seguro contra "todo o data center pegou fogo".

Nível 4 – dados das aplicações separadamente. O Discourse em si faz seus próprios backups e os coloca no S3 (esta é sua funcionalidade nativa). Assim, mesmo que o PBS e todo o servidor dedicado desapareçam – eu ainda tenho dumps consistentes do Discourse em sua nuvem.

bash
1# Restaurar uma VM inteira do PBS – literalmente um comando:
2pvesm list backup-pbs    # ver o que existe
3qmrestore backup-pbs:backup/vzdump-qemu-201-2026_04_06-04_00_03.vma.zst 999 \
4  --storage local-zfs
5# e em um minuto você tem uma cópia do fórum-VM no momento das 4 da manhã rodando na VMID 999.

Este é um ponto crítico: backups que você não tentou restaurar – não são backups. Uma vez por mês eu faço um restore de teste de uma VM aleatória em uma VMID vazia, verifico que ela inicia, que a aplicação nela funciona, e a excluo. Chato, mas uma vez exatamente assim eu descobri que um dos crons escreve em /tmp/..., que é omitido durante o backup, e a aplicação após o restore requer uma etapa manual.

Monitoramento

Eu não gosto de montar compilações como Prometheus + Grafana + Alertmanager + Loki quando tenho 15 máquinas. Por isso, parei em três ferramentas leves em um único LXC:

  • Beszel – coleta métricas dos agentes em cada VM (CPU, RAM, discos, interfaces de rede, contêineres Docker). O hub vive no LXC, os agentes – em cada VM/LXC via unidade systemd. O Beszel tem sua própria autenticação, via PocketBase, o que às vezes é inconveniente (veja abaixo sobre os problemas), mas no geral funciona.
  • Uptime Kuma – verificações por HTTP/HTTPS/Ping/TCP. Tenho tudo o que é público (domínios), todos os serviços internos (via NetBird), e pings para todos os nós da malha. Alertas – no Telegram.
  • Homarr – página inicial com links para todas as interfaces de administração. Para não ter que lembrar qual porta está a UI do PBS, qual a do Dokploy, qual a do Vaultwarden. Simplesmente abro o Homarr e clico.

Todos os três no mesmo Docker compose, no mesmo LXC, acessíveis apenas via NetBird.

Problema com Beszel, para que você não o encontre: o Beszel tem duas tabelas de usuários no PocketBase – _superusers (para CLI/API) e users (para a interface web). Se você redefinir a senha via CLI superuser upsert – você redefine apenas os _superusers, e na UI você faz login via users e a senha não funciona. Isso é corrigido com uma requisição PATCH para /api/collections/users/records/<id> via API REST.

O que eu obtive no final

Após cerca de três semanas de migração, quando os últimos serviços se estabilizaram, fiz um balanço:

ParâmetroAntesDepois
Servidores / contas5 de 3 provedores1 servidor dedicado + 1 micro-VPS
Pagamentos por mês~$X~$X/2
Recursos livres"parece que é suficiente"8 vCPUs e 30 GB de RAM em reserva
Backupsrsync-cron para S3 em cada VPSPBS + offsite + snapshots ZFS
Restauração"bem, um dia mais ou menos"2-5 minutos por VM do PBS
Acesso SSH5 portas e chaves diferentesuma malha NetBird com SSO
Isolamento de serviçoslixo comumcada um em sua própria VM/LXC
Snapshot antes da atualização"ore"qm snapshot 201 pre-update
Interface web para tarefas rotineirasque interface web?UI do Proxmox

O principal que isso me deu emocionalmente – parei de ter medo de mexer em algo. Qualquer ação perigosa (atualização, migração, experimento) agora começa com um snapshot e termina com um commit ou um rollback em 30 segundos. Comecei a experimentar novidades com mais frequência, porque o custo do erro caiu uma ordem de magnitude.

Checklist, se você for repetir

Se você se pega com os mesmos sintomas que eu – aqui está um breve checklist, em qual ordem faz sentido seguir:

  1. Calcule quanto você paga por todas as VPS juntas, e compare com os preços dos servidores dedicados da OVH/Hetzner/LeaseWeb. Você se surpreenderá.
  2. Pegue RAM ECC, se planeja usar ZFS. Não economize.
  3. Pegue pelo menos dois discos em espelho. Um disco – não é uma opção para produção.
  4. Instale o Proxmox via KVM/IPMI, não via rescue + debootstrap. Menos dor de cabeça.
  5. Imediatamente configure chaves SSH, porta não padrão, desative senhas, instale fail2ban.
  6. Imediatamente limite o ZFS ARC. Por padrão, ele consumirá metade da RAM.
  7. Crie um segundo bridge vmbr1 para a rede privada com NAT. Todas as VMs/LXCs para lá. Sem IPs públicos nas máquinas virtuais.
  8. Configure o NetBird (ou Tailscale, ou Headscale) antes de começar a migrar. Este será seu canal de migração e acesso administrativo.
  9. Não abra a UI do Proxmox para o exterior. Apenas via malha VPN.
  10. Uma pequena VPS de saída em outro provedor para terminação TLS e contornar bloqueios – não é obrigatório, mas muito conveniente. O preço é irrisório, os benefícios são muitos.
  11. PBS em um LXC separado + sincronização offsite para S3. Backups devem ser automáticos.
  12. Pelo menos uma vez por mês, faça um restore de teste. Caso contrário, você não tem backups, mas arquivos para autoconfiança.
  13. Migre um serviço por vez, em ordem crescente de criticidade. Não tente "mover tudo em um fim de semana".
  14. Reduza o TTL do DNS um dia antes da troca, não uma hora antes.
  15. Mantenha documentação para cada serviço: onde estão as configurações, como iniciar, como fazer backup, como restaurar. Daqui a seis meses, você agradecerá a si mesmo.

O que ainda resta a fazer

Para ser completo: a migração ainda não está 100% concluída. Restam:

  • Alguns painéis Remnawave do servidor antigo (planejado para o próximo fim de semana).
  • Migração do Caddy com plugins (há uma compilação customizada), por enquanto está funcionando temporariamente.
  • CrowdSec antigo – estou instalando separadamente do zero, não migrando.

Mas tudo o que é crítico (fóruns, faturamento, bots, bancos de dados) – já está no servidor dedicado, funcionando de forma estável, com backup e monitoramento.

Se você tiver perguntas sobre etapas específicas, configurações ou problemas que encontrei com mais detalhes – escreva nos comentários, tentarei explicar. Especialmente interessante ouvir como vocês resolvem problemas semelhantes em outros hipervisores (XCP-ng, ESXi, ou totalmente em Docker Swarm puro) – talvez eu esteja perdendo algo.

Boa sorte com a consolidação de suas infraestruturas. Menos contas, mais controle – vale a pena.

~17 min read · scroll to continue ↓

## discussion

$ topics --entity=article0
sign in to start or join a discussion
No discussions yet — start one to break the ice.
↑↓ nav open⌘K palettei install? help