Rundeck es una plataforma de automatización de operaciones: centraliza comandos, scripts y runbooks, los ejecuta por SSH en tus servidores y deja registro de quién lanzó qué y con qué resultado. En este tutorial instalarás Rundeck Community en Ubuntu 24.04 con PostgreSQL como base de datos, lo publicarás detrás de Nginx con HTTPS, darás de alta nodos remotos, crearás un runbook de respuesta a incidentes y definirás un grupo de operadores que solo puede ejecutar jobs.
Requisitos previos
- Un servidor con Ubuntu 24.04 LTS y al menos 2 GB de RAM (4 GB recomendados), por ejemplo un VPS de CubePath.
- Un usuario no root con privilegios
sudo. - Un dominio con un registro A apuntando a la IP del servidor, por ejemplo
rundeck.your_domain. - Los puertos 22, 80 y 443 abiertos en UFW.
- Uno o varios servidores Linux que quieras gestionar, accesibles por SSH desde el servidor de Rundeck.
Paso 1: Instalar Java y PostgreSQL
Rundeck es una aplicación Java y en su versión 5 funciona con Java 17. Instala el runtime sin interfaz gráfica y PostgreSQL:
sudo apt update
sudo apt install openjdk-17-jre-headless postgresql
Comprueba la versión de Java:
java -version
openjdk version "17.0.x" ...
Por defecto Rundeck usa una base de datos H2 embebida, válida solo para pruebas. Crea un usuario y una base de datos en PostgreSQL. Sustituye your_strong_password por una contraseña robusta:
sudo -u postgres psql -c "CREATE USER rundeck WITH PASSWORD 'your_strong_password';"
sudo -u postgres psql -c "CREATE DATABASE rundeck OWNER rundeck;"
Paso 2: Añadir el repositorio de Rundeck e instalar el paquete
PagerDuty publica los paquetes de Rundeck en su propio repositorio. Descarga la clave en /etc/apt/keyrings:
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://packages.rundeck.com/pagerduty/rundeck/gpgkey | sudo gpg --dearmor -o /etc/apt/keyrings/rundeck.gpg
Crea el archivo del repositorio:
echo "deb [signed-by=/etc/apt/keyrings/rundeck.gpg] https://packages.rundeck.com/pagerduty/rundeck/any/ any main" | sudo tee /etc/apt/sources.list.d/rundeck.list
Instala Rundeck:
sudo apt update
sudo apt install rundeck
El paquete crea el usuario de sistema rundeck, la configuración en /etc/rundeck/, los datos en /var/lib/rundeck/ y los logs en /var/log/rundeck/. No arranques todavía el servicio: primero lo conectarás a PostgreSQL para que no cree sus tablas en H2.
Paso 3: Configurar la base de datos y la URL pública
Abre el archivo de configuración principal:
sudo nano /etc/rundeck/rundeck-config.properties
Localiza las líneas grails.serverURL y dataSource.url y deja el bloque así, con tu dominio y la contraseña del paso 1:
grails.serverURL=https://rundeck.your_domain
server.address=127.0.0.1
dataSource.dbCreate = none
dataSource.driverClassName = org.postgresql.Driver
dataSource.url = jdbc:postgresql://localhost/rundeck
dataSource.username = rundeck
dataSource.password = your_strong_password
grails.serverURLes la URL que Rundeck usa en enlaces, redirecciones y webhooks. Debe coincidir con la que escribirá el navegador.server.address=127.0.0.1hace que Rundeck escuche solo en local en el puerto 4440; el acceso desde fuera pasará por Nginx.
Este archivo contiene una contraseña, así que restringe sus permisos:
sudo chown rundeck:rundeck /etc/rundeck/rundeck-config.properties
sudo chmod 640 /etc/rundeck/rundeck-config.properties
Paso 4: Cambiar la contraseña del administrador
Los usuarios locales se definen en /etc/rundeck/realm.properties con el formato usuario:contraseña,rol1,rol2. La instalación trae admin con contraseña admin. Cámbiala antes del primer arranque:
sudo nano /etc/rundeck/realm.properties
admin:your_admin_password,user,admin
Aprovecha para crear un usuario operador que usarás en el paso 9:
operador1:your_operator_password,user,operadores
Protege el archivo:
sudo chown rundeck:rundeck /etc/rundeck/realm.properties
sudo chmod 640 /etc/rundeck/realm.properties
Paso 5: Arrancar Rundeck
El servicio se llama rundeckd. Habilítalo y arráncalo:
sudo systemctl enable --now rundeckd
El primer arranque tarda uno o dos minutos porque crea el esquema en PostgreSQL. Sigue el log hasta ver el mensaje de que el servidor está listo:
sudo tail -f /var/log/rundeck/service.log
Grails application running at http://127.0.0.1:4440 in environment: production
Pulsa Ctrl+C y comprueba que escucha en local:
sudo ss -tlnp | grep 4440
LISTEN 0 100 127.0.0.1:4440 0.0.0.0:* users:(("java",pid=...))
Paso 6: Publicar Rundeck con Nginx y HTTPS
Instala Nginx y Certbot:
sudo apt install nginx certbot python3-certbot-nginx
Crea el sitio:
sudo nano /etc/nginx/sites-available/rundeck
server {
listen 80;
server_name rundeck.your_domain;
location / {
proxy_pass http://127.0.0.1:4440;
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;
}
}
Actívalo, valida la sintaxis y recarga:
sudo ln -s /etc/nginx/sites-available/rundeck /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Abre HTTP y HTTPS en el firewall y obtén el certificado de Let's Encrypt:
sudo ufw allow 'Nginx Full'
sudo certbot --nginx -d rundeck.your_domain
Abre https://rundeck.your_domain en el navegador e inicia sesión como admin con la contraseña del paso 4. Si tras el login te redirige a http:// o a localhost, revisa grails.serverURL.
Paso 7: Crear un proyecto y dar de alta nodos
En Rundeck todo vive dentro de un proyecto: jobs, nodos, claves y webhooks. Pulsa New Project, llámalo infraestructura y guarda.
Preparar el acceso SSH a los nodos
Rundeck se conecta a cada nodo por SSH con una clave. Genera un par de claves dedicado en el servidor de Rundeck:
sudo -u rundeck ssh-keygen -t ed25519 -f /var/lib/rundeck/.ssh/id_ed25519_nodos -N "" -C "rundeck"
En cada nodo gestionado, crea un usuario deploy y añade la clave pública (/var/lib/rundeck/.ssh/id_ed25519_nodos.pub) a /home/deploy/.ssh/authorized_keys. Desde el servidor de Rundeck, comprueba la conexión y acepta la huella del host:
sudo -u rundeck ssh -i /var/lib/rundeck/.ssh/id_ed25519_nodos deploy@your_node_ip hostname
web-01
Ahora sube la clave privada al almacén de claves de Rundeck para no referenciar archivos del disco. En el proyecto, ve a Project Settings > Key Storage > Add or Upload a Key, elige Private Key, pega el contenido de /var/lib/rundeck/.ssh/id_ed25519_nodos y guárdala con el nombre deploy en la ruta que propone (keys/project/infraestructura/). La ruta completa será keys/project/infraestructura/deploy.
Definir el inventario de nodos
Crea un archivo YAML con los nodos. Cada nodo lleva etiquetas (tags) que después usarás para filtrar:
sudo mkdir -p /etc/rundeck/nodes
sudo nano /etc/rundeck/nodes/infraestructura.yaml
web-01:
nodename: web-01
hostname: 203.0.113.10
username: deploy
osFamily: unix
tags: web,produccion
ssh-key-storage-path: keys/project/infraestructura/deploy
web-02:
nodename: web-02
hostname: 203.0.113.11
username: deploy
osFamily: unix
tags: web,produccion
ssh-key-storage-path: keys/project/infraestructura/deploy
sudo chown -R rundeck:rundeck /etc/rundeck/nodes
En el proyecto, ve a Project Settings > Edit Nodes > Add a new Node Source, elige File, formato resourceyaml y ruta /etc/rundeck/nodes/infraestructura.yaml. Guarda y abre Nodes: al filtrar por tags: web deben aparecer web-01 y web-02.
Para probar la conexión, ve a Commands, escribe el filtro tags: web, el comando uptime y pulsa Run on 2 Nodes. Deberías ver la salida de cada servidor.
Paso 8: Crear un runbook de respuesta a incidentes
Un runbook es un job que recoge el procedimiento que el equipo seguiría a mano. Este ejemplo diagnostica un servidor web y, si se lo pides, reinicia un servicio. Guárdalo en tu equipo como runbook-web.yaml:
- name: "Runbook: servidor web degradado"
description: Recoge diagnóstico y opcionalmente reinicia el servicio indicado
loglevel: INFO
executionEnabled: true
nodeFilterEditable: true
nodefilters:
filter: "tags: web"
options:
- name: servicio
description: Servicio a comprobar
required: true
enforced: true
value: nginx
values:
- nginx
- php8.3-fpm
- name: reiniciar
description: Reiniciar el servicio si no está activo
required: true
enforced: true
value: "no"
values:
- "no"
- "si"
sequence:
keepgoing: true
strategy: node-first
commands:
- exec: uptime
- exec: df -h /
- exec: free -h
- exec: systemctl status ${option.servicio} --no-pager --lines=20
- script: |
#!/usr/bin/env bash
set -euo pipefail
servicio="@option.servicio@"
if systemctl is-active --quiet "$servicio"; then
echo "$servicio activo"
elif [ "@option.reiniciar@" = "si" ]; then
sudo systemctl restart "$servicio"
systemctl is-active "$servicio"
else
echo "$servicio NO activo, reinicio no solicitado"
exit 1
fi
En los comandos exec las opciones se referencian como ${option.nombre} y dentro de scripts como @option.nombre@.
Para que el usuario deploy pueda reiniciar solo esos servicios, crea en cada nodo una regla de sudo limitada:
sudo visudo -f /etc/sudoers.d/rundeck-deploy
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart nginx, /usr/bin/systemctl restart php8.3-fpm
Importa el job en Jobs > Job Actions > Upload Definition, elige el archivo y el formato YAML. Ejecútalo con Run Job Now: verás un bloque de salida por nodo y el estado final de cada paso. Todas las ejecuciones quedan en Activity con usuario, hora y log completo, lo que sirve después para el informe del incidente.
Lanzar el runbook desde una alerta
Para que tu sistema de monitorización lance el runbook, crea un webhook en Webhooks > Create Webhook, elige el plugin Run Job, selecciona el job y fija las opciones, por ejemplo -servicio nginx -reiniciar no. Rundeck muestra la URL del webhook, que puedes invocar con un POST:
curl -X POST "https://rundeck.your_domain/api/45/webhook/your_webhook_token#runbook-web"
En Activity debe aparecer una nueva ejecución del runbook lanzada por el webhook. Trata esa URL como un secreto: cualquiera que la conozca puede lanzar el job.
Paso 9: Limitar permisos con una política ACL
El usuario operador1 pertenece al grupo operadores, que aún no tiene permisos. Las políticas ACL son archivos .aclpolicy en /etc/rundeck/ y Rundeck los recarga sin reiniciar. Crea una política que permita ver y ejecutar jobs, pero no crearlos ni editarlos:
sudo nano /etc/rundeck/operadores.aclpolicy
description: Operadores, ver y ejecutar jobs en todos los proyectos
context:
project: '.*'
for:
resource:
- equals:
kind: event
allow: [read]
job:
- allow: [read, run, kill]
node:
- allow: [read, run]
by:
group: operadores
---
description: Operadores, acceso de lectura a nivel de aplicación
context:
application: 'rundeck'
for:
resource:
- equals:
kind: system
allow: [read]
project:
- match:
name: '.*'
allow: [read]
storage:
- allow: [read]
by:
group: operadores
sudo chown rundeck:rundeck /etc/rundeck/operadores.aclpolicy
sudo chmod 640 /etc/rundeck/operadores.aclpolicy
Inicia sesión como operador1 en una ventana privada: debe ver el proyecto y poder pulsar Run Job Now, pero no el botón de crear jobs ni la configuración del proyecto. Si una política tiene errores de sintaxis, aparece marcada en System > Access Control.
Solución de problemas
El servicio no arranca. Revisa el log de arranque, donde suelen aparecer errores de conexión a PostgreSQL o de versión de Java:
sudo journalctl -u rundeckd -n 50 --no-pager
sudo tail -n 100 /var/log/rundeck/service.log
Error Authentication failure o Host key verification failed al ejecutar en un nodo. Comprueba que la ruta ssh-key-storage-path del YAML coincide con la del almacén de claves y que la conexión manual del paso 7 funciona como usuario rundeck.
Los jobs programados se ejecutan a una hora distinta. Rundeck usa la zona horaria del sistema. Compruébala con timedatectl, ajústala con sudo timedatectl set-timezone Europe/Madrid y reinicia rundeckd.
Conclusión
Tienes Rundeck funcionando en Ubuntu 24.04 con PostgreSQL, HTTPS, un inventario de nodos por SSH, un runbook de incidentes que se puede lanzar a mano o desde un webhook y un rol de operador con permisos limitados. Como siguientes pasos, puedes añadir un calendario al job desde la pestaña Schedule, integrar el webhook con tu herramienta de alertas y configurar copias de seguridad de la base de datos rundeck con pg_dump.
