Harper
PLAN DE FORMACIÓN Departamento de Infraestructura
Tutorial · Zabbix
Tutorial avanzado · Monitoreo

Zabbix 7.0 LTS sobre Proxmox — de la plantilla al primer host monitoreado

Guía completa para desplegar un servidor Zabbix 7.0 LTS en una VM Ubuntu 24.04 dentro del Proxmox del lab. Al terminar tendrás: el servidor y frontend funcionando bajo HTTPS, PostgreSQL como backend, la agente monitoreando el propio host, un cliente Linux monitoreado con template, alertas por email operativas y backup nocturno. Este es el material canónico para instalaciones a cliente.

Zabbix7.0.27 LTS
SOUbuntu 24.04 LTS
BackendPostgreSQL 16
WebNginx + PHP-FPM 8.3
Recursos VM2 vCPU · 4 GB · 40 GB
Fases14
Duración~3–4 horas
Soporte hastaJunio 2029
Arquitectura del stack
flowchart LR subgraph PVE ["Proxmox del lab"] direction TB subgraph VM ["VM 192.168.0.230 - Ubuntu 24.04"] direction TB SRV["zabbix-server
tcp/10051"] FE["nginx + php-fpm
tcp/80 y 443"] AGT["zabbix-agent2
127.0.0.1:10050"] DB[("PostgreSQL 16
127.0.0.1:5432")] FE --> DB SRV --> DB AGT -.-> SRV end end USER["Operador Harper"] -->|"HTTPS 443"| FE HOST1["Host Linux cliente
agent2"] -->|"tcp/10051 push"| SRV HOST2["Otro host cliente"] -->|"tcp/10051 push"| SRV ALERT["Email
infra@har-per.com"] SRV -.->|"triggers - smtp"| ALERT
Tu progreso 0 / 14 · 0%
◆ ¿Por qué Zabbix 7.0 LTS y no 8.0?

Al 2026-07-01, Zabbix 8.0 sigue en Release Candidate (no ha alcanzado GA). Instalar RC en producción es aceptable únicamente en un lab; en cualquier cliente se instala Zabbix 7.0 LTS (7.0.27): soporte activo hasta 2027 y de seguridad hasta junio 2029. Cuando 8.0 lleve ~6 meses en GA (probable inicio de 2027), este tutorial se actualizará y se documentará el path de upgrade 7.0 → 8.0 sin pérdida de datos.

ⓘ Contexto arquitectónico — leer antes de la fase 1

Zabbix se compone de cuatro procesos que corren en la misma VM:

  • zabbix-server — el motor. Recolecta datos, procesa triggers, dispara alertas. Se conecta a la DB.
  • zabbix-agent2 — daemon liviano en cada host monitoreado (incluyendo el propio servidor).
  • frontend PHP — la web UI, servida por Nginx + PHP-FPM. Habla con la DB directamente.
  • PostgreSQL 16 — persistencia. Todo (config, history, eventos) vive aquí.

En clientes grandes conviene separar la DB en otra VM. Para lab y clientes chicos (≤ 200 hosts), todo en una sola VM está bien.

FQDN de la VM
zbx.lab.harper.local
Ajusta al DNS del cliente
IP sugerida
192.168.0.230
IP libre en la red del lab
Puertos abiertos (LAN)
22 · 80 · 443 · 10051
10051 = puerto activo del server hacia agents (tráfico entrante)
Puerto del agent
10050 (en cada host)
Solo abierto en hosts monitoreados hacia el server
DB
postgres 16 · db=zabbix · user=zabbix
Contraseña se genera en la fase 4
Web
https://zbx.lab.harper.local/
Certbot en la fase 10; auto-firmado interno mientras tanto
01

Clonar la VM desde la plantilla cloud-init en Proxmox

Meta: tener una VM Ubuntu 24.04 recién nacida con IP fija, hostname, llave SSH del usuario y updates aplicados — lista para instalar servicios.

1.1 Localizar la plantilla base

En el Proxmox del lab ya existe la plantilla ubuntu-24.04-cloudinit (VMID normalmente 9000). Antes de clonar, confirma que existe y anota su VMID.

Ejecutar enhost: proxmox (SSH root@pve)
qm list | awk 'NR==1 || /template/ || /ubuntu.*24|ubuntu2404|cloudinit/i'
VMID NAME STATUS MEM(MB) BOOTDISK(GB) PID 9000 ubuntu-24.04-cloudinit stopped 2048 10.00 0

1.2 Elegir el VMID nuevo y clonar

Convención Harper: los servicios "core" del lab van en el rango 200–299. Zabbix quedará como VMID 230. Cambia el nombre si tu convención es otra.

Ejecutar enhost: proxmox
# Clon "linked" (rápido, comparte disco base) desde snapshot de la plantilla.
# Si tu plantilla no tiene snapshot, usa "full" en vez de "linked".
qm clone 9000 230 \
  --name zbx-lab \
  --description "Zabbix 7.0 LTS server · Ubuntu 24.04 · lab Harper" \
  --full 0 --pool lab
⚠ Si el clone falla con "no snapshot found"

La plantilla no tiene snapshot base — usa --full 1 (clon completo, ocupa disco entero pero funciona sin snapshot). Anótalo en el ticket para que se añada el snapshot a la plantilla luego.

1.3 Ajustar recursos y arranque

Ejecutar enhost: proxmox
# Recursos: 2 vCPU + 4 GB RAM. Disco a 40 GB (crece si el cliente monitorea muchos hosts).
qm set 230 --cores 2 --sockets 1 --cpu host --memory 4096 --balloon 0
qm resize 230 scsi0 40G

# Configurar el cloud-init (usuario, llave SSH, red estática).
# El password es de emergencia — el acceso real es por llave SSH.
qm set 230 \
  --ciuser rbatista \
  --sshkeys ~/.ssh/dojo_authorized_keys \
  --ipconfig0 ip=192.168.0.230/24,gw=192.168.0.1 \
  --nameserver "192.168.0.1 1.1.1.1" \
  --searchdomain lab.harper.local

# Regenerar la imagen cloud-init (si no, los cambios no se aplican al primer boot).
qm cloudinit update 230

1.4 Arrancar y esperar el primer boot

Ejecutar enhost: proxmox
# Configurar arranque al boot del host + iniciar.
qm set 230 --onboot 1
qm start 230

# Esperar al agent (cloud-init tarda ~40-60s el primer boot).
until qm agent 230 ping 2>/dev/null; do echo "esperando cloud-init..."; sleep 5; done
qm agent 230 network-get-interfaces | jq -r '.[] | select(.name!="lo").["ip-addresses"][]?."ip-address"'
192.168.0.230 fe80::be24:11ff:fe7f:9d2a
✓ Verificación de la fase

Desde tu máquina, deberías poder hacer SSH sin password (llave ya inyectada por cloud-init) y ver Ubuntu 24.04 arriba.

Ejecutar enhost: local (tu laptop)
ssh rbatista@192.168.0.230 "hostnamectl; lsb_release -d; ip -brief a; uptime"
Static hostname: zbx-lab Icon name: computer-vm Chassis: vm 🖴 Machine ID: 3f2c... Operating System: Ubuntu 24.04.2 LTS Kernel: Linux 6.8.0-45-generic Description: Ubuntu 24.04.2 LTS lo UNKNOWN 127.0.0.1/8 ::1/128 ens18 UP 192.168.0.230/24 fe80::be24:11ff:fe7f:9d2a/64 08:14:32 up 1 min, 1 user, load average: 0.15, 0.05, 0.02
02

Post-instalación de la VM: hostname, updates, hardening SSH

Meta: la VM queda alineada con el estándar Harper — hostname correcto, sistema actualizado, sudo sin password para el usuario base, SSH sin password ni root login.

2.1 Fijar hostname y timezone

Ejecutar enhost: vm (ssh a zbx-lab)
sudo hostnamectl set-hostname zbx-lab.lab.harper.local
sudo timedatectl set-timezone America/Santo_Domingo

# Verificar
hostnamectl
timedatectl

2.2 Aplicar todas las actualizaciones + kernel

Ejecutar enhost: vm
sudo apt update
sudo DEBIAN_FRONTEND=noninteractive apt -y full-upgrade
sudo apt -y install curl wget gnupg2 lsb-release ca-certificates \
  ufw fail2ban unattended-upgrades chrony jq htop net-tools bash-completion

# Si actualizó el kernel: reiniciar.
[ -f /var/run/reboot-required ] && sudo reboot
💡 Buena práctica — updates automáticos de seguridad

unattended-upgrades ya se instaló arriba. Por defecto aplica solo parches de seguridad todos los días a las 06:00 y reinicia si es indispensable. Confirma con sudo systemctl status unattended-upgrades.

2.3 Sudo sin password para el usuario base (opcional pero recomendado en lab)

Ejecutar enhost: vm
echo "rbatista ALL=(ALL) NOPASSWD: ALL" | sudo tee /etc/sudoers.d/90-rbatista
sudo chmod 440 /etc/sudoers.d/90-rbatista
sudo visudo -c   # valida sintaxis; debe decir "parsed OK"

2.4 Hardening SSH

Solo llaves, sin root login, límite de intentos. Guardamos los cambios en un archivo drop-in (/etc/ssh/sshd_config.d/) para no tocar el original de Ubuntu.

Ejecutar enhost: vm
sudo tee /etc/ssh/sshd_config.d/50-harper.conf >/dev/null <<'EOF'
# --- Harper SSH hardening baseline ---
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
EOF

sudo sshd -t && sudo systemctl reload ssh
⚠ Antes de cerrar la sesión SSH actual

Abre una segunda sesión SSH en paralelo y valida que puedes entrar con tu llave. Si funciona, cierras la primera. Si no, la primera queda como red de seguridad para revertir.

2.5 Firewall base (UFW)

Todavía no abrimos 80/443/10051; solo dejamos SSH por ahora. Los puertos del stack se abrirán al final, cuando cada componente esté funcionando.

Ejecutar enhost: vm
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw --force enable
sudo ufw status verbose
✓ Verificación

ssh root@192.168.0.230 debe fallar con "Permission denied" antes de pedir password. Un intento por SSH con password debe rechazarse.

03

Instalar PostgreSQL 16 como backend

Meta: PostgreSQL 16 corriendo, escuchando solo en localhost, con parámetros de rendimiento ajustados y timezone en UTC (requisito de Zabbix).

◆ ¿Por qué PostgreSQL y no MySQL/MariaDB?

Zabbix soporta ambas. Elegimos PostgreSQL porque: (1) es la DB recomendada por Zabbix desde 7.0 y donde ellos concentran las mejoras, (2) integra TimescaleDB como extensión nativa (hypertables para métricas), (3) mejor comportamiento con particionado automático de history. En cliente que ya tenga MariaDB desplegado por otras apps, la ruta MariaDB también es válida — la doc oficial cubre ambos flujos.

3.1 Instalar PostgreSQL 16 desde el repo oficial de PGDG

Ubuntu 24.04 trae PostgreSQL 16 en sus repos base, pero preferimos el repo PGDG (PostgreSQL Global Development Group) — recibe minor updates de seguridad antes que el repo Ubuntu.

Ejecutar enhost: vm
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
  --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc

echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" | \
  sudo tee /etc/apt/sources.list.d/pgdg.list

sudo apt update
sudo apt -y install postgresql-16 postgresql-contrib-16

3.2 Verificar que arrancó y qué versión quedó

Ejecutar enhost: vm
systemctl status postgresql --no-pager
sudo -u postgres psql -c "select version();"
version -------------------------------------------------------------------------------------------------- PostgreSQL 16.9 (Ubuntu 16.9-1.pgdg24.04+1) on x86_64-pc-linux-gnu, compiled by gcc 13.2.0, 64-bit

3.3 Tuning mínimo para Zabbix

Los defaults de Postgres son conservadores. Ajustamos shared_buffers, effective_cache_size y work_mem proporcional a la RAM (4 GB). Si escalas la VM más adelante, recalculas.

Ejecutar enhost: vm
sudo tee /etc/postgresql/16/main/conf.d/50-harper-zabbix.conf >/dev/null <<'EOF'
# --- Harper baseline para Zabbix 7.0 (VM 4 GB RAM) ---
listen_addresses = 'localhost'
shared_buffers = 1GB              # ~25% de RAM
effective_cache_size = 3GB        # ~75% de RAM
work_mem = 16MB                   # por operación de sort
maintenance_work_mem = 256MB
wal_buffers = 16MB
checkpoint_completion_target = 0.9
random_page_cost = 1.1            # asumimos SSD
max_connections = 100

timezone = 'UTC'                  # requisito Zabbix
log_timezone = 'UTC'
EOF

# Debe estar en UTC — Zabbix guarda todo en UTC y convierte en el frontend.
sudo systemctl restart postgresql
sudo -u postgres psql -c "show timezone;"
✓ Verificación

ss -ltnp | grep 5432 debe mostrar Postgres escuchando SOLO en 127.0.0.1:5432. Ningún cliente externo puede conectarse — como debe ser.

04

Crear la base de datos y el usuario de Zabbix

Meta: existe la DB zabbix, el usuario zabbix con password fuerte, y la contraseña queda guardada de forma segura en /root/.zabbix-db-pass.

4.1 Generar el password y guardarlo

Ejecutar enhost: vm
# Generar 32 caracteres random URL-safe.
ZBX_DB_PASS="$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-32)"

# Guardar para uso futuro (backups, upgrades) — solo root.
echo "$ZBX_DB_PASS" | sudo tee /root/.zabbix-db-pass >/dev/null
sudo chmod 600 /root/.zabbix-db-pass
echo "Password guardado en /root/.zabbix-db-pass"

4.2 Crear el usuario y la DB

Zabbix 7.0 requiere la base creada con encoding UTF-8 y locale C — evitar collation locale-dependant que causa slowdowns.

Ejecutar enhost: vm
sudo -u postgres psql <<EOF
CREATE USER zabbix WITH PASSWORD '$(sudo cat /root/.zabbix-db-pass)';
CREATE DATABASE zabbix
  OWNER zabbix
  ENCODING 'UTF8'
  LC_COLLATE 'C'
  LC_CTYPE 'C'
  TEMPLATE template0;
GRANT ALL PRIVILEGES ON DATABASE zabbix TO zabbix;
\c zabbix
GRANT ALL ON SCHEMA public TO zabbix;
EOF
✓ Verificación
Ejecutar enhost: vm
PGPASSWORD="$(sudo cat /root/.zabbix-db-pass)" psql -h 127.0.0.1 -U zabbix -d zabbix -c "\l zabbix"
List of databases Name | Owner | Encoding | Locale Provider | Collate | Ctype | Access privileges ----------+---------+----------+-----------------+---------+-------+--------------------- zabbix | zabbix | UTF8 | libc | C | C | =Tc/zabbix + | | | | | | zabbix=CTc/zabbix
05

Añadir el repo oficial de Zabbix e instalar el server + frontend + agent

Meta: paquetes de Zabbix 7.0 instalados desde el repositorio oficial (garantiza minor updates automáticos con apt upgrade).

5.1 Añadir el repositorio 7.0 para Ubuntu 24.04

Ejecutar enhost: vm
cd /tmp
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest+ubuntu24.04_all.deb
sudo dpkg -i zabbix-release_latest+ubuntu24.04_all.deb
sudo apt update
💡 Anclar la rama 7.0 explícitamente

El paquete zabbix-release añade el repo apuntado a 7.0. Si en el futuro sale 8.0 LTS y el paquete se actualiza, un apt upgrade descuidado podría intentar saltar de rama. Confirma la rama con: apt-cache policy zabbix-server-pgsql | head — debe decir Version: 1:7.0.x-*.

5.2 Instalar los cinco paquetes

Instalamos: server (con backend PostgreSQL), frontend (PHP), configs de Nginx, agent2 (versión nueva del agent, en Go), y los scripts SQL para cargar el schema.

Ejecutar enhost: vm
sudo apt -y install \
  zabbix-server-pgsql \
  zabbix-frontend-php \
  php8.3-pgsql \
  zabbix-nginx-conf \
  zabbix-sql-scripts \
  zabbix-agent2 \
  zabbix-agent2-plugin-postgresql \
  zabbix-agent2-plugin-mongodb
⚠ Si apt se queja de "unable to locate zabbix-frontend-php"

Estás en el repo equivocado. Verifica con grep -r zabbix /etc/apt/sources.list* — debe apuntar a zabbix/7.0/ubuntu. Si dice zabbix/8.0, quita ese repo y reinstala zabbix-release apuntando a 7.0.

5.3 Cargar el schema SQL en la DB

El schema completo pesa ~40 MB (comprimido). Puede tardar 1–3 minutos en aplicarse. No canceles.

Ejecutar enhost: vm
ZBX_DB_PASS="$(sudo cat /root/.zabbix-db-pass)"

zcat /usr/share/zabbix-sql-scripts/postgresql/server.sql.gz | \
  PGPASSWORD="$ZBX_DB_PASS" psql -h 127.0.0.1 -U zabbix -d zabbix

# Verificar: debe haber ~180 tablas.
PGPASSWORD="$ZBX_DB_PASS" psql -h 127.0.0.1 -U zabbix -d zabbix -c "\dt" | tail -5
echo "Tablas creadas: $(PGPASSWORD=$ZBX_DB_PASS psql -h 127.0.0.1 -U zabbix -d zabbix -tAc "select count(*) from pg_tables where schemaname='public';")"
Tablas creadas: 173
✓ Verificación

dpkg -l | grep zabbix debe mostrar los 5 paquetes con versión 1:7.0.x-*. Si ves alguno en ii ... 1:6.0.x — quedó una instalación previa, hay que remover y reinstalar.

06

Configurar zabbix-server.conf y arrancar el server

Meta: el proceso zabbix-server conecta a la DB, arranca limpio, y los logs muestran "server #0 started" sin errores.

6.1 Editar la config del server

Todo lo importante vive en /etc/zabbix/zabbix_server.conf. Sólo cambiamos tres cosas: password de la DB, número de workers, y ubicación del log.

Ejecutar enhost: vm
ZBX_DB_PASS="$(sudo cat /root/.zabbix-db-pass)"

# Sed idempotente — funciona la primera vez y las siguientes.
sudo sed -i -E \
  -e "s|^# ?DBPassword=.*|DBPassword=$ZBX_DB_PASS|" \
  -e "s|^# ?DBHost=.*|DBHost=127.0.0.1|" \
  -e "s|^# ?StartPollers=.*|StartPollers=10|" \
  -e "s|^# ?StartPingers=.*|StartPingers=4|" \
  -e "s|^# ?CacheSize=.*|CacheSize=64M|" \
  -e "s|^# ?HistoryCacheSize=.*|HistoryCacheSize=32M|" \
  -e "s|^# ?LogSlowQueries=.*|LogSlowQueries=3000|" \
  /etc/zabbix/zabbix_server.conf

# Confirmar que el password quedó (sin imprimirlo — grep muestra la línea entera).
sudo grep -E "^(DBHost|DBPassword|StartPollers|CacheSize)" /etc/zabbix/zabbix_server.conf | \
  sed 's/DBPassword=.*/DBPassword=[HIDDEN]/'
DBHost=127.0.0.1 DBPassword=[HIDDEN] StartPollers=10 CacheSize=64M

6.2 Arrancar el server y verificar el log

Ejecutar enhost: vm
sudo systemctl enable --now zabbix-server
sudo journalctl -u zabbix-server -n 30 --no-pager
sudo tail -20 /var/log/zabbix/zabbix_server.log
12345:20260701:081432.010 Starting Zabbix Server. Zabbix 7.0.27 (revision c4a3b1). 12345:20260701:081432.010 ****** Enabled features ****** 12345:20260701:081432.010 SNMP monitoring: YES 12345:20260701:081432.010 IPMI monitoring: YES 12345:20260701:081432.010 Web monitoring: YES 12345:20260701:081432.010 VMware monitoring: YES 12345:20260701:081432.010 SMTP authentication: YES 12345:20260701:081432.010 ODBC: YES 12345:20260701:081432.010 SSH support: YES 12345:20260701:081432.010 TLS support: YES 12345:20260701:081432.010 ****************************** 12345:20260701:081432.010 server #0 started [main process] 12345:20260701:081432.020 server #1 started [service manager #1] ...
⚠ Si ves "connection to database 'zabbix' failed"

El server no puede autenticarse contra Postgres. Causas más comunes:

  • El password en zabbix_server.conf tiene caracteres especiales sin escapar — reemplaza el password por uno solo alfanumérico y prueba.
  • pg_hba.conf tiene el método peer en local — Zabbix conecta por TCP a 127.0.0.1, no local. Debe estar en md5 o scram-sha-256. Verifica con: sudo grep '^host' /etc/postgresql/16/main/pg_hba.conf
  • Postgres no reinició tras cambiar listen_addresses. Reinicia y reintenta.
✓ Verificación

El proceso escucha en 10051/tcp (puerto del server hacia los agents).

Ejecutar enhost: vm
ss -ltnp | grep 10051
LISTEN 0 256 0.0.0.0:10051 0.0.0.0:* users:(("zabbix_server",pid=12345,fd=8))
07

Configurar Nginx + PHP-FPM para el frontend web

Meta: http://192.168.0.230/ muestra la pantalla de setup de Zabbix.

7.1 Activar el vhost de Nginx

El paquete zabbix-nginx-conf instala la config en /etc/zabbix/nginx.conf. Ajustamos server_name + listen y la enlazamos.

Ejecutar enhost: vm
sudo sed -i \
  -e 's|^#\s*listen\s\+8080;|        listen          80;|' \
  -e 's|^#\s*server_name.*|        server_name     zbx-lab.lab.harper.local 192.168.0.230;|' \
  /etc/zabbix/nginx.conf

# Enlazar como sitio activo en Nginx.
sudo ln -sf /etc/zabbix/nginx.conf /etc/nginx/conf.d/zabbix.conf

# Deshabilitar el default para no chocar en :80.
[ -e /etc/nginx/sites-enabled/default ] && sudo rm /etc/nginx/sites-enabled/default || true

sudo nginx -t
sudo systemctl reload nginx

7.2 Ajustar PHP-FPM (timezone + memoria)

Zabbix exige date.timezone declarado y post_max_size + max_execution_time por encima de los defaults (imágenes, imports).

Ejecutar enhost: vm
sudo sed -i -E \
  -e 's|^;?\s*date.timezone\s*=.*|date.timezone = America/Santo_Domingo|' \
  -e 's|^;?\s*post_max_size\s*=.*|post_max_size = 16M|' \
  -e 's|^;?\s*upload_max_filesize\s*=.*|upload_max_filesize = 2M|' \
  -e 's|^;?\s*max_execution_time\s*=.*|max_execution_time = 300|' \
  -e 's|^;?\s*max_input_time\s*=.*|max_input_time = 300|' \
  -e 's|^;?\s*memory_limit\s*=.*|memory_limit = 256M|' \
  /etc/php/8.3/fpm/php.ini

sudo systemctl restart php8.3-fpm
sudo systemctl status php8.3-fpm --no-pager | head -8

7.3 Abrir el puerto 80 en UFW y probar en el navegador

Ejecutar enhost: vm
sudo ufw allow 80/tcp
sudo ufw status
✓ Verificación

Desde tu laptop, abre http://192.168.0.230/ — debe salir el asistente de bienvenida de Zabbix (idioma → check de requisitos → DB → server → resumen).

⚠ Si sale "502 Bad Gateway"

Nginx no puede hablar con PHP-FPM. Verifica que el socket exista: ls -la /run/php/php8.3-fpm.sock y que Nginx lo apunte con el path correcto en /etc/zabbix/nginx.conf (buscar fastcgi_pass). Un típico bug es tener PHP 8.2 en la config y PHP 8.3 instalado.

08

Completar el asistente web de instalación

Meta: primer login como Admin, cambio inmediato de password default, e idioma en español.

8.1 Recorrer las pantallas del wizard

  1. Welcome → seleccionar Spanish (es_ES)Next step.
  2. Check of pre-requisites → todas las líneas deben decir OK. Si alguna marca Fail vuelve atrás a la fase 7 y corrige el php.ini.
  3. Configure DB connection — llenar así:
    • Database type: PostgreSQL
    • Database host: 127.0.0.1
    • Database port: 5432
    • Database name: zabbix
    • User: zabbix
    • Password: el contenido de /root/.zabbix-db-pass
    • TLS encryption: dejar desmarcado (loopback local, no aporta).
  4. Settings → Zabbix server name: Harper-LAB. Timezone: America/Santo_Domingo. Tema default: Blue.
  5. Summary → confirmar → Finish. Genera el archivo /etc/zabbix/web/zabbix.conf.php.
💡 El archivo generado por el wizard

/etc/zabbix/web/zabbix.conf.php contiene el password de la DB en claro. Confirma que quedó en 640 zabbix:www-data: ls -la /etc/zabbix/web/zabbix.conf.php.

8.2 Primer login

  • Usuario: Admin (con A mayúscula).
  • Password default: zabbix.
  • Cambia el password inmediatamente: menú superior derecho → User settings → Change password. Usa un password fuerte y guárdalo en la bóveda del cliente.
✓ Verificación

Ve a Monitoring → Hosts — debe haber un host Zabbix server con "Availability" en rojo/gris (aún no configuramos el agent). Eso es correcto en esta fase.

09

Configurar zabbix-agent2 para que el server se monitoree a sí mismo

Meta: el host Zabbix server pasa a Available (Zabbix agent) en verde, y los gráficos empiezan a llenarse.

El agent ya está instalado (fase 5). Solo hay que apuntarlo al server local.

9.1 Config mínima del agent

Ejecutar enhost: vm
sudo sed -i -E \
  -e 's|^Server=.*|Server=127.0.0.1|' \
  -e 's|^ServerActive=.*|ServerActive=127.0.0.1|' \
  -e 's|^Hostname=.*|Hostname=Zabbix server|' \
  /etc/zabbix/zabbix_agent2.conf

sudo systemctl enable --now zabbix-agent2
sudo systemctl status zabbix-agent2 --no-pager | head -8
⚠ Hostname del agent = Hostname del host en la GUI

El valor Hostname del zabbix_agent2.conf DEBE coincidir EXACTAMENTE con el nombre del host en la GUI (incluidas mayúsculas y espacios). El host default que crea Zabbix se llama Zabbix server (con "Z" mayúscula y un espacio). Si difiere en una letra, el agent responde pero Zabbix no lo asocia.

✓ Verificación (esperar ~90 segundos)

En la GUI Monitoring → Hosts, la columna Availability del host Zabbix server debe pasar a verde con "Z". Los primeros datos (CPU, RAM, disco) aparecen en Monitoring → Latest data al minuto siguiente.

10

TLS en el frontend (Certbot para clientes con dominio público, cert interno en lab)

Meta: https://zbx.lab.harper.local/ funcionando; http:// redirige a HTTPS.

◆ Certbot o certificado interno

Cliente con dominio público (Zabbix accesible por internet): usar certbot con HTTP-01 (puerto 80 accesible externamente).
Lab / cliente cerrado (solo LAN): usar cert auto-firmado o cert emitido por la CA interna. En este tutorial documentamos ambos.

10.1 Ruta A · Certbot (dominio público)

Ejecutar enhost: vm
sudo apt -y install certbot python3-certbot-nginx
sudo certbot --nginx \
  -d zbx.cliente-ejemplo.com \
  --agree-tos \
  --email ramces.batista@har-per.com \
  --no-eff-email \
  --redirect

# Verificar renovación automática (via systemd timer)
sudo systemctl list-timers | grep certbot

10.2 Ruta B · Cert auto-firmado para el lab

Ejecutar enhost: vm
sudo mkdir -p /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 825 -newkey rsa:2048 \
  -keyout /etc/nginx/ssl/zbx-lab.key \
  -out    /etc/nginx/ssl/zbx-lab.crt \
  -subj "/C=DO/ST=SDO/L=SantoDomingo/O=Harper/OU=Infra/CN=zbx-lab.lab.harper.local"

# Editar /etc/zabbix/nginx.conf: añadir bloque HTTPS + redirect.
sudo tee /etc/nginx/conf.d/zabbix-ssl.conf >/dev/null <<'EOF'
server {
    listen 80;
    server_name zbx-lab.lab.harper.local 192.168.0.230;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    server_name zbx-lab.lab.harper.local 192.168.0.230;

    ssl_certificate     /etc/nginx/ssl/zbx-lab.crt;
    ssl_certificate_key /etc/nginx/ssl/zbx-lab.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    include /etc/zabbix/nginx.conf;
}
EOF

# Quitar el /etc/nginx/conf.d/zabbix.conf duplicado (queda dentro del SSL).
sudo mv /etc/nginx/conf.d/zabbix.conf /etc/nginx/conf.d/zabbix.conf.disabled

sudo nginx -t && sudo systemctl reload nginx
sudo ufw allow 443/tcp
✓ Verificación

curl -kI https://192.168.0.230/ debe devolver 200 OK. El navegador muestra la advertencia de cert auto-firmado (esperado en lab) y al aceptar carga el login.

11

Añadir el primer host cliente (Ubuntu/Debian) y aplicar template

Meta: un segundo host Linux aparece en verde y recibe métricas cada 1 min.

11.1 En el host a monitorear: instalar el agent

Repetimos el patrón: repo oficial → agent2 → configurar → arrancar. En cliente Debian/Ubuntu 24.04 es igual que en la VM del server.

Ejecutar enhost: host-cliente (por ejemplo, otro Ubuntu 24.04)
cd /tmp
wget https://repo.zabbix.com/zabbix/7.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest+ubuntu24.04_all.deb
sudo dpkg -i zabbix-release_latest+ubuntu24.04_all.deb
sudo apt update
sudo apt -y install zabbix-agent2

# Apuntar al servidor Zabbix (IP LAN de la VM del server).
sudo sed -i -E \
  -e 's|^Server=.*|Server=192.168.0.230|' \
  -e 's|^ServerActive=.*|ServerActive=192.168.0.230|' \
  -e "s|^Hostname=.*|Hostname=$(hostname -f)|" \
  /etc/zabbix/zabbix_agent2.conf

sudo systemctl enable --now zabbix-agent2

# Abrir el puerto 10050 SOLO desde la IP del Zabbix server.
sudo ufw allow from 192.168.0.230 to any port 10050 proto tcp

11.2 En la GUI Zabbix: crear el host

  1. Data collection → Hosts → Create host.
  2. Host name: exacto igual al Hostname del agent (ej. web01.lab.harper.local).
  3. Templates: añadir Linux by Zabbix agent (el activo, no el pasivo si el firewall del cliente bloquea entrantes).
  4. Host groups: Linux servers.
  5. Interfaces: Agent, IP del host, puerto 10050.
  6. Save.
💡 Template "by Zabbix agent" vs "by Zabbix agent active"

El template active hace que el agent envíe datos (push, sale por 10051 del server) — mejor si el host cliente está detrás de NAT o firewall que no permite entrantes. El passive hace que el server pregunte (pull, entra por 10050 al cliente). En Harper por defecto usamos active — es más amigable con firewalls de cliente.

✓ Verificación

Espera 90 segundos. El host aparece con Availability verde y en Latest data ves CPU utilization, Memory used, Uptime, etc.

12

Notificaciones por email al equipo de infraestructura

Meta: cuando un trigger de High/Disaster se dispara, llega email a infra@har-per.com en < 30 segundos.

Necesitas: cuenta SMTP con app-password (Microsoft 365, Google Workspace, cuenta dedicada del cliente). Nunca reutilizar credenciales personales — usar cuenta de servicio.

12.1 Configurar el "Media type" Email

  1. Alerts → Media types → Email (viene desactivado).
  2. SMTP server: smtp.office365.com · Port: 587
  3. SMTP helo: zbx-lab.lab.harper.local
  4. SMTP email: zabbix-alerts@har-per.com (from address).
  5. Connection security: STARTTLS.
  6. Authentication: Username and password → usuario + app-password.
  7. Message format: HTML.
  8. Enabled: ✓ · Test → enviar a tu email → confirmar que llega.

12.2 Vincular el email al usuario Admin (y crear un usuario "alerts")

  1. Users → Users → Admin → Media: añadir Email → infra@har-per.comSeverity: Warning + High + Disaster.
  2. Alerts → Actions → Trigger actions: crear una acción "Notify Infra" con condición Trigger severity ≥ High y operación Send message to user Admin (Email).
✓ Verificación

Detén temporalmente el agent del host cliente (sudo systemctl stop zabbix-agent2). Tras ~2 minutos debe llegar el email [PROBLEM] Host unreachable. Arranca el agent de nuevo y llega [RESOLVED].

13

Backup nocturno de la DB y de /etc/zabbix/

Meta: cada noche a las 03:00 se genera un dump comprimido de la DB + tar de la config, con retención de 14 días.

13.1 Script de backup

Ejecutar enhost: vm
sudo tee /usr/local/sbin/zbx-backup.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
# Backup nocturno de Zabbix — Harper.
# - Dump comprimido de la DB Postgres (schema + datos).
# - Tar de /etc/zabbix (configs).
# - Retención: 14 archivos más recientes de cada tipo.
set -euo pipefail

BACKUP_DIR=/var/backups/zabbix
STAMP=$(date +%F_%H%M)
mkdir -p "$BACKUP_DIR"

# 1) DB
export PGPASSWORD="$(cat /root/.zabbix-db-pass)"
pg_dump -h 127.0.0.1 -U zabbix -Fc zabbix \
  | gzip -9 > "$BACKUP_DIR/zabbix-db-$STAMP.dump.gz"

# 2) Configs
tar -C / -czf "$BACKUP_DIR/zabbix-etc-$STAMP.tar.gz" etc/zabbix etc/nginx/conf.d 2>/dev/null

# 3) Retención: dejar 14 más recientes de cada patrón.
ls -1t "$BACKUP_DIR"/zabbix-db-*.dump.gz  | tail -n +15 | xargs -r rm --
ls -1t "$BACKUP_DIR"/zabbix-etc-*.tar.gz  | tail -n +15 | xargs -r rm --

logger -t zbx-backup "backup OK · $STAMP · $(du -sh $BACKUP_DIR | cut -f1)"
EOF

sudo chmod 700 /usr/local/sbin/zbx-backup.sh
sudo /usr/local/sbin/zbx-backup.sh   # test manual
ls -lh /var/backups/zabbix/

13.2 Timer de systemd (03:00 local)

Ejecutar enhost: vm
sudo tee /etc/systemd/system/zbx-backup.service >/dev/null <<'EOF'
[Unit]
Description=Zabbix nightly backup (DB + configs)
After=postgresql.service

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/zbx-backup.sh
EOF

sudo tee /etc/systemd/system/zbx-backup.timer >/dev/null <<'EOF'
[Unit]
Description=Trigger zbx-backup.service cada noche a las 03:00

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=5m

[Install]
WantedBy=timers.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now zbx-backup.timer
sudo systemctl list-timers zbx-backup.timer
💡 Off-site del backup

Los backups locales protegen contra corrupción de DB, no contra pérdida de la VM. Añade un rclone sync o rsync hacia el servidor de backup del cliente / OBS de Huawei Cloud. Documentar la política de retención remota en el ticket de handoff.

14

Documentación de handoff al cliente

Meta: dejar al cliente la información mínima para operar, actualizar y recuperar.

14.1 Ficha de servicio (rellenar y entregar)

CampoValor
Cliente
Fecha de entrega
FQDN del server
IP LAN
Versión Zabbix7.0.27 LTS
URL frontend
User admin creado
Media type email configurado (sí/no)
Cuenta SMTP usada
Ruta de backups (/var/backups/zabbix)
Off-site backup destino
Snapshots Proxmox activados (sí/no)
Firewall abierto (puertos)
Hosts monitoreados al momento de entrega
Contacto técnico Harper
Notas / Excepciones

14.2 Checklist de entrega (evaluación final)

  • La VM boots limpia, Ubuntu 24.04 actualizado, SSH sin password, UFW activo.
  • PostgreSQL 16 escucha solo en 127.0.0.1:5432, timezone UTC.
  • La DB zabbix tiene ≥ 173 tablas cargadas.
  • zabbix-server arranca sin errores en el log.
  • El frontend responde en https://…/ con cert válido (o auto-firmado documentado en lab).
  • Login Admin con password nuevo (no zabbix).
  • El host Zabbix server aparece en verde (agent local funciona).
  • Al menos un host cliente monitoreado con template Linux.
  • Email de prueba llega desde Zabbix a la lista de alertas.
  • Timer de backup zbx-backup.timer activo y ejecutado al menos una vez.
  • Ficha 14.1 rellena y compartida con el cliente.
  • Snapshot Proxmox tomado post-entrega ("post-handoff") para rollback rápido.

14.3 Comandos de referencia rápida (cheatsheet)

Diagnóstico y operación diaria

QuéComando
Ver estado del serversystemctl status zabbix-server
Log del server en vivosudo tail -f /var/log/zabbix/zabbix_server.log
Reiniciar solo el serversudo systemctl restart zabbix-server
Reiniciar todo el stack websudo systemctl restart php8.3-fpm nginx
Contar hosts activosPGPASSWORD=… psql -h 127.0.0.1 -U zabbix -d zabbix -c "select count(*) from hosts where status=0;"
Backup manual on-demandsudo /usr/local/sbin/zbx-backup.sh
Ver últimos triggers activosMonitoring → Problems en la GUI
Detectar cola atascadaReports → Queue
Testear agent desde el serverzabbix_get -s IP_HOST -k system.uptime
💡 Path de upgrade a Zabbix 8.0

Cuando 8.0 LTS lleve ~6 meses en GA: (1) snapshot Proxmox pre-upgrade, (2) apt install zabbix-release_latest+ubuntu24.04_all.deb apuntado a 8.0, (3) apt update && apt install --only-upgrade zabbix-server-pgsql zabbix-frontend-php, (4) el server aplica migrations al arrancar (revisar log), (5) verificar frontend. Documentaremos el playbook oficial cuando 8.0 esté estable.

✓ Fin del tutorial

Si todos los ítems del checklist 14.2 están marcados, el servidor Zabbix está listo para producción y este es tu procedimiento canónico para clientes a partir de hoy. Copia esta página como base de la documentación interna del cliente.

Departamento de Infraestructura · Harper · 2026 Tutorial · Zabbix 7.0 LTS sobre Proxmox