Por qué alojar su CI/CD con Jenkins
Una CI alojada es práctica hasta que los builds se multiplican: cada minuto por encima de la cuota se factura, los proyectos grandes esperan su turno y las claves de despliegue de sus servidores se guardan en el proveedor. Jenkins invierte este modelo. Funciona en su VPS, ejecuta tantos builds como permitan sus máquinas y guarda sus credenciales cifradas en casa.
Es también la herramienta que la mayoría de los equipos ya conoce: un Jenkinsfile se lee sin formación, la documentación es abundante y casi todas las herramientas del mercado tienen su plugin de Jenkins.
Lo que aporta Jenkins
- Pipelines como código — un Jenkinsfile versionado con el proyecto describe cada etapa, revisada en code review como el resto.
- Webhooks Git — GitHub, GitLab, Gitea o Forgejo lanzan el build en cada push o pull request.
- Multibranch — cada rama y cada pull request recibe su propio pipeline, creado automáticamente.
- Agentes de build — los builds se ejecutan en máquinas dedicadas, conectadas por SSH.
- Más de 2.000 plugins — Docker, Kubernetes, SonarQube, Slack, informes de pruebas JUnit.
- Credenciales cifradas — claves SSH y tokens inyectados en el pipeline, enmascarados en los registros.
Jenkins frente a otras CI autoalojadas
Desplace la tabla
| Jenkins | Woodpecker CI | OneDev | |
|---|---|---|---|
| Licencia | MIT | Apache-2.0 | MIT |
| Definición del pipeline | Jenkinsfile (Groovy) | YAML | YAML o editor visual |
| Forja Git integrada | No, se conecta a la suya | No, se conecta a la suya | Sí |
| Ecosistema de plugins | Más de 2.000 plugins | Plugins como imágenes Docker | Funciones integradas |
| Ideal para | Pipelines complejos, equipos existentes | Pipelines sencillos en contenedores | Equipo pequeño que quiere todo en uno |
Requisitos previos
Un VPS Ubuntu 24.04 con 2 GB de RAM y 2 vCPU basta para el controlador; cuente 4 GB si sus builds se ejecutan en la misma máquina. Necesita Docker y el plugin Compose, un nombre de dominio (o un subdominio) que apunte al VPS, y nginx con un certificado TLS para publicarlo en HTTPS. Jenkins debe responder en una dirección HTTPS estable: es la que sus repositorios llaman para los webhooks.
Instalar Jenkins con Docker Compose
Crear el archivo Compose
Este
docker-compose.ymlarranca Jenkins LTS sobre Java 21. El puerto solo se publica en la interfaz de bucle local: solo nginx accede a él. Todos los datos (jobs, plugins, credenciales, historial) viven en el volumenjenkins-home. El puerto 50000 de los agentes entrantes no se publica: los agentes se conectan por SSH.services: jenkins: image: jenkins/jenkins:2.580.1-lts-jdk21 restart: unless-stopped ports: - "127.0.0.1:8104:8080" environment: JAVA_OPTS: -Djava.awt.headless=true volumes: - jenkins-home:/var/jenkins_home healthcheck: test: ["CMD-SHELL", "curl -fsS -o /dev/null http://localhost:8080/login || exit 1"] interval: 15s retries: 10 start_period: 60s volumes: jenkins-home: {}Arrancar el contenedor
Coloque el archivo en
/opt/jenkinsy arranque la stack. El primer arranque tarda unos treinta segundos;docker compose psdebe mostrar el estadohealthy.mkdir -p /opt/jenkins && cd /opt/jenkins docker compose up -d docker compose psPublicar Jenkins en HTTPS tras nginx
En el bloque
serverde su dominio, transmita las cabecerasX-Forwarded-*: sin ellas, Jenkins genera enlaces en HTTP y señala un proxy inverso mal configurado.location / { proxy_pass http://127.0.0.1:8104; 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_set_header X-Forwarded-Port 443; }Desbloquear Jenkins
Abra
https://su-dominio. Jenkins pide la contraseña inicial escrita en su volumen de datos:docker compose exec jenkins cat /var/jenkins_home/secrets/initialAdminPasswordInstale después los plugins sugeridos, cree su cuenta de administrador y confirme la URL HTTPS de la instancia.
No ejecute builds en el controlador
El controlador de Jenkins guarda todas sus credenciales. Un build que se ejecute en él puede leerlas. En Administrar Jenkins, ponga a 0 el número de ejecutores del nodo integrado y conecte al menos un agente por SSH. Por la misma razón, no monte el socket Docker del VPS en el contenedor de Jenkins: daría a cualquier build acceso root al servidor.
Escribir un primer pipeline
Cree un «Multibranch Pipeline» que apunte a su repositorio y añada un Jenkinsfile en la raíz. Este ejemplo construye y prueba cada rama, y solo despliega la rama main, en un agente con la etiqueta linux:
pipeline {
agent { label 'linux' }
stages {
stage('Build') { steps { sh 'make build' } }
stage('Test') { steps { sh 'make test' } }
stage('Deploy') {
when { branch 'main' }
steps { sh './deploy.sh' }
}
}
}Añada por último un webhook en su repositorio hacia https://su-dominio/github-webhook/ para GitHub, o hacia la URL que indique el plugin de su forja. Cada push lanza entonces un build.
Credenciales y agentes de build
Las claves SSH, los tokens de API y las contraseñas de despliegue se guardan en Administrar Jenkins, Credentials. Jenkins las almacena cifradas en su volumen y solo las inyecta en un build cuando una etapa las pide, con withCredentials o la directiva environment de un Jenkinsfile; su valor se enmascara en los registros. Dé a cada credencial el alcance más estrecho posible: una clave de despliegue por servidor de destino, un token de solo lectura para clonar los repositorios.
Para los agentes, lo más sencillo es un segundo VPS con Java y Docker instalados. En Administrar Jenkins, Nodes, añada un nodo permanente con el método de arranque «via SSH», la dirección del VPS y una clave SSH guardada como credencial. Póngale una etiqueta, por ejemplo linux, y apúntela en sus pipelines. El controlador ya solo orquesta, y un build comprometido nunca accede a sus otros secretos.
Copias de seguridad y actualización de Jenkins
Todo el estado de Jenkins vive en el volumen jenkins-home: jobs, configuración, plugins, credenciales cifradas e historial de builds. Un archivo de este volumen basta para restaurarlo todo. Detenga Jenkins durante la copia para obtener un archivo coherente:
cd /opt/jenkins
docker compose stop jenkins
docker run --rm -v jenkins_jenkins-home:/data -v \"$PWD\":/backup alpine tar czf /backup/jenkins-home.tar.gz -C /data .
docker compose start jenkinsPara actualizar, siga la línea LTS, publicada aproximadamente cada doce semanas con correcciones intermedias: sustituya la etiqueta de la imagen en docker-compose.yml y ejecute docker compose pull y docker compose up -d. Actualice después los plugins desde Administrar Jenkins, Plugins, y lea los avisos de seguridad que publica el proyecto: la mayoría de las vulnerabilidades corregidas afectan a plugins, no al núcleo.
Solución de problemas
«It appears that your reverse proxy set up is broken»: nginx no transmite X-Forwarded-Proto o la URL de Jenkins no está en HTTPS. Corrija el bloque location y después la URL en Administrar Jenkins, System.
El contenedor se reinicia en bucle: lea los registros. La causa más frecuente es la falta de memoria; dé al VPS al menos 2 GB de RAM.
docker compose logs --tail=100 jenkinsLos webhooks no llegan: revise en el repositorio el historial de entregas del webhook y compruebe que la dirección llamada es la URL HTTPS pública de Jenkins.
Instalación en un clic desde el Marketplace de ServOrbit
En un VPS de ServOrbit, Jenkins se instala desde el Marketplace: elija la dirección, pulse Instalar y el script despliega Jenkins LTS en Docker, con su volumen de datos y el proxy inverso nginx en HTTPS. La contraseña inicial de administración aparece en su área de cliente. ¿Sin dominio? Basta el subdominio gratuito del VPS, HTTPS incluido.