Jenkins es un servidor de automatización de código abierto que ejecuta tareas de integración y entrega continua (CI/CD): compilar, probar y desplegar tu código cada vez que cambia. En este tutorial instalarás la versión LTS de Jenkins en Ubuntu 24.04 desde el repositorio oficial, la dejarás escuchando solo en local y la publicarás detrás de Nginx con un certificado de Let's Encrypt. Al terminar completarás el asistente inicial y ejecutarás tu primer pipeline declarativo.

Requisitos previos

Para seguir esta guía necesitas:

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath, con al menos 2 GB de RAM (4 GB si vas a ejecutar compilaciones en el propio servidor) y 20 GB libres en disco.
  • Un usuario no root con privilegios sudo y UFW activo con OpenSSH permitido.
  • Un dominio o subdominio (en esta guía jenkins.tu_dominio) con un registro DNS A que apunte a la IP del servidor. Lo necesitas para el certificado HTTPS.

Paso 1: Instalar Java

Jenkins es una aplicación Java y necesita un JRE compatible. Las versiones LTS actuales funcionan con Java 21, que está en los repositorios de Ubuntu 24.04. El paquete fontconfig es necesario para que Jenkins genere gráficos e informes:

sudo apt update
sudo apt install fontconfig openjdk-21-jre

Comprueba la versión instalada:

java -version
openjdk version "21.0.8" 2025-07-15
OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1)
OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing)

No hace falta definir JAVA_HOME: el servicio de Jenkins encuentra Java a través de /usr/bin/java.

Paso 2: Añadir el repositorio oficial de Jenkins

Jenkins publica dos canales: weekly, con novedades cada semana, y LTS, más estable y con parches de seguridad. Para un servidor de producción usa LTS, cuyo repositorio es debian-stable.

Descarga la clave con la que Jenkins firma sus paquetes:

sudo install -m 0755 -d /etc/apt/keyrings
sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2026.key

Añade el repositorio indicando que solo se confíe en esa clave:

echo "deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/" | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null

Actualiza el índice y comprueba que el paquete viene del repositorio de Jenkins:

sudo apt update
apt-cache policy jenkins
jenkins:
  Installed: (none)
  Candidate: 2.516.3
  Version table:
     2.516.3 500
        500 https://pkg.jenkins.io/debian-stable binary/ Packages

El número de versión será distinto; lo importante es el origen pkg.jenkins.io.

Paso 3: Instalar Jenkins

Instala el paquete. Crea el usuario jenkins, el directorio de datos /var/lib/jenkins y un servicio de systemd que arranca automáticamente:

sudo apt install jenkins

Comprueba que el servicio está activo:

sudo systemctl status jenkins
● jenkins.service - Jenkins Continuous Integration Server
     Loaded: loaded (/usr/lib/systemd/system/jenkins.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-25 10:21:07 UTC; 12s ago

Si el servicio no arranca, revisa el motivo con sudo journalctl -u jenkins -n 50.

Paso 4: Hacer que Jenkins escuche solo en localhost

Por defecto Jenkins escucha en el puerto 8080 de todas las interfaces. Hasta que completes el asistente, cualquiera que llegue a ese puerto podría intentar configurarlo, y además el tráfico va sin cifrar. Como Nginx será la única puerta de entrada, limita Jenkins a 127.0.0.1.

El servicio lee su configuración de variables de entorno. Crea un override de systemd en lugar de modificar el archivo del paquete, que se sobrescribiría en cada actualización:

sudo systemctl edit jenkins

Añade estas líneas en la zona indicada del editor y guarda:

[Service]
Environment="JENKINS_LISTEN_ADDRESS=127.0.0.1"

Reinicia Jenkins y comprueba en qué dirección escucha:

sudo systemctl restart jenkins
sudo ss -tlnp | grep 8080
LISTEN 0      50     [::ffff:127.0.0.1]:8080            *:*    users:(("java",pid=4211,fd=8))

Paso 5: Configurar Nginx como proxy inverso

Instala Nginx y permite el tráfico HTTP y HTTPS en el cortafuegos:

sudo apt install nginx
sudo ufw allow 'Nginx Full'

Crea el archivo del sitio:

sudo nano /etc/nginx/sites-available/jenkins

Pega esta configuración, basada en la recomendada por el proyecto Jenkins, y sustituye jenkins.tu_dominio:

upstream jenkins {
    keepalive 32;
    server 127.0.0.1:8080;
}

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    listen [::]:80;
    server_name jenkins.tu_dominio;

    location / {
        proxy_pass http://jenkins;
        proxy_http_version 1.1;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Upgrade $http_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_max_temp_file_size 0;
        proxy_request_buffering off;
        proxy_read_timeout 90;
        client_max_body_size 50m;
    }
}

Las cabeceras Upgrade y Connection permiten las conexiones WebSocket que usan los agentes y la consola en vivo, y X-Forwarded-Proto le dice a Jenkins que el usuario llega por HTTPS.

Activa el sitio, comprueba la sintaxis y recarga Nginx:

sudo ln -s /etc/nginx/sites-available/jenkins /etc/nginx/sites-enabled/
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: Obtener el certificado HTTPS

Instala Certbot con el plugin de Nginx y solicita el certificado. Certbot modifica el bloque server, añade la redirección de HTTP a HTTPS y programa la renovación automática:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d jenkins.tu_dominio

Comprueba que la renovación funcionará:

sudo certbot renew --dry-run
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/jenkins.tu_dominio/fullchain.pem (success)

Paso 7: Completar el asistente inicial

Abre https://jenkins.tu_dominio en el navegador. Jenkins pide una contraseña de desbloqueo que genera en la primera ejecución. Léela en el servidor:

sudo cat /var/lib/jenkins/secrets/initialAdminPassword
3f5b1c7e9a2d4e6f8a0b1c2d3e4f5a6b

Pégala en el formulario y sigue el asistente:

  1. Personalizar Jenkins: elige Install suggested plugins. Incluye Pipeline, Git y Credentials, que son los que usarás a continuación.
  2. Crear el primer usuario administrador: define un usuario propio con una contraseña robusta. A partir de ahí la contraseña inicial deja de funcionar.
  3. Configuración de la instancia: comprueba que la Jenkins URL es https://jenkins.tu_dominio/. Jenkins la usa para generar enlaces en correos y notificaciones.

Tras el asistente verás el panel principal. Entra en Manage Jenkins: si aparece un aviso de que la configuración del proxy inverso está rota, revisa las cabeceras Host y X-Forwarded-Proto del paso 5.

Paso 8: Crear tu primer pipeline

Un pipeline describe en código las etapas de tu proceso de CI/CD. Crea uno de prueba para comprobar que todo funciona:

  1. En el panel, pulsa New Item.
  2. Escribe hola-pipeline, selecciona Pipeline y pulsa OK.
  3. En la sección Pipeline, deja Pipeline script y pega el siguiente código:
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'echo "Compilando en $(hostname)"'
                sh 'java -version'
            }
        }
        stage('Test') {
            steps {
                sh 'echo "Ejecutando pruebas"'
            }
        }
    }

    post {
        always {
            echo "Resultado: ${currentBuild.currentResult}"
        }
    }
}
  1. Guarda y pulsa Build Now.

Abre la ejecución y entra en Console Output. Deberías ver algo así al final:

[Pipeline] echo
Resultado: SUCCESS
[Pipeline] }
[Pipeline] // stage
[Pipeline] End of Pipeline
Finished: SUCCESS

En un proyecto real, guarda ese código en un archivo Jenkinsfile en la raíz del repositorio y crea el trabajo con Pipeline script from SCM, indicando la URL del repositorio Git y unas credenciales. Así el pipeline se versiona junto al código.

Paso 9: Proteger la instalación

Unas pocas medidas cubren los riesgos más comunes:

  • No ejecutes compilaciones en el controlador: el nodo integrado (Built-In Node) tiene acceso a /var/lib/jenkins, donde están todas las credenciales. Para uso real, conecta agentes en otras máquinas y pon a 0 el campo Number of executors del nodo integrado en Manage Jenkins > Nodes.
  • Autorización: en Manage Jenkins > Security, mantén Jenkins' own user database y elige una estrategia de autorización que no dé permisos a usuarios anónimos. Para equipos, el plugin Matrix Authorization Strategy permite asignar permisos por usuario o grupo.
  • Credenciales: guarda tokens y claves SSH en Manage Jenkins > Credentials y úsalos desde el pipeline con withCredentials o credentials(), nunca escritos en el Jenkinsfile.
  • Actualizaciones: Jenkins y sus plugins publican avisos de seguridad con frecuencia. Actualiza el paquete con sudo apt upgrade y los plugins desde Manage Jenkins > Plugins > Updates.

Comprueba que el puerto 8080 no es accesible desde fuera (ejecútalo desde tu equipo, no desde el servidor):

curl -m 5 http://ip_de_tu_servidor:8080
curl: (7) Failed to connect to ip_de_tu_servidor port 8080 after 41 ms: Couldn't connect to server

Paso 10: Copias de seguridad

Toda la configuración de Jenkins (trabajos, usuarios, credenciales cifradas, plugins) vive en /var/lib/jenkins. Los espacios de trabajo (workspace) y las cachés se pueden regenerar, así que exclúyelos para ahorrar espacio:

sudo tar -czf "jenkins-$(date +%F).tar.gz" -C /var/lib --exclude='jenkins/workspace' --exclude='jenkins/caches' jenkins

Guarda el archivo fuera del servidor. Incluye secrets/: sin secrets/master.key las credenciales guardadas no se pueden descifrar al restaurar.

Para restaurar en un servidor nuevo, instala Jenkins siguiendo esta guía, detén el servicio, extrae la copia y devuelve la propiedad al usuario jenkins:

sudo systemctl stop jenkins
sudo tar -xzf jenkins-2026-09-25.tar.gz -C /var/lib
sudo chown -R jenkins:jenkins /var/lib/jenkins
sudo systemctl start jenkins

Solución de problemas

502 Bad Gateway al abrir Jenkins: Jenkins aún está arrancando (tarda hasta un minuto) o no está en marcha. Revisa sudo systemctl status jenkins y sudo journalctl -u jenkins -n 50.

Aviso "It appears that your reverse proxy set up is broken": la Jenkins URL de Manage Jenkins > System no coincide con la dirección real o falta alguna cabecera proxy_set_header del paso 5.

El servicio falla con OutOfMemoryError: el servidor tiene poca RAM para el número de trabajos o plugins. Añade memoria o conecta agentes para sacar las compilaciones del controlador.

apt update muestra NO_PUBKEY para pkg.jenkins.io: la clave de firma ha cambiado. Descarga la actual como en el paso 2.

Conclusión

Tienes Jenkins LTS instalado desde el repositorio oficial, accesible solo a través de Nginx con HTTPS, con un usuario administrador y un primer pipeline funcionando. Como siguientes pasos, conecta un agente en otra máquina para ejecutar las compilaciones, mueve tus pipelines a un Jenkinsfile en cada repositorio y configura un webhook en tu servidor Git para lanzar las compilaciones con cada push.