DevOps, CI/CD y contenedores
Instalar Jenkins y crear jobs: controller, agentes, credenciales y disparadores
Principiante12 min de lecturaActualizado
Esta página se tradujo del inglés con ayuda de IA y se cotejó con el original. Leer la versión en inglés
Jenkins sigue siendo el servidor de automatización que hay detrás de buena parte de los pipelines de build empresariales, y casi todos los dolores de cabeza que se le atribuyen vienen de instalaciones que nunca se configuraron bien. Esta guía monta un controller que puedas defender, explica los agentes, las etiquetas y los executors, muestra cómo se gestionan las credenciales y los plugins, y compara los jobs freestyle con los pipelines y el polling con los webhooks.
Lo que aprenderás
- Instalar un controller Jenkins LTS con Docker o con un paquete y completar la configuración de seguridad
- Describir la arquitectura de controller y agentes y conectar un agente por SSH o en modo inbound
- Guardar y referenciar credenciales sin poner jamás un secreto en la configuración de un job
- Crear un job de build funcional y explicar por qué los pipelines han sustituido a los jobs freestyle
- Elegir entre webhooks, polling del SCM y builds programados, y hacer copia de seguridad de JENKINS_HOME
Jenkins lleva ejecutando builds desde 2011 y no da señales de ir a desaparecer, sobre todo porque automatiza cualquier cosa: no tiene opinión sobre tu lenguaje, tu sistema operativo ni tu destino de despliegue, y su ecosistema de plugins cubre prácticamente todas las herramientas que un build haya necesitado jamás. Esa flexibilidad es también su debilidad. Una instalación por defecto es un servidor de automatización sin autenticación que ejecuta comandos de shell arbitrarios, y una instancia de Jenkins que ha crecido sin orden durante cinco años suele ser un montón de jobs configurados a mano que nadie se atreve a tocar.
Esta guía monta justo lo contrario: un controller con una seguridad sensata, el trabajo ejecutándose en agentes y no en el propio servidor, las credenciales en el almacén de credenciales y una configuración que puedes reconstruir. Da por hecho que ya sabes por qué quieres integración continua; el objetivo aquí es una instalación funcional y defendible, y el vocabulario necesario para operarla.
Las piezas y cómo encajan
Una instalación de Jenkins tiene tres partes.
El controller es la aplicación web. Sirve la interfaz y la API REST, guarda la configuración y el historial de builds, planifica los builds y aloja los plugins. No debería ejecutar ningún build por sí mismo.
Un agente (la documentación antigua habla de «slave», y algunos campos de plugins siguen haciéndolo) es una máquina o un contenedor que ejecuta builds. Cada agente anuncia un número de executors —slots de build concurrentes— y un conjunto de etiquetas (labels) como linux, jdk21 o docker. Los jobs piden una etiqueta, y Jenkins los asigna a un agente que coincida y tenga un executor libre.
Un job —Jenkins ahora los llama items— es una unidad de automatización: un pipeline, un proyecto freestyle, un pipeline multibranch, una carpeta que los agrupa. Todo lo que un job produce durante una ejecución vive en un workspace, un directorio del agente que se reutiliza entre builds del mismo job en el mismo agente.
El controller y los agentes se comunican mediante una conexión TCP que transporta un protocolo de remoting. Hay dos sentidos posibles: el controller se conecta al agente por SSH, o el agente se conecta al controller en un puerto dedicado. Cuál uses es una cuestión de firewall, no de funcionalidades.
Instalar el controller
Jenkins se publica como versión semanal y como línea LTS; las versiones LTS reciben correcciones retroportadas durante doce semanas y son las que deberías usar en producción. La línea LTS 2.5x requiere Java 17 o 21: el soporte de Java 11 terminó hace años y las versiones más recientes se niegan a arrancar con él.
La imagen de contenedor es el camino más rápido y deja el host limpio:
docker volume create jenkins_home
docker run -d --name jenkins \
-p 8080:8080 -p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
--restart unless-stopped \
jenkins/jenkins:lts-jdk21
El puerto 8080 es la interfaz web; el 50000 es el puerto de agentes inbound, que solo necesitas publicar si hay agentes que se conectan al controller. El volumen con nombre es JENKINS_HOME, y es el único estado que importa: si puedes restaurar ese volumen, puedes restaurar Jenkins.
En un host Linux, la instalación por paquete coloca JENKINS_HOME en /var/lib/jenkins y se ejecuta bajo systemd con el usuario jenkins:
sudo apt-get install -y openjdk-21-jre fontconfig
# add the Jenkins apt repository and key as documented, then:
sudo apt-get install -y jenkins
sudo systemctl enable --now jenkins
systemctl status jenkins
En ambos casos, la primera página pide una clave de desbloqueo que aparece en el log y se guarda en secrets/initialAdminPassword:
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
# or, for a package install
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
Acepta los plugins sugeridos, crea la primera cuenta de administrador con una contraseña de verdad y configura correctamente la URL de Jenkins: los plugins construyen enlaces a partir de ella, y un valor erróneo produce webhooks y correos que no apuntan a ninguna parte.
Blindar la instancia
Un Jenkins recién instalado no se puede exponer tal cual. Repasa esta lista antes de que nadie más tenga una cuenta.
Pon TLS delante
Ejecuta Jenkins detrás de nginx u otro reverse proxy que termine el HTTPS. Jenkins puede servir TLS por sí mismo, pero un proxy te da renovación de certificados, HTTP/2 y un sitio donde añadir rate limiting. Configura el proxy para que reenvíe las cabeceras originales de host y de esquema, o Jenkins avisará de que su configuración de reverse proxy está rota.Elige un security realm
La base de datos de usuarios integrada basta para un puñado de personas. Para algo mayor, conecta LDAP, Active Directory o un proveedor SAML/OIDC mediante un plugin, de modo que salir de la empresa retire el acceso. Nunca actives el registro libre en una instancia accesible desde fuera.Cambia a autorización por matriz
El valor por defecto, «los usuarios autenticados pueden hacer cualquier cosa», es cómodo y es un error. La seguridad basada en matriz, o una estrategia por roles con el plugin Role Strategy, te permite dar lectura a todos, build a los desarrolladores y administración a dos personas. Asigna los permisos a grupos, no a individuos.Pon a cero los executors del controller
Manage Jenkins → Nodes → Built-In Node → pon el número de executors a 0. Así los builds no tienen dónde ejecutarse salvo en los agentes, que es exactamente lo que se busca.Mantén activas la protección CSRF y la script security
Ambas vienen activadas por defecto y ambas las desactiva de vez en cuando alguien que está depurando una integración. Ninguna debe quedarse apagada. El Groovy que los pipelines ejecutan fuera del sandbox debe aprobarse explícitamente en In-process Script Approval.Aplica parches con un calendario
Jenkins y sus plugins publican avisos de seguridad con regularidad. Suscríbete al feed de avisos, aplica las actualizaciones de plugins cada mes y las de LTS al menos cada trimestre. Un Jenkins sin parchear con acceso de red a producción es un riesgo serio.
Añadir agentes
El agente duradero más sencillo es un host Linux al que se accede por SSH. Prepáralo con un JRE y las herramientas de build que necesites, crea un usuario jenkins con directorio personal y añade la clave pública del controller a su authorized_keys. Después, en Manage Jenkins → Nodes → New Node, elige un agente permanente y rellena:
- Remote root directory: un directorio de trabajo como
/home/jenkins/agent, con disco de sobra. Ahí viven los workspaces. - Labels: descriptivas y específicas, como
linux jdk21 maven docker. Los jobs seleccionan agentes mediante expresiones de etiquetas, así quelinux && dockerfunciona. - Usage: «use this node as much as possible», o «only build jobs with label expressions matching this node» para hardware especializado.
- Launch method: Launch agents via SSH, apuntando al host con la credencial SSH que guardaste en Jenkins.
Para agentes detrás de un firewall que no admite conexiones entrantes, usa en su lugar el método inbound. El controller te da una línea de comandos para ejecutar en el agente:
java -jar agent.jar \
-url https://jenkins.example.com/ \
-secret @/etc/jenkins/agent-secret \
-name build-node-2 \
-workDir /home/jenkins/agent
Ejecútala bajo systemd para que se reconecte tras un reinicio. Una tercera opción, y la que mejor escala, son los agentes efímeros: el plugin de Docker o de Kubernetes arranca un contenedor nuevo para cada build y lo destruye al terminar, de modo que no se filtra estado entre builds y no hay ningún agente que parchear. Cuesta algo de tiempo de arranque por build y merece la pena en cuanto tienes más de un puñado de jobs.
Credenciales
Nunca pongas una contraseña en la configuración de un job, en un script de build ni en una variable de entorno escrita en la interfaz. Jenkins tiene un almacén de credenciales, cifrado con una clave que está en JENKINS_HOME/secrets, y todos los plugins que necesitan un secreto lo leen de ahí.
Las credenciales tienen un tipo —usuario y contraseña, clave privada SSH, secret text (para tokens de API), secret file, certificado— y un ámbito (scope). El ámbito global hace visible una credencial para todos los jobs; el ámbito de sistema la restringe al propio Jenkins, por ejemplo para la clave de conexión de un agente. Guarda las credenciales en una carpeta en lugar de globalmente siempre que un equipo sea dueño de un grupo de jobs: una credencial con ámbito de carpeta es invisible para los jobs de fuera, y es la forma de aislamiento más barata que ofrece Jenkins.
Cada credencial tiene un ID. Dale uno estable y con significado —nexus-deploy, github-app-ci—, porque ese ID es lo que referencia la configuración de los jobs:
withCredentials([usernamePassword(credentialsId: 'nexus-deploy',
usernameVariable: 'NEXUS_USER',
passwordVariable: 'NEXUS_PASS')]) {
sh 'mvn -s settings.xml deploy'
}
Jenkins enmascara los valores en el log de consola, pero el enmascarado es una red de seguridad, no una garantía: un script que codifica un secreto en base64 y lo imprime lo filtrará. Prefiere credenciales con los permisos más reducidos posibles y rótalas periódicamente.
Los jobs freestyle y por qué los pipelines los sustituyeron
Un proyecto freestyle se configura por completo mediante formularios web: gestión del código fuente, disparadores de build, pasos de build y acciones post-build. Crear uno es instructivo porque muestra la anatomía de un build.
Crea un nuevo Freestyle project y luego:
- Source Code Management: Git, con la URL del repositorio y una credencial; indica la rama.
- Build Steps: «Invoke top-level Maven targets» con los goals
clean verify, o «Execute shell» con los comandos que ejecutarías en local. - Post-build Actions: publica los resultados de JUnit desde
**/target/surefire-reports/*.xml, archivatarget/*.jary envía un correo si falla.
Ese job funciona y se crea en cinco minutos. Sus límites aparecen enseguida. La configuración solo existe en el XML del controller, así que no está versionada con el código ni se puede revisar. No puede expresar una secuencia de stages con paralelismo y promoción condicional. No sobrevive a una reconstrucción del controller a menos que restaures todo el JENKINS_HOME. Y las ramas necesitan jobs duplicados.
Un job de pipeline resuelve los cuatro problemas trasladando la definición a un Jenkinsfile que se versiona junto al código fuente. Entonces el build se revisa como código, cada rama lleva su propio pipeline y un controller puede reconstruirse desde cero apuntando nuevos jobs a los repositorios. Usa los jobs freestyle para pequeñas tareas de mantenimiento y los pipelines para todo lo que construya un producto. La guía del Jenkinsfile cubre la sintaxis en profundidad.
Disparar builds
Cuatro disparadores cubren prácticamente todo.
Los webhooks son la opción por defecto correcta. El servidor Git llama a https://jenkins.example.com/github-webhook/ (o al endpoint de webhook genérico) en cada push, y el build arranca en menos de un segundo sin polling desperdiciado. Esto exige que el controller sea accesible desde el servidor Git, lo que en una red privada suele implicar una ruta de entrada en lista blanca.
El polling del SCM pregunta al repositorio si ha cambiado algo, con una programación como H/5 * * * *. Es el plan B cuando los webhooks son imposibles. La H es una extensión de Jenkins que significa «reparte el intervalo según el hash del nombre de este job», lo que reparte las consultas en lugar de que todos los jobs caigan sobre el servidor en el mismo minuto.
Los builds programados (H 2 * * *) se ejecutan haya cambios o no, que es lo que quieres para suites de integración nocturnas, escaneos de vulnerabilidades en dependencias o pruebas de rendimiento largas.
Los disparadores upstream lanzan un job cuando termina otro, formando una cadena. Dentro de un mismo pipeline, los stages los sustituyen; entre repositorios —una biblioteca que dispara a sus consumidores— siguen siendo útiles.
Plugins, actualizaciones y configuración como código
Todo lo que hace Jenkins lo hace a través de plugins, que son también su principal riesgo operativo: cada uno es código que se ejecuta con privilegios completos, y un plugin abandonado por su autor se convierte en un bloqueo en la siguiente actualización de Java. Mantén la lista corta: instala lo que necesita un job, desinstala lo que nada referencia y busca actualizaciones con un calendario, no cuando algo se rompe.
Los plugins que usa casi cualquier instalación: Pipeline (la suite workflow-aggregator), Git, Credentials Binding, Matrix Authorization, JUnit, Warnings Next Generation, Docker Pipeline y Configuration as Code.
Este último merece atención. JCasC permite que la propia configuración del controller viva en un fichero YAML, de modo que la instancia puede recrearse en lugar de restaurarse:
jenkins:
systemMessage: "Managed by configuration as code — do not edit through the UI"
numExecutors: 0
mode: EXCLUSIVE
securityRealm:
local:
allowsSignup: false
authorizationStrategy:
globalMatrix:
entries:
- group:
name: "authenticated"
permissions: ["Overall/Read", "Job/Read"]
- group:
name: "developers"
permissions: ["Job/Build", "Job/Cancel"]
unclassified:
location:
url: "https://jenkins.example.com/"
adminAddress: "[email protected]"
Apunta la variable de entorno CASC_JENKINS_CONFIG a ese fichero, guárdalo en Git y la configuración del controller pasará a ser revisable. Combínalo con una lista de plugins con versiones fijadas y reconstruir la instancia se convierte en un trabajo de quince minutos.
Copias de seguridad y disco
Todo lo que Jenkins sabe está bajo JENKINS_HOME. Una copia de seguridad que cubra los *.xml del nivel superior, jobs/*/config.xml, users/, nodes/ y, de forma crítica, secrets/ basta para reconstruir la instancia. El historial de builds y los workspaces ocupan mucho y son en gran parte prescindibles; excluir jobs/*/builds y workspace mantiene el backup lo bastante pequeño como para ejecutarlo cada noche.
#!/usr/bin/env bash
set -euo pipefail
JENKINS_HOME=${JENKINS_HOME:-/var/lib/jenkins}
STAMP=$(date +%F)
tar -czf "/backup/jenkins-${STAMP}.tar.gz" \
-C "$JENKINS_HOME" \
--exclude='jobs/*/builds' \
--exclude='workspace' \
--exclude='caches' \
.
Cifra el archivo: contiene el directorio secrets y, con él, todas las credenciales que guarda Jenkins. Después prueba una restauración al menos una vez: una copia de seguridad que nadie ha restaurado es una hipótesis.
El disco es el otro problema recurrente. Define una política de retención de builds en cada job y limpia los workspaces en los agentes que alojan muchos jobs; un controller que se queda sin disco corrompe la configuración de los jobs al escribirla.
Errores comunes
- Ejecutar builds en el controller. Da a cada build acceso de lectura a todas las credenciales y tumba el servidor cuando un test se come toda la memoria.
- Configurarlo todo a golpe de clic. Al cabo de un año nadie sabe por qué funciona un job. Lleva la lógica de build a un
Jenkinsfiley los ajustes del controller a JCasC. - Secretos pegados en los pasos de build. Acaban en el XML de los jobs, en los backups y en los logs de consola. Usa el almacén de credenciales y
withCredentials. - No actualizar nunca. Los avisos del core y de los plugins se acumulan, y saltar cuatro versiones LTS de golpe es mucho más difícil que hacer una por trimestre.
- Historial de builds sin límite. La retención por defecto lo guarda todo para siempre, y los logs de consola más los artefactos archivados acabarán llenando el disco.
- Un único agente gigante compartido. Los jobs se pelean por puertos, cachés y disco. Los agentes efímeros en contenedores eliminan toda una categoría de misterios del tipo «solo falla en el nodo 3».
- Sin responsable. Un Jenkins que todo el mundo usa y nadie mantiene se degrada de forma previsible. Nombra a un responsable y dale tiempo para ello.
Ideas clave
- Usa la línea LTS con Java 17 o 21, reserva el controller para la planificación y la interfaz, y pon a cero su número de executors.
- Protege la instancia antes de abrirla: TLS mediante un proxy, un security realm de verdad, autorización por matriz, CSRF y script security activadas, y un calendario de parches.
- Los agentes se conectan de salida por SSH o de entrada por el puerto de agentes; los agentes efímeros de Docker o Kubernetes dan builds limpios sin máquinas que mantener.
- Guarda cada secreto en el almacén de credenciales, limita su ámbito a una carpeta cuando sea posible y referéncialo con un ID estable.
- Los jobs freestyle son una demostración útil de cinco minutos; los pipelines definidos en un
Jenkinsfileversionado son lo que debe usar la automatización en producción. - Dispara con webhooks siempre que puedas, recurre al polling con hash como alternativa y usa builds programados para el trabajo nocturno.
JENKINS_HOMEes el sistema entero: haz copia de seguridad incluyendosecrets/, cifra el archivo, limita la retención de builds y mantén la configuración reproducible con JCasC.
Fuentes y lecturas recomendadas
Preguntas frecuentes
- ¿Deberían ejecutarse builds alguna vez en el controller de Jenkins?
- No. Un build que corre en el controller tiene acceso a JENKINS_HOME, que contiene todas las credenciales, todas las definiciones de jobs y las claves de cifrado que las protegen. Pon a cero el número de executors del controller y ejecuta todo el trabajo en agentes. Es la medida de hardening más valiosa sobre una instalación por defecto, y además evita que un build desbocado tumbe el servidor entero.
- ¿Sigue mereciendo la pena Jenkins frente a los servicios de CI alojados?
- Depende de tus restricciones, no de las modas. Los servicios alojados son más sencillos cuando tu código ya está en su plataforma y tus builds no necesitan nada fuera de lo común. Jenkins compensa cuando los builds tienen que ejecutarse dentro de una red privada, necesitan hardware especializado o toolchains con licencia, o deben integrarse con sistemas que no tienen conector cloud. A cambio, las actualizaciones, las copias de seguridad y la seguridad corren de tu cuenta.
- ¿Cuántos executors debería tener un agente?
- Empieza con un executor por núcleo de CPU y reduce si los builds consumen mucha memoria o se pelean por el disco. Un executor es un slot de build concurrente, así que un agente con cuatro executors ejecuta cuatro builds a la vez sobre el mismo sistema de archivos. Las suites de tests que usan puertos fijos o una base de datos compartida acabarán chocando, y por eso los equipos suelen terminar con uno o dos executors por agente.
- ¿Qué hay que incluir exactamente en la copia de seguridad?
- JENKINS_HOME lo guarda todo: configuraciones de jobs, jars de plugins y sus ajustes, el almacén de credenciales, los usuarios y el historial de builds. Las partes críticas son los ficheros XML del nivel superior, el directorio jobs sin builds ni workspaces, el directorio users y el directorio secrets. Sin secrets, las credenciales cifradas del backup no se pueden descifrar, así que hay que incluirlo y proteger la copia en consecuencia.