Implantação de Zabbix Proxy 7.0 (PostgreSQL, TLS PSK) em LXC sob Proxmox
- Categoria: Segurança / Monitoramento / NOC
- Última revisão: 21/08/2026
- Responsável: EdenCore (desenvolvido por Daniel Selbach Figueiró)
- Ver também: Integrações do Zabbix Proxy (SNMP e Grafana)
Todos os nomes de host, IPs, senhas e identificadores neste documento são fictícios. Substitua pelos valores reais do ambiente antes de aplicar qualquer comando.
1. Contexto
Este documento descreve a implantação de um Zabbix Proxy 7.0, incluindo banco PostgreSQL, criptografia TLS PSK entre proxy e server e hardening de firewall com nftables.
O proxy sobe em um container LXC no Proxmox, com Debian 13 (Trixie) como sistema operacional. Esse ponto importa porque o confinamento aplicado pelo LXC sob Proxmox pode restringir a criação de mount namespace por alguns serviços systemd, independentemente de o container ser privileged ou unprivileged, detalhado na seção 4.
O proxy roda em modo ativo: ele inicia a conexão com o Zabbix server, nunca o contrário. Isso evita expor qualquer porta de entrada no proxy voltada para a internet, o que é preferível quando o proxy fica atrás de NAT ou numa rede sem IP público dedicado.
Topologia de referência:
- Zabbix server:
mon.exemplo.com.br(203.0.113.10), hospedado em nuvem - Zabbix proxy:
ZBXPROXY-EXEMPLO-HQ(10.10.9.252), container LXC (Debian 13 Trixie) no Proxmox - Escritório administrativo:
198.51.100.20
2. Instalação do Zabbix Proxy
Referência oficial: Zabbix Documentation 7.0 — Install e DB scripts.
2.1. Repositório e pacotes
wget https://repo.zabbix.com/zabbix/7.0/debian-arm64/pool/main/z/zabbix-release/zabbix-release_latest_7.0+debian13_all.deb
dpkg -i zabbix-release_latest_7.0+debian13_all.deb
apt update
apt install zabbix-proxy-pgsql zabbix-sql-scripts
Ajuste o caminho do pacote (debian-arm64 neste exemplo) para a arquitetura real do container. Instale também o servidor PostgreSQL, caso ainda não esteja presente no ambiente:
apt install postgresql
2.2. Banco de dados
Conforme a documentação oficial, crie o usuário e o banco no host de banco de dados:
sudo -u postgres createuser --pwprompt zabbix
sudo -u postgres createdb -O zabbix zabbix_proxy
Em containers LXC sem o pacote sudo instalado, substitua por:
su - postgres -c "createuser --pwprompt zabbix"
su - postgres -c "createdb -O zabbix zabbix_proxy"
Importe o schema inicial:
cat /usr/share/zabbix-sql-scripts/postgresql/proxy.sql | sudo -u zabbix psql zabbix_proxy
Duas observações práticas que a documentação oficial não cobre, mas que aparecem com frequência:
- Se o banco for criado sem especificar encoding, o PostgreSQL herda o padrão do sistema, às vezes
SQL_ASCII. O Zabbix rejeita esse encoding na inicialização. Force UTF8 na criação:
sudo -u postgres createdb -O zabbix -E UTF8 -T template0 zabbix_proxy
- Se o import do schema for feito por um usuário diferente do dono do banco (por exemplo, via
postgresem vez dezabbix, comum quandosudo -u zabbixfalha por o usuário de sistemazabbixnão ter shell de login), as tabelas ficam com o dono errado e o proxy falha na inicialização compermission denied for table users. Corrija concedendo privilégios explicitamente:
su - postgres -c "psql -d zabbix_proxy -c 'GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO zabbix;'"
su - postgres -c "psql -d zabbix_proxy -c 'GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO zabbix;'"
2.3. Configuração principal
/etc/zabbix/zabbix_proxy.conf:
Server=mon.exemplo.com.br
Hostname=ZBXPROXY-EXEMPLO-HQ
ProxyMode=0
DBName=zabbix_proxy
DBUser=zabbix
DBPassword=<senha_do_banco>
ProxyMode=0 define o modo ativo. Hostname precisa ser idêntico, caractere por caractere, ao Proxy name cadastrado no server em Administration > Proxies. Qualquer divergência gera o erro recorrente proxy "X" not found no log.
2.4. Iniciar o serviço
systemctl restart zabbix-proxy
systemctl enable zabbix-proxy
3. Criptografia TLS PSK
Duas relações de confiança distintas existem nesse desenho, cada uma com sua própria chave. Não reaproveite arquivos entre elas: fazer isso quebra a autenticação de um lado sempre que o outro precisar rotacionar a chave.
| Relação | Arquivo de chave | Configurado em |
|---|---|---|
| Proxy ↔ Server | /etc/zabbix/proxy_psk.key |
zabbix_proxy.conf |
| Agente local ↔ Proxy | /etc/zabbix/agent_psk.key |
zabbix_agent2.conf |
3.1. Gerar a chave proxy-server
openssl rand -hex 32 > /etc/zabbix/proxy_psk.key
chown zabbix:zabbix /etc/zabbix/proxy_psk.key
chmod 400 /etc/zabbix/proxy_psk.key
Adicione ao zabbix_proxy.conf:
TLSConnect=psk
TLSAccept=psk
TLSPSKIdentity=ZBXPROXY-EXEMPLO-HQ
TLSPSKFile=/etc/zabbix/proxy_psk.key
3.2. Cadastro no server
Em Administration > Proxies, crie o proxy com:
- Proxy name:
ZBXPROXY-EXEMPLO-HQ - Proxy mode: Active
- Address for active agents: hostname ou IP do próprio proxy (campo obrigatório mesmo em modo ativo, usado para descoberta de agentes ativos)
- Aba Encryption: marque
Connections from proxycomo PSK, informe a mesma identity e cole o valor da chave gerada
O campo Connections to proxy fica desabilitado por design em modo ativo, já que o server nunca inicia conexão com o proxy nesse cenário.
3.3. Validação
systemctl restart zabbix-proxy
tail -f /var/log/zabbix/zabbix_proxy.log
A linha received configuration data from server confirma que o handshake TLS e a sincronização funcionaram. Erros comuns e suas causas:
connection of type "unencrypted" is not allowed— normalmente indica queTLSPSKFileestá apontando para o arquivo de chave errado (mistura entre a chave do proxy e a do agente local)cannot find requested PSK identity— a identity configurada localmente não bate com a cadastrada no server, ou o proxy ainda não sincronizou a config atualizada
4. Firewall (nftables)
O nftables.service padrão do Debian pode falhar dentro de um container LXC sob Proxmox mesmo com o container configurado como privileged. O sintoma é Failed to set up mount namespacing: Permission denied, código de saída 226/NAMESPACE, causado pelas diretivas ProtectSystem e ProtectHome do unit, que exigem criação de mount namespace. O confinamento aplicado pelo próprio LXC (perfil AppArmor do container) pode bloquear essa operação independentemente de o container ser privileged ou unprivileged.
Uma tentativa comum é neutralizar essas diretivas via override (systemctl edit nftables), mas atenção à sintaxe: valores como ProtectSystem= vazio geram Failed to parse ProtectSystem=, ignoring: Invalid argument no log, e o systemd ignora o override, mantendo a diretiva original ativa. Se esse erro aparecer no journalctl -u nftables, o override não está surtindo efeito.
A correção que funciona de forma consistente não é ajustar o unit original (o bloqueio pode vir do confinamento do LXC, não só do systemd), e sim usar um serviço próprio, sem sandboxing:
cat > /etc/systemd/system/nftables-load.service << 'EOF'
[Unit]
Description=Load nftables ruleset (LXC-safe)
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/nft -f /etc/nftables.conf
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl disable --now nftables 2>/dev/null
systemctl enable --now nftables-load
4.1. Ruleset de referência
#!/usr/sbin/nft -f
# ZBXPROXY-EXEMPLO-HQ - Zabbix Proxy 7
# Modo ativo, sem porta de entrada exposta ao Zabbix server
flush ruleset
table inet filter {
set trusted_ips {
type ipv4_addr
flags interval
elements = {
203.0.113.10, # Zabbix server (nuvem)
198.51.100.20, # Escritório administrativo
10.99.0.0/24 # Rede corporativa (VPN)
}
}
set client_vlans {
type ipv4_addr
flags interval
elements = {
10.10.9.0/24, # VLAN de monitoramento
10.10.20.0/24, # VLAN de servidores internos
10.10.21.0/28, # VLAN de management (hypervisor)
10.10.100.0/24 # VLAN de management (switches/APs)
}
}
chain input {
type filter hook input priority 0; policy drop;
iif "lo" accept
ct state established,related accept
ct state invalid drop
ip protocol icmp icmp type { echo-request, echo-reply, destination-unreachable, time-exceeded } accept
ip saddr @trusted_ips tcp dport 22222 accept
# Itens ativos / heartbeat de agentes vindos das sub-redes monitoradas
ip saddr @client_vlans tcp dport 10051 accept
log prefix "nft-input-drop: " limit rate 5/minute
drop
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy drop;
oif "lo" accept
ct state established,related accept
udp dport 53 accept
tcp dport 53 accept
udp dport 123 accept
ip daddr 203.0.113.10 tcp dport 10051 accept
ip daddr @client_vlans accept
log prefix "nft-output-drop: " limit rate 5/minute
drop
}
}
Pontos de atenção nesse ruleset:
- O
INPUTlibera SSH apenas na porta não padrão22222, já migrada do padrão22. Manter a porta padrão fora do firewall reduz o volume de tentativas automatizadas de brute-force contra o host. - A regra de
client_vlansna porta10051doINPUTexiste porque agentes configurados com item ativo (ServerActive=) iniciam a conexão em direção ao proxy. Sem essa regra, a coleta ativa falha com timeout mesmo que o SNMP e os checks passivos funcionem normalmente. - O
OUTPUTé restritivo por padrão (policy drop), liberando apenas DNS, NTP, o Zabbix server e as sub-redes monitoradas. Isso bloqueia inclusiveapt updatee testes de conectividade genéricos (ex: ping para1.1.1.1), o que é o comportamento esperado. Para rodar updates de sistema, libere temporariamente:
nft insert rule inet filter output position 0 tcp dport { 80, 443 } accept
apt update && apt upgrade -y
nft -f /etc/nftables.conf # remove a regra temporária
Aplicação e teste:
cp nftables-ruleset.conf /etc/nftables.conf
nft -f /etc/nftables.conf
systemctl restart nftables-load
nft list ruleset
Teste sempre em uma sessão SSH separada antes de encerrar a sessão atual, para não perder acesso ao host em caso de erro na regra.
5. Instalação do Zabbix Agent 2
Referência oficial: Zabbix Documentation 7.0 — Install.
Válido tanto para hosts monitorados comuns quanto para o próprio servidor do proxy (seção 6).
5.1. Repositório e pacote
Se o host já tiver o repositório Zabbix configurado (por exemplo, por já ter o proxy instalado), pule direto para a instalação do agente. Caso contrário:
wget https://repo.zabbix.com/zabbix/7.0/debian-arm64/pool/main/z/zabbix-release/zabbix-release_latest_7.0+debian13_all.deb
dpkg -i zabbix-release_latest_7.0+debian13_all.deb
apt update
apt install zabbix-agent2
5.2. Plugins (opcional)
Necessário apenas se o host monitorar serviços específicos como bancos de dados:
apt install zabbix-agent2-plugin-mongodb zabbix-agent2-plugin-mssql zabbix-agent2-plugin-postgresql
5.3. Iniciar o serviço
systemctl restart zabbix-agent2
systemctl enable zabbix-agent2
A configuração de Server=, ServerActive= e TLS PSK é detalhada na seção 3 (para a chave agente-proxy) e na seção 6 (para o caso específico do host que também executa o proxy).
6. Host que acumula proxy e agente monitorado
É comum que o mesmo servidor rode o processo zabbix_proxy e também precise ser monitorado como host comum (CPU, disco, memória do próprio proxy). Isso exige atenção a dois pontos:
Saúde do processo proxy: cadastre um host no server vinculado ao template "Zabbix proxy health", com Monitored by = Proxy (o próprio proxy monitorando a si mesmo, via loopback). Não existe interface de rede nesse host, já que os itens são do tipo "Zabbix internal", calculados localmente por quem avalia o host.
Saúde do sistema operacional: para isso, instale o zabbix-agent2 normalmente no mesmo servidor (seção 5), configurando Server=127.0.0.1 e ServerActive=127.0.0.1. Como a checagem é feita localmente, o tráfego passa pela interface de loopback, que já está liberada por padrão em qualquer ruleset (iif "lo" accept).
Um erro comum nesse cenário é o agente rejeitar conexões vindas do IP real da máquina (não apenas 127.0.0.1), gerando Connection reset by peer. Se o teste for feito a partir do IP de rede em vez do loopback, ajuste Server= para incluir ambos:
Server=127.0.0.1,10.10.9.252
7. Checklist de hardening (implantação)
- [ ] TLS PSK configurado entre proxy e server, com chave exclusiva (não reaproveitada de outro uso)
- [ ] TLS PSK configurado entre agentes e proxy, preferencialmente com chave exclusiva por host
- [ ] Firewall com
INPUTrestrito a origens conhecidas (administração) e sub-redes monitoradas na porta de itens ativos - [ ] Firewall com
OUTPUTrestrito ao Zabbix server, DNS, NTP e as sub-redes monitoradas - [ ] PostgreSQL aceitando apenas conexões locais (
listen_addresses = 'localhost') - [ ] Permissões de arquivo restritas em chaves PSK (
chmod 400) e no config principal (chmod 640) - [ ] Serviço rodando com usuário dedicado (
zabbix), não root - [ ] Atualizações de segurança do sistema operacional agendadas ou aplicadas periodicamente
Para o checklist de integrações (SNMP e Grafana), ver o documento "Integrações do Zabbix Proxy".