O teu túnel WireGuard está a funcionar. Mas perguntas-te: quantos Mbps atinge no pico? Que peers se conectam e quando? O VPS da Contabo realmente atinge os 200 Mbps anunciados? Poderias abrir um terminal e tail -f journalctl sempre, ou instalar uma stack Prometheus + Grafana em 30 minutos que te dá respostas visuais, alertas sobre incidentes e mantém histórico.
Este guia implementa uma configuração de nível de produção para um VPS S da Contabo. node_exporter para o sistema, wireguard_exporter para os peers, Prometheus para armazenamento, Grafana para visualização, Alertmanager + webhook do Discord para alertas.
Porque monitorizar uma VPN auto-hospedada (e não apenas olhar para wg show)
Executar wg show num terminal dá-te o estado instantâneo: peers conectados, último handshake, total de bytes trocados desde o início do túnel. Útil para um debug pontual, mas nunca te dirá quanto de largura de banda usaste ontem às 22h, qual peer monopoliza o teu upload por três dias, ou se a tua latência Paris-Nuremberga duplicou silenciosamente devido a um peering BGP quebrado no upstream da Contabo. Para isso, precisas de séries temporais: registar uma métrica a cada 15 segundos, manter 30 dias de histórico e ser capaz de consultar "throughput médio entre as 18h e as 22h nas últimas duas semanas úteis". É exatamente isso que o Prometheus faz, e é exatamente por isso que o Grafana existe sobre ele.
Outra razão subestimada são os alertas proativos. Sem monitorização, descobres um túnel quebrado quando um peer te envia uma mensagem no Telegram dizendo "não funciona para mim". Com Alertmanager + um webhook do Discord, recebes a notificação no minuto seguinte à falha, geralmente antes que os teus utilizadores percebam. Os tipos de incidentes que isto deteta precocemente: um OOM no processo WireGuard desencadeado por um peer mal configurado a abrir centenas de conexões paralelas, um disco a encher-se silenciosamente devido a uma rotação de logs quebrada, ou um corte no upstream durante uma manutenção não anunciada. Sem monitorização, diagnosticar esses casos é uma luta.
Finalmente, esta é a base da transparência para os utilizadores. Se hospedas uma VPN para a tua família ou empresa, ser capaz de lhes mostrar um dashboard público de leitura apenas com uptime + largura de banda consumida dá credibilidade que ninguém oferece no lado do consumidor (a NordVPN não publica o seu uptime, a ExpressVPN também não).
Arquitetura
Tudo corre no mesmo VPS da Contabo. Três processos systemd:
- node_exporter (porta 9100): métricas do sistema (CPU, RAM, disco, rede)
- wireguard_exporter (porta 9586): métricas dos peers do WireGuard (handshake, bytes_in/out, last_seen)
- prometheus (porta 9090): recolhe dados dos exporters a cada 15s, retém 30 dias
- grafana (porta 3000): dashboards
- alertmanager (porta 9093): regras de alerta + webhook do Discord
Custo: ~250 MB RAM, ~3% CPU constante num VPS de 4 vCPU. Sem impacto perceptível no túnel.
Passo 1 — Instalar node_exporter
# No VPS, com sudo
sudo useradd --no-create-home --shell /usr/sbin/nologin node_exporter
cd /tmp
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xzf node_exporter-1.8.2.linux-amd64.tar.gz
sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
unidade systemd /etc/systemd/system/node_exporter.service:
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter --web.listen-address=127.0.0.1:9100
[Install]
WantedBy=multi-user.target
Importante: ligamos em 127.0.0.1 (não 0.0.0.0) — sem exposição pública. O Prometheus acede via localhost.
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://127.0.0.1:9100/metrics | head -20
# Deve retornar métricas como "node_cpu_seconds_total"
Passo 2 — Instalar prometheus-wireguard-exporter
O exporter que usamos: github.com/MindFlavor/prometheus_wireguard_exporter (Rust, ~3 MB binário, recolhe a saída de wg show).
cd /tmp
wget https://github.com/MindFlavor/prometheus_wireguard_exporter/releases/download/3.6.6/prometheus_wireguard_exporter_3.6.6_linux_amd64.tar.gz
tar xzf prometheus_wireguard_exporter_3.6.6_linux_amd64.tar.gz
sudo cp prometheus_wireguard_exporter /usr/local/bin/
sudo chmod +x /usr/local/bin/prometheus_wireguard_exporter
unidade systemd /etc/systemd/system/wireguard_exporter.service:
[Unit]
Description=WireGuard Prometheus Exporter
After=network.target wg-quick@wg0.service
Requires=wg-quick@wg0.service
[Service]
User=root
ExecStart=/usr/local/bin/prometheus_wireguard_exporter -a 127.0.0.1 -p 9586 -n /etc/wireguard/wg0.conf
Restart=on-failure
[Install]
WantedBy=multi-user.target
A flag -n /etc/wireguard/wg0.conf permite que o exporter use nomes de peers (comentados no .conf) como etiquetas do Prometheus. Mais legível no Grafana do que chaves públicas.
sudo systemctl daemon-reload
sudo systemctl enable --now wireguard_exporter
curl -s http://127.0.0.1:9586/metrics | grep wireguard_
# Deve retornar wireguard_sent_bytes_total, wireguard_received_bytes_total, etc.
Passo 3 — Instalar Prometheus
sudo useradd --no-create-home --shell /usr/sbin/nologin prometheus
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown prometheus:prometheus /etc/prometheus /var/lib/prometheus
cd /tmp
wget https://github.com/prometheus/prometheus/releases/download/v2.55.1/prometheus-2.55.1.linux-amd64.tar.gz
tar xzf prometheus-2.55.1.linux-amd64.tar.gz
sudo cp prometheus-2.55.1.linux-amd64/prometheus /usr/local/bin/
sudo cp prometheus-2.55.1.linux-amd64/promtool /usr/local/bin/
sudo chown prometheus:prometheus /usr/local/bin/prometheus /usr/local/bin/promtool
Configuração /etc/prometheus/prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- 127.0.0.1:9093
rule_files:
- "alert_rules.yml"
scrape_configs:
- job_name: prometheus
static_configs:
- targets: [127.0.0.1:9090]
- job_name: node
static_configs:
- targets: [127.0.0.1:9100]
labels:
instance: vps-contabo-nuremberg
- job_name: wireguard
static_configs:
- targets: [127.0.0.1:9586]
labels:
instance: vps-contabo-nuremberg
Regras de alerta /etc/prometheus/alert_rules.yml:
groups:
- name: vpn_alerts
interval: 30s
rules:
- alert: HighCPU
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
annotations:
summary: "CPU > 80% em {{ $labels.instance }}"
- alert: WireGuardPeerDown
expr: time() - wireguard_latest_handshake_seconds > 600
for: 5m
annotations:
summary: "Peer WG {{ $labels.peer }} não fez handshake em >10min"
- alert: HighBandwidth
expr: rate(node_network_transmit_bytes_total{device="eth0"}[5m]) * 8 > 180000000
for: 10m
annotations:
summary: "Largura de banda > 180 Mbps em eth0 — a aproximar-se do limite da Contabo"
- alert: DiskAlmostFull
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 15
for: 10m
annotations:
summary: "Disco < 15% livre em {{ $labels.instance }}"
unidade systemd /etc/systemd/system/prometheus.service:
[Unit]
Description=Prometheus
After=network.target
[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
--config.file /etc/prometheus/prometheus.yml \
--storage.tsdb.path /var/lib/prometheus/ \
--storage.tsdb.retention.time=30d \
--web.listen-address=127.0.0.1:9090
[Install]
WantedBy=multi-user.target
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml /etc/prometheus/alert_rules.yml
sudo systemctl daemon-reload
sudo systemctl enable --now prometheus
sudo systemctl status prometheus
Passo 4 — Instalar Grafana
sudo apt install -y apt-transport-https software-properties-common
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/grafana.gpg
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt update
sudo apt install -y grafana
Edita /etc/grafana/grafana.ini para ligar apenas ao localhost:
[server]
http_addr = 127.0.0.1
http_port = 3000
sudo systemctl enable --now grafana-server
Passo 5 — Aceder ao Grafana de forma segura
Em vez de abrir a porta 3000 publicamente, túnel SSH a partir do teu portátil:
ssh -L 3000:127.0.0.1:3000 eric@vpn.example.com
Depois abre http://127.0.0.1:3000 no teu navegador local. Login admin / admin (muda imediatamente).
Alternativa: aceder via o túnel WireGuard. Se o teu VPS é 10.66.66.1 no lado da VPN, acede a http://10.66.66.1:3000 a partir de qualquer peer conectado. Nenhuma porta exposta à Internet pública.
Passo 6 — Configurar a fonte de dados do Prometheus
No Grafana:
- Definições → Fontes de Dados → Adicionar fonte de dados → Prometheus
- URL:
http://127.0.0.1:9090 - Guardar & Testar → "Fonte de dados está a funcionar"
Passo 7 — Importar dashboards
Dashboards prontos a usar:
- Node Exporter Full: ID
1860no grafana.com — métricas completas do sistema - WireGuard: ID
12557ou mais recente — peers, largura de banda, last_seen
No Grafana: Dashboards → Importar → colar o ID → escolher a fonte de dados Prometheus → Importar.
Para um dashboard personalizado de VPS-VPN, publicámos o nosso JSON no GitHub (link no repositório VPNSmith). Contém:
- Visão geral: RAM/CPU/disco/uptime
- Largura de banda eth0 (in/out, 1h/24h/7d)
- Peers do WireGuard: nome, último handshake, bytes trocados
- Principais peers por uso
- Alertas ativos
Passo 8 — Alertas do Discord via webhook
Instalar Alertmanager:
cd /tmp
wget https://github.com/prometheus/alertmanager/releases/download/v0.27.0/alertmanager-0.27.0.linux-amd64.tar.gz
tar xzf alertmanager-0.27.0.linux-amd64.tar.gz
sudo cp alertmanager-0.27.0.linux-amd64/alertmanager /usr/local/bin/
sudo cp alertmanager-0.27.0.linux-amd64/amtool /usr/local/bin/
sudo useradd --no-create-home --shell /usr/sbin/nologin alertmanager
sudo mkdir -p /etc/alertmanager /var/lib/alertmanager
sudo chown alertmanager:alertmanager /etc/alertmanager /var/lib/alertmanager
Configuração /etc/alertmanager/alertmanager.yml:
global:
resolve_timeout: 5m
route:
receiver: discord
receivers:
- name: discord
webhook_configs:
- url: 'https://discord.com/api/webhooks/XXXXXXX/YYYYYYY?wait=true'
send_resolved: true
Gera o webhook do Discord: Definições do Servidor → Integrações → Webhooks → Novo Webhook. Copia o URL. O formato bruto do Prometheus não é bonito no Discord — usamos a ponte alertmanager-discord ou um parser simples que produz embeds limpos no Discord.
unidade systemd /etc/systemd/system/alertmanager.service:
[Unit]
Description=Alertmanager
After=network.target
[Service]
User=alertmanager
Group=alertmanager
Type=simple
ExecStart=/usr/local/bin/alertmanager \
--config.file=/etc/alertmanager/alertmanager.yml \
--storage.path=/var/lib/alertmanager \
--web.listen-address=127.0.0.1:9093
[Install]
WantedBy=multi-user.target
sudo chown alertmanager:alertmanager /etc/alertmanager/alertmanager.yml
sudo systemctl daemon-reload
sudo systemctl enable --now alertmanager
Consultas úteis para um VPS VPN
No Grafana, estas consultas Prometheus são as mais úteis no dia-a-dia:
Largura de banda total do WireGuard (Mbps):
rate(wireguard_sent_bytes_total[5m]) * 8 / 1e6 + rate(wireguard_received_bytes_total[5m]) * 8 / 1e6
Top 5 peers por bytes recebidos (24h):
topk(5, increase(wireguard_received_bytes_total[24h]))
Último handshake por peer (humanizado):
time() - wireguard_latest_handshake_seconds
Utilização de CPU %:
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Uso de disco %:
100 - (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100
Backup e retenção
O Prometheus mantém 30 dias por padrão (--storage.tsdb.retention.time=30d). Além disso, ou aumentas a retenção (adicionas disco) ou fazes downsample com Thanos ou VictoriaMetrics (exagero para um VPS pessoal).
/var/lib/prometheus/ consome ~50-100 MB por dia para esta stack. Em 30 dias, ~2-3 GB no máximo. O teu VPS da Contabo tem 50 GB NVMe, margem de sobra.
Reforço adicional
- fail2ban no Grafana: cria um filtro para tentativas de login. 5× autenticação falhada → ban de 15 minutos.
- Proxy reverso com autenticação básica: Caddy ou Nginx à frente do Grafana se quiseres partilhar o dashboard com um colega sem túnel SSH. Mas sempre prefere o túnel WireGuard se possível.
- TLS: se expuseres o Grafana fora da LAN/túnel, certbot + Caddy em 5 minutos.
Veredicto
Com esta stack, obténs visibilidade em tempo real de tudo o que passa na tua VPN VPS. Vês imediatamente quando um peer transfere 200 GB durante a noite (provavelmente um ISO Linux, ou backup Plex), quando o CPU dispara (frequentemente um OOM mal configurado), quando um peer não fez handshake em 1h (cliente morto ou ausente).
São 30 minutos de configuração uma vez, para uma paz de espírito duradoura num VPS S da Contabo com o seu link anunciado de 200 Mbit/s.
Para começar:
- Configuração do Contabo VPS + WireGuard em 20 min
- Templates prontos a usar do WireGuard
- Interruptor de segurança Netfilter para nunca vazar
O VPS que recomendamos: Contabo VPS S Cloud — 4.99 €/mês, link anunciado de 200 Mbit/s, jurisdição GDPR alemã. Vê a nossa revisão completa do VPS Contabo.
★ Datacenter GDPR em Nuremberg · ✓ IPv4 dedicado incluído · 200+ Mbps garantidos
Self-host your VPN on your own VPS → ContaboFull root access · public IPv4 · pick your region→