Instalación de Rundeck: Automatización de Jobs y Respuesta a Incidentes
Rundeck es una plataforma de automatización operacional que permite definir, programar y ejecutar runbooks de forma centralizada, facilitando tanto la automatización rutinaria como la respuesta a incidentes. Con soporte para control de acceso granular, gestión de nodos remotos y triggers via webhook, Rundeck es la solución ideal para equipos de operaciones que gestionan servidores Linux en producción.
Requisitos Previos
- Ubuntu 20.04/22.04 o CentOS/Rocky Linux 8+
- Java 11+ (OpenJDK recomendado)
- Al menos 2 GB de RAM (4 GB recomendado para producción)
- MySQL 8.0+ o PostgreSQL 14+ (para producción, SQLite por defecto)
- Acceso SSH a los nodos remotos que se van a gestionar
- Acceso root o usuario con privilegios sudo
Instalación de Rundeck
Instalación en Ubuntu/Debian
# Instalar dependencias
sudo apt-get update
sudo apt-get install -y openjdk-11-jdk curl gnupg
# Añadir repositorio de Rundeck
curl -s https://packagecloud.io/pagerduty/rundeck/gpgkey | sudo apt-key add -
cat > /etc/apt/sources.list.d/rundeck.list << 'EOF'
deb https://packagecloud.io/pagerduty/rundeck/ubuntu/ focal main
EOF
sudo apt-get update
sudo apt-get install -y rundeck
# Iniciar y habilitar el servicio
sudo systemctl enable rundeck
sudo systemctl start rundeck
# Verificar el estado
sudo systemctl status rundeck
Instalación en CentOS/Rocky Linux
# Añadir repositorio RPM
sudo curl -o /etc/yum.repos.d/rundeck.repo \
https://packagecloud.io/pagerduty/rundeck/config_file.repo?os=rpm_any
# Instalar
sudo yum install -y java-11-openjdk rundeck
# Iniciar servicio
sudo systemctl enable rundeck
sudo systemctl start rundeck
Instalación con Docker
# Crear directorio de datos persistente
mkdir -p /opt/rundeck/{data,logs}
# Docker Compose para Rundeck con MySQL
cat > /opt/rundeck/docker-compose.yml << 'EOF'
version: '3.8'
services:
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: root_password_seguro
MYSQL_DATABASE: rundeck
MYSQL_USER: rundeck
MYSQL_PASSWORD: rundeck_pass_123
volumes:
- mysql_data:/var/lib/mysql
rundeck:
image: rundeck/rundeck:latest
restart: unless-stopped
ports:
- "4440:4440"
environment:
RUNDECK_DATABASE_DRIVER: org.mariadb.jdbc.Driver
RUNDECK_DATABASE_URL: jdbc:mysql://db:3306/rundeck?autoReconnect=true&useSSL=false
RUNDECK_DATABASE_USERNAME: rundeck
RUNDECK_DATABASE_PASSWORD: rundeck_pass_123
RUNDECK_GRAILS_URL: http://rundeck.mi-dominio.com:4440
RUNDECK_SERVER_ADDRESS: 0.0.0.0
volumes:
- rundeck_data:/home/rundeck/server/data
- /opt/rundeck/logs:/home/rundeck/var/logs
depends_on:
- db
volumes:
mysql_data:
rundeck_data:
EOF
cd /opt/rundeck
docker-compose up -d
Configuración Inicial
# Acceder a la interfaz web: http://servidor:4440
# Credenciales por defecto: admin / admin (CAMBIAR inmediatamente)
# Configuración del archivo principal de Rundeck
sudo cat > /etc/rundeck/rundeck-config.properties << 'EOF'
# URL base de Rundeck
grails.serverURL=https://rundeck.mi-dominio.com
# Base de datos (producción con MySQL)
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/rundeck?autoReconnect=true
dataSource.username=rundeck
dataSource.password=rundeck_pass_123
# Configuración de seguridad
rundeck.security.requestHeaderAuthentication.enabled=false
EOF
# Cambiar contraseña del administrador
# Editar /etc/rundeck/realm.properties
sudo sed -i 's/admin:admin,user,admin,architect,deploy,build/admin:NUEVA_PASSWORD,user,admin,architect,deploy,build/' \
/etc/rundeck/realm.properties
sudo systemctl restart rundeck
Definición de Jobs
Los jobs son la unidad central de automatización en Rundeck:
# Crear un job via API (primero obtener token de API)
# Panel Admin > User > Profile > API Tokens > Generate Token
# Crear proyecto
curl -X POST http://localhost:4440/api/40/projects \
-H "X-Rundeck-Auth-Token: TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "infraestructura",
"description": "Automatización de infraestructura",
"config": {
"project.description": "Gestión de servidores de producción"
}
}'
# Crear job en formato YAML
cat > /tmp/job-deploy.yaml << 'EOF'
- name: Despliegue de Aplicación
description: Despliega la última versión de la aplicación en producción
id: deploy-app-v1
loglevel: INFO
sequence:
keepgoing: false
strategy: node-first
commands:
# Paso 1: Verificar salud del servidor
- exec: "systemctl is-active nginx || exit 1"
# Paso 2: Hacer backup de la versión actual
- exec: "cp -r /var/www/app /var/www/app.bak.$(date +%Y%m%d)"
# Paso 3: Descargar nueva versión
- exec: "cd /opt/releases && git pull origin main"
# Paso 4: Instalar dependencias
- exec: "cd /opt/releases && npm install --production"
# Paso 5: Reiniciar la aplicación
- exec: "systemctl restart app"
# Paso 6: Verificar que la aplicación responde
- exec: "sleep 5 && curl -f http://localhost:3000/health"
nodefilters:
filter: "tags: web-server"
schedule:
time:
hour: "2"
minute: "0"
seconds: "0"
month: "*"
year: "*"
dayofweek: "*"
scheduleEnabled: true
EOF
# Importar el job al proyecto
curl -X POST "http://localhost:4440/api/40/project/infraestructura/jobs/import" \
-H "X-Rundeck-Auth-Token: TU_TOKEN" \
-H "Content-Type: application/yaml" \
--data-binary @/tmp/job-deploy.yaml
# Ejecutar el job manualmente
curl -X POST "http://localhost:4440/api/40/job/JOB_ID/run" \
-H "X-Rundeck-Auth-Token: TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{"argString": "-entorno produccion"}'
Gestión de Nodos
Definir los nodos (servidores) que Rundeck gestiona:
# Crear archivo de recursos de nodos
sudo mkdir -p /var/rundeck/projects/infraestructura/etc
cat > /var/rundeck/projects/infraestructura/etc/resources.yaml << 'EOF'
# Inventario de nodos gestionados por Rundeck
web-01:
nodename: web-01
hostname: 192.168.1.10
username: deploy
tags: web-server,produccion
description: "Servidor web principal"
osFamily: unix
ssh-key-storage-path: "keys/web-servers/deploy_key"
web-02:
nodename: web-02
hostname: 192.168.1.11
username: deploy
tags: web-server,produccion
description: "Servidor web secundario"
osFamily: unix
ssh-key-storage-path: "keys/web-servers/deploy_key"
db-primary:
nodename: db-primary
hostname: 192.168.1.20
username: rundeck
tags: database,mysql,produccion
description: "Base de datos MySQL principal"
osFamily: unix
ssh-key-storage-path: "keys/db-servers/rundeck_key"
EOF
# Subir claves SSH al almacén de Rundeck
curl -X POST "http://localhost:4440/api/40/storage/keys/web-servers/deploy_key" \
-H "X-Rundeck-Auth-Token: TU_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @~/.ssh/deploy_key
# Verificar nodos disponibles
curl "http://localhost:4440/api/40/project/infraestructura/nodes" \
-H "X-Rundeck-Auth-Token: TU_TOKEN"
Políticas ACL
Control de acceso granular con políticas ACLPOLICY:
# Crear política para operadores (solo pueden ejecutar jobs, no crearlos)
cat > /etc/rundeck/acl/operadores.aclpolicy << 'EOF'
# Política ACL para el rol de operadores
description: Política para operadores - solo ejecución
context:
project: '.*'
for:
resource:
- equals:
kind: job
allow: [read, run]
- equals:
kind: node
allow: [read, run]
job:
- allow: [read, run, kill]
node:
- allow: [read, run]
by:
group: operadores
---
description: Acceso a la aplicación
context:
application: rundeck
for:
resource:
- equals:
kind: project
allow: [read]
project:
- match:
name: '.*'
allow: [read]
by:
group: operadores
EOF
# Verificar la sintaxis de la política ACL
sudo java -jar /var/lib/rundeck/bootstrap/rundeck-cli.jar \
aclvalidate -f /etc/rundeck/acl/operadores.aclpolicy
sudo systemctl reload rundeck
Triggers via Webhook
Ejecutar jobs automáticamente via HTTP:
# Crear webhook desde el panel: Jobs > Webhooks > Add Webhook
# O via API
curl -X POST "http://localhost:4440/api/40/project/infraestructura/webhooks" \
-H "X-Rundeck-Auth-Token: TU_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "deploy-trigger",
"enabled": true,
"eventPlugin": "webhook-run-job",
"config": {
"jobId": "JOB_ID",
"argString": "-entorno produccion"
}
}'
# El webhook se invoca con una petición HTTP POST:
curl -X POST "http://localhost:4440/api/40/webhook/TOKEN_WEBHOOK" \
-H "Content-Type: application/json" \
-d '{"branch": "main", "commit": "abc123"}'
# Integración con GitHub Actions (en .github/workflows/deploy.yml):
# - name: Trigger Rundeck Deploy
# run: |
# curl -X POST "$RUNDECK_WEBHOOK_URL" \
# -H "Content-Type: application/json" \
# -d '{"commit": "${{ github.sha }}"}'
Runbooks de Respuesta a Incidentes
Definir procedimientos estandarizados para incidentes:
# Job de respuesta a servidor no disponible
cat > /tmp/runbook-servidor-caido.yaml << 'EOF'
- name: "RUNBOOK: Servidor No Disponible"
description: "Procedimiento de respuesta cuando un servidor deja de responder"
loglevel: INFO
sequence:
keepgoing: false
commands:
# Paso 1: Verificar conectividad de red
- exec: "ping -c 3 ${node.hostname} && echo 'RED OK' || echo 'SIN RED'"
# Paso 2: Verificar servicios críticos
- script: |
#!/bin/bash
# Comprobar estado de servicios esenciales
for servicio in nginx mysql sshd; do
if ! systemctl is-active --quiet $servicio; then
echo "FALLO: $servicio no está activo"
systemctl start $servicio
sleep 3
systemctl is-active --quiet $servicio && echo "$servicio reiniciado OK"
else
echo "OK: $servicio activo"
fi
done
# Paso 3: Verificar espacio en disco
- exec: "df -h / | awk 'NR==2{print \"Disco: \"$5\" usado\"}'"
# Paso 4: Verificar carga del sistema
- exec: "uptime && free -h"
# Paso 5: Enviar informe de estado
- exec: "journalctl -n 50 --no-pager > /tmp/incident_log.txt"
options:
- name: servidor
description: "Nombre del servidor afectado"
required: true
- name: severidad
description: "Nivel de severidad del incidente"
values:
- "critico"
- "alto"
- "medio"
required: true
EOF
curl -X POST "http://localhost:4440/api/40/project/infraestructura/jobs/import" \
-H "X-Rundeck-Auth-Token: TU_TOKEN" \
-H "Content-Type: application/yaml" \
--data-binary @/tmp/runbook-servidor-caido.yaml
Solución de Problemas
Rundeck no arranca (error de Java):
# Verificar versión de Java
java -version
# Revisar logs de inicio
sudo journalctl -u rundeck -n 50
sudo tail -f /var/log/rundeck/service.log
No se puede conectar a los nodos via SSH:
# Probar conexión SSH manual
ssh -i /path/to/key [email protected]
# Verificar que la clave está correctamente almacenada en Rundeck
curl "http://localhost:4440/api/40/storage/keys/web-servers/deploy_key" \
-H "X-Rundeck-Auth-Token: TU_TOKEN"
# Revisar el log de ejecución del job para ver el error SSH específico
El scheduler no ejecuta los jobs:
# Verificar que la zona horaria está configurada correctamente
sudo cat /etc/rundeck/profile | grep JAVA_OPTS
# Añadir si falta: JAVA_OPTS="... -Duser.timezone=Europe/Madrid"
sudo systemctl restart rundeck
Conclusión
Rundeck transforma la gestión operacional al centralizar la ejecución de runbooks, scripts y tareas de mantenimiento en una plataforma con control de acceso y auditoría completa. Su integración via webhooks permite responder automáticamente a alertas de herramientas de monitorización, mientras que el sistema de jobs programados elimina intervención manual en tareas rutinarias. Con políticas ACL granulares, Rundeck habilita el autoservicio seguro para equipos de desarrollo sin comprometer la seguridad de la infraestructura.


