Zammad es un sistema de tickets y helpdesk de código abierto que centraliza en una sola bandeja las solicitudes que llegan por correo, formulario web, chat o teléfono. En este tutorial desplegarás Zammad en Ubuntu 24.04 con el proyecto oficial zammad-docker-compose, que incluye PostgreSQL, Elasticsearch, Redis y Memcached ya configurados. Después lo publicarás detrás de Nginx con un certificado de Let's Encrypt y conectarás tu buzón de soporte.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 4 GB de RAM (8 GB recomendados si esperas muchos agentes o tickets), 2 vCPU y 30 GB de disco. Elasticsearch es el componente que más memoria consume.
  • Un usuario no root con privilegios sudo.
  • Un dominio o subdominio, por ejemplo soporte.example.com, con un registro DNS de tipo A que apunte a la IP del servidor. En la guía se usa your_domain como marcador.
  • Los puertos 22, 80 y 443 abiertos.
  • Una cuenta de correo (IMAP y SMTP) para el buzón de soporte, por ejemplo [email protected].

Paso 1: Instalar Docker Engine y Docker Compose

Instala Docker desde el repositorio oficial, que incluye el plugin docker compose. Primero añade la clave y el repositorio:

sudo apt update
sudo apt install -y ca-certificates curl git
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Instala los paquetes:

sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Comprueba que Docker y Compose responden:

sudo docker --version
sudo docker compose version
Docker version 28.4.0, build d8eb465
Docker Compose version v2.39.2

Las versiones exactas pueden ser más recientes. Necesitas Docker Compose 2.24 o superior para la etiqueta !override que se usa en el paso 3.

Paso 2: Preparar el kernel para Elasticsearch

Elasticsearch necesita un valor alto de vm.max_map_count para arrancar. Créalo en un archivo propio para que persista tras reiniciar:

echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-elasticsearch.conf
sudo sysctl --system

Comprueba el valor aplicado:

sysctl vm.max_map_count
vm.max_map_count = 262144

Paso 3: Descargar y ajustar zammad-docker-compose

Clona el repositorio oficial en /opt:

sudo git clone https://github.com/zammad/zammad-docker-compose.git /opt/zammad-docker-compose
cd /opt/zammad-docker-compose

Por defecto, el contenedor zammad-nginx publica el puerto 8080 en todas las interfaces. Docker añade sus propias reglas de iptables y ese puerto quedaría accesible desde Internet aunque UFW lo bloquee. Como vas a poner Nginx del sistema delante, publícalo solo en 127.0.0.1 con un archivo de override, que Compose carga automáticamente y que no se pierde al actualizar el repositorio:

sudo nano /opt/zammad-docker-compose/docker-compose.override.yml
services:
  zammad-nginx:
    ports: !override
      - "127.0.0.1:8080:8080"

Valida la configuración combinada y comprueba el puerto:

sudo docker compose config | grep -A4 "ports:"
    ports:
      - mode: ingress
        host_ip: 127.0.0.1
        target: 8080
        published: "8080"

Paso 4: Arrancar Zammad

Descarga las imágenes y arranca todos los servicios en segundo plano:

sudo docker compose up -d

El primer arranque tarda unos minutos: el contenedor zammad-init crea la base de datos, ejecuta las migraciones y construye el índice de Elasticsearch, y después termina. Comprueba el estado:

sudo docker compose ps

Todos los servicios deben aparecer como running (o healthy), salvo zammad-init, que se detiene al terminar su trabajo. Si quieres seguir el proceso de inicialización:

sudo docker compose logs -f zammad-init

Cuando termine, comprueba que Zammad responde en el puerto local:

curl -sI http://127.0.0.1:8080 | head -n 1
HTTP/1.1 200 OK

Si recibes 502 Bad Gateway, el servidor de Rails todavía está arrancando: espera un minuto y repite.

Paso 5: Configurar Nginx como proxy inverso

Instala Nginx en el sistema:

sudo apt install -y nginx

Crea un bloque de servidor para tu dominio. Zammad usa WebSockets para actualizar tickets en tiempo real, así que el proxy debe reenviar las cabeceras Upgrade y Connection:

sudo nano /etc/nginx/sites-available/zammad
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    listen [::]:80;
    server_name your_domain;

    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300s;
    }
}

client_max_body_size limita el tamaño de los adjuntos que los agentes pueden subir; ajústalo a tus necesidades. Activa el sitio, desactiva el sitio por defecto y comprueba la sintaxis:

sudo ln -s /etc/nginx/sites-available/zammad /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Paso 6: Abrir el cortafuegos y activar HTTPS

Permite SSH y el tráfico web en UFW:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Instala Certbot y solicita el certificado. Certbot añade a tu bloque de servidor la configuración TLS y la redirección de HTTP a HTTPS:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your_domain

Comprueba que el sitio responde por HTTPS y que la renovación automática funciona:

curl -sI https://your_domain | head -n 1
sudo certbot renew --dry-run
HTTP/2 200
...
Congratulations, all simulated renewals succeeded:

Paso 7: Completar el asistente inicial

Abre https://your_domain en el navegador y elige Configurar nuevo sistema. El asistente te pide:

  1. Los datos del primer administrador (nombre, correo y contraseña).
  2. El nombre de la organización, el logotipo y la URL del sistema. Comprueba que aparece https://your_domain; Zammad la usa en los enlaces de los correos que envía.
  3. El envío de correo. Puedes configurarlo aquí o saltarlo y hacerlo en el siguiente paso.

Al terminar entrarás en la vista de agente, con los paneles de tickets, clientes y organizaciones.

Paso 8: Conectar el buzón de soporte

Para que los correos enviados a tu dirección de soporte se conviertan en tickets, ve a Configuración (icono del engranaje) > Canales > Correo electrónico y pulsa Añadir cuenta. Introduce el nombre, la dirección y la contraseña del buzón. Zammad intenta detectar los servidores IMAP y SMTP automáticamente; si no lo consigue, pulsa en la configuración avanzada e introduce los datos de tu proveedor, por ejemplo:

CampoEntrada (IMAP)Salida (SMTP)
Servidorimap.example.comsmtp.example.com
Puerto993587
CifradoSSL/TLSSTARTTLS

Asigna la cuenta a un grupo (por ejemplo Users o uno nuevo llamado Soporte). Para verificarlo, envía un correo desde una cuenta externa a tu dirección de soporte: en uno o dos minutos debería aparecer como ticket nuevo en ese grupo, y al responder desde Zammad el cliente recibirá la contestación con el número de ticket en el asunto.

Con el canal funcionando, revisa en Configuración > Gestionar los grupos, roles, calendarios de horario laboral y SLA, y crea los agentes desde Usuarios.

Paso 9: Revisar las copias de seguridad

El stack incluye un servicio zammad-backup que exporta periódicamente la base de datos PostgreSQL y los archivos de Zammad a un volumen de Docker. La hora de la copia y los días que se conservan se controlan con las variables de entorno de ese servicio en docker-compose.yml. Comprueba en su registro que se están generando:

cd /opt/zammad-docker-compose
sudo docker compose logs --tail=20 zammad-backup

Localiza el volumen donde se guardan:

sudo docker volume ls | grep backup
local     zammad-docker-compose_zammad-backup

Ese volumen vive en el mismo servidor. Copia su contenido de forma periódica a otro sistema (por ejemplo, con rsync desde la ruta que indica sudo docker volume inspect zammad-docker-compose_zammad-backup) para poder recuperarte si pierdes el servidor.

Paso 10: Actualizar Zammad

Para actualizar, descarga los cambios del repositorio y las imágenes nuevas y recrea los contenedores. El contenedor zammad-init aplicará las migraciones necesarias:

cd /opt/zammad-docker-compose
sudo git pull
sudo docker compose pull
sudo docker compose up -d

Antes de un salto de versión mayor, comprueba que tienes una copia reciente y lee las notas de la versión.

Solución de problemas

El contenedor de Elasticsearch se reinicia en bucle. Revisa sudo docker compose logs zammad-elasticsearch. Si menciona max virtual memory areas vm.max_map_count, repite el paso 2. Si el servidor tiene poca RAM, el contenedor puede morir por falta de memoria: comprueba dmesg | grep -i oom y amplía la RAM.

La interfaz muestra "Conexión perdida" o no se actualiza en tiempo real. El proxy no está reenviando WebSockets. Comprueba que el bloque map y las cabeceras Upgrade y Connection están en la configuración de Nginx y recárgalo.

Los enlaces de los correos apuntan a http:// o a la IP. Corrige la URL del sistema en Configuración > Sistema > Base (FQDN y tipo HTTP).

Error yaml: unknown tag !override. Tu versión de Docker Compose es anterior a la 2.24. Actualiza el paquete docker-compose-plugin.

Conclusión

Zammad ya está funcionando en Ubuntu 24.04 con Docker Compose, publicado solo a través de Nginx con HTTPS y recibiendo tickets desde tu buzón de soporte. Como siguientes pasos, define SLA y horarios laborales para tu equipo, añade el formulario web o el chat en tu sitio desde Canales y programa la copia externa del volumen de backups.