Um servidor de laboratório, três papéis de confiança, um domínio de falha
Uma entrada VPN, serviços privados e trabalhos de CI precisam de privilégios separados mesmo em um servidor. Divida os papéis, isole as redes e mantenha a recuperação pelo console.
Tudo funciona até o executor de build precisar do mesmo socket de host que o convidado VPN usa, e então ninguém consegue explicar por que um trabalho pode ler as chaves do gateway. Tudo foi instalado em uma máquina porque cabia, e cada convidado recebeu acesso amplo porque era o jeito mais rápido de fazer funcionar. O resultado é um host cuja fronteira de confiança é o cabo de energia. Dividir os papéis dá menos trabalho do que parece, e começa por nomeá-los.
Três papéis que hoje compartilham tudo
Uma entrada VPN, um conjunto de serviços privados e um executor de build querem coisas diferentes. A primeira precisa de uma porta pública e de uma rede estreita do lado privado. O segundo precisa de armazenamento persistente e dos segredos da aplicação. O terceiro executa código que outra pessoa escreveu.
Dar o mesmo acesso aos três é o que torna o sintoma confuso, porque então qualquer um deles pode afetar os outros. Um trabalho de build que alcança o socket do hipervisor é um trabalho que pode parar a VPN. Um convidado de serviços com rota para a rede de gerenciamento pode mudar a configuração do switch. O problema são os privilégios, e a lista de processos é apenas onde isso aparece. Nomear os papéis primeiro dá a cada privilégio um lugar para morar.
O esboço abaixo é um ponto de partida para essa divisão, não uma promessa de alta disponibilidade. Trate-o como hipótese a verificar, não como o desenho final.
Divida três papéis, não três processos
Três convidados em um host dão três conjuntos de privilégios e três posições de rede. Eles não dão três domínios de falha, e o desenho deve dizer isso em voz alta.
A separação só ajuda se o comprometimento de um convidado não conceder os outros automaticamente, e isso é uma configuração do hipervisor, não uma convenção de nomes. Chamar uma VM de gateway não impede outro convidado de alcançar o host. Leia a configuração do switch virtual em vez do nome do host e depois confirme que cada convidado está onde você pensa.
host
├─ vpn-gw 10.60.10.2/24 public 51820/udp only
├─ services 10.60.0.10/24 no route to the management network
└─ ci-runner 10.60.20.2/24 outbound only, no host socket
Escreva a topologia e depois verifique-a com as ferramentas que a controlam. Um convidado que aparece na bridge errada é um achado, não um detalhe. Corrija a rede antes de mudar qualquer configuração de serviço.
Deixe o convidado VPN abrir apenas as portas que são dele
Publique a porta do túnel no roteador e nada mais. As portas de administração dos convidados ficam em um caminho de gerenciamento, não na internet, e a interface do próprio hipervisor também fica lá.
A rede do lado privado deve alcançar os serviços de que os usuários remotos precisam e parar por aí. A autenticação da aplicação continua ligada, porque um túnel é transporte e não login. Mantenha a tabela de rotas do convidado VPN pequena o bastante para descrevê-la em uma frase. Se você não consegue descrevê-la assim tão simples, a fronteira já se desfez.
virsh net-list --all
virsh net-dumpxml lab-private
sudo nft list ruleset | grep -n -E '51820|10.60'
Tudo o que escuta no host e não é necessário para gerenciamento não deveria estar escutando. Isso inclui a API do hipervisor, que é fácil deixar exposta em uma interface pública.
Trabalhos de build precisam de outro tipo de fronteira
Um trabalho de CI executa comandos controlados pelo repositório, então sua confiança depende de quem pode enviar código. Um executor de shell roda esses comandos como o usuário do runner no host, que é a fronteira mais ampla disponível.
Executores de contêiner são mais estreitos, e um contêiner privilegiado não é um dos estreitos. Mantenha o runner em seu próprio convidado com seu próprio escopo de rede e dê a ele apenas o acesso a artefatos e implantação de que os trabalhos precisam. Trabalhadores descartáveis reduzem o estado retido; não reduzem a alcançabilidade nem a exposição de segredos. Ambos ainda precisam de limites explícitos.
O convidado de serviços é dono dos dados, então o plano de backup dele é o que precisa funcionar. Mantenha repositórios, uploads e o banco de dados no mesmo agendamento. Teste uma restauração em vez de ler o status do trabalho.
Planeje a falha que os três compartilham
Um host é um domínio de falha. Um reboot remove o túnel e todos os serviços privados no mesmo instante, que é exatamente quando um caminho de entrada mais importa.
Mantenha acesso ao console que não dependa do convidado VPN, seja um console físico, uma interface de gerenciamento fora de banda ou um console do provedor. Um snapshot guardado no mesmo disco não é uma cópia independente, e também não é um backup que roda dentro do convidado que ele protege. Depois teste a inicialização a frio como uma sequência, não como uma lista de verificação: host, redes virtuais, caminho do túnel e uma aplicação nomeada sob uma conta comum.
virsh list --all
systemctl is-active libvirtd
curl -sS -m 5 -o /dev/null -w '%{http_code}\n' https://10.60.0.10/
ss -ltnp | grep -E ':51820|:443'
A ordem de início dos processos não prova nada sobre rotas e DNS, então teste o caminho em vez dos estados das unidades. O caminho é o que um usuário remoto realmente precisa.