
Um servidor pessoal endurecido em camadas, a alojar os meus agentes de IA e projetos 24/7. O meu primeiro projeto a sério com Linux.

O problema que resolve: Eu precisava de um sítio sob o meu controlo para correr os meus agentes e projetos 24/7. Soluções "serverless" ou hosted ficam caras à escala que quero, e não dão o nível de controlo que preciso. A alternativa é um VPS, mas um VPS mal configurado é um convite a ser invadido. Daí o projeto: montar um servidor pessoal seguro o suficiente para confiar nele com tudo. Público-alvo Builders e indie hackers que querem self-hostar a sua infra (agentes, bots, sites, automações) mas sentem que segurança de Linux é uma caixa preta. A ideia de partilhar isto é mostrar que dá para chegar a um setup sólido sem ser sysadmin profissional, apenas com muita curiosidade, paciência e não me contentando com o bom. A filosofia: camadas independentes, não muralhas Cada camada faz uma coisa bem feita; se uma falha, as outras seguram. Seis camadas: 1. Acesso administrativo invisível à internet A maior decisão de segurança foi a mais simples: tirar o SSH da internet. Está atrás de Tailscale (mesh VPN com chaves WireGuard) — quem fizer port scan ao IP público não vê SSH aberto. Em cima disso, o próprio sshd faz bind apenas à interface privada (não a 0.0.0.0), por isso mesmo que o firewall falhasse o SSH continuaria fora do alcance público. Porta não-default, autenticação só por chave pública, root bloqueado, AllowUsers whitelist, cripto moderna apenas (curve25519, chacha20-poly1305, aes256-gcm). 2. Perímetro de rede com ingress controlado UFW deny-by-default em ambas as direcções relevantes (deny incoming + deny routed). Cada porta aberta tem comentário a justificar-se — se não consigo justificar, fecha. Tráfego HTTPS público entra exclusivamente por Caddy, que termina TLS com certificados Let's Encrypt automáticos e faz reverse proxy para serviços internos que escutam só em 127.0.0.1. Webhooks externos (Telegram) só aceitam ligações dos CIDRs oficiais do serviço, não do mundo inteiro. Painéis internos (métricas, dashboards) só são alcançáveis via VPN. 3. Detecção activa CrowdSec (threat intel comunitário, bloqueia IPs com má reputação antes de tocarem em qualquer serviço) + Fail2ban com jail recidive (banimentos progressivamente mais longos para repeat offenders) + auditd para log imutável de chamadas críticas + alertas Telegram em tempo real para logins novos e anomalias. 4. Hardening do kernel (perfil CIS) kptr_restrict, dmesg_restrict, yama.ptrace_scope, tcp_syncookies, rp_filter, anti-broadcast ICMP. Mitigações clássicas que muita gente nunca liga porque "já tenho firewall". 5. Updates + backups + tudo como código unattended-upgrades para patches automáticos. Backups cron diários + snapshot semanal, com alerta se um backup ficar mais de 36h por correr. Stack inteira em Docker Compose + git — qualquer container é descartável, infra reproduzível em ~30 min. 6. Observabilidade que não é só "está vivo?" Configurar segurança é fácil; saber que continua a fazer o que prometeu é a parte difícil. Métricas em tempo real (Netdata, acessível só pela VPN), dashboard próprio regenerado a cada 5 min, e um healthcheck a cada 3 min que verifica: todos os containers críticos (não só o gateway), disco (alerta a 85%), memória (alerta a 90%), latência do bridge HTTPS público (alerta acima dum threshold), e idade do backup mais recente. Cada alerta cai-me no Telegram. O auditd só vale se leres os alertas; o fail2ban só vale se a jail estiver activa. Observabilidade é o que transforma "configurei uma vez" em "sei que continua a funcionar". Diferenciais — o que aprendi - A decisão que mais te protege costuma ser a mais simples. Não foi "configurar 5 ferramentas" — foi tirar o SSH da internet. Tudo o resto é defense-in-depth a complementar. - Considerar a infra descartável vale mais do que tentar nunca rebootar. Em Abril reprovisionei o servidor por completo e em ~30 min estava tudo de pé via Docker Compose + git. Isto vale mais do que três meses de uptime contínuo. - Há diferença entre perímetro e ingress, e a maioria das pessoas confunde. Firewall não é a resposta para "como é que o Vercel chega ao meu endpoint". Termination TLS, reverse proxy, e processos a fazer bind em 127.0.0.1 são. Decidir essa boundary explicitamente — em vez de abrir portas e esperar que o token "chegue" — foi o que separou o setup amador do setup actual. - Auditar a tua própria stack é parte do trabalho, não um extra. Esta semana fiz uma auditoria de portas e encontrei três regras UFW órfãs (legacy de quando tinha um serviço diferente), uma documentação interna que descrevia um nginx reverse-proxy que nunca tinha sido implementado, e um endpoint HTTP exposto que devia estar atrás de HTTPS. Limpei, reescrevi a doc para reflectir a realidade, e migrei o endpoint para um subdomínio dedicado, servido via Caddy com HTTPS end-to-end. Estar a publicar isto e a operá-lo não é incompatível com encontrar problemas no que escrevi há 6 meses — é exactamente o sinal de que o sistema continua vivo. Estado actual (mensurável) - Ao serviço desde 8 de Fevereiro de 2026 — ~3 meses, sem incidentes de segurança. - 0 tentativas falhadas de SSH nas últimas 24h (porque o SSH não é visível à internet). - Dezenas de IPs banidos automaticamente; o CrowdSec apanha a maioria antes do fail2ban. - 1 reprovisão completa, planeada, executada em ~30 min. - Apenas 2 portas abertas à internet (80 para ACME challenges, 443 para o Caddy). Tudo o resto está fechado, em 127.0.0.1, ou só na VPN. Não está acabado — nada nunca está — mas é o que estou orgulhoso de ter agora. Para um primeiro projeto a sério, é o que ensinou mais.
Rúben
CriadorDev
0 pontos acumulados