Drone es una plataforma de integración continua ligera en la que cada paso de un pipeline se ejecuta dentro de un contenedor Docker. Se compone de un servidor, que recibe los webhooks del proveedor Git y muestra la interfaz web, y de uno o varios runners, que ejecutan los pipelines. En este tutorial instalarás el servidor de Drone y el runner de Docker con Docker Compose en Ubuntu 24.04, lo publicarás con Nginx y HTTPS, lo conectarás a GitHub y ejecutarás un pipeline definido en .drone.yml.
Requisitos previos
Para seguir esta guía necesitas:
- Un servidor con Ubuntu 24.04 LTS con al menos 2 vCPU y 4 GB de RAM, por ejemplo un VPS de CubePath, y un usuario no root con privilegios
sudo. - Docker Engine y el plugin de Docker Compose instalados desde el repositorio oficial de Docker.
- Un dominio o subdominio, como
drone.your_domain, con un registro DNS A que apunte a la IP pública del servidor. - Una cuenta de GitHub con acceso a los repositorios que quieres integrar.
Sustituye drone.your_domain por tu subdominio y your_github_user por tu usuario de GitHub en todos los comandos y archivos.
NotaDrone lo mantiene Harness, que ha integrado su evolución en Harness Open Source. Drone 2 sigue publicándose como imagen
drone/drone:2y es una opción válida para un CI autoalojado sencillo.
Paso 1: Crear la aplicación OAuth en GitHub
Drone no tiene usuarios propios: los usuarios inician sesión con su cuenta de GitHub mediante OAuth, y Drone usa ese acceso para leer los repositorios y crear los webhooks.
En GitHub, ve a Settings > Developer settings > OAuth Apps > New OAuth App y rellena el formulario:
| Campo | Valor |
|---|---|
| Application name | Drone |
| Homepage URL | https://drone.your_domain |
| Authorization callback URL | https://drone.your_domain/login |
Pulsa Register application. En la página de la aplicación copia el Client ID y pulsa Generate a new client secret para obtener el Client secret. Guarda ambos valores: los usarás en el paso 2.
Paso 2: Preparar la configuración de Drone
Crea un directorio para el proyecto de Docker Compose:
sudo mkdir -p /opt/drone
cd /opt/drone
El servidor y el runner se autentican entre sí con un secreto compartido. Genéralo con openssl:
openssl rand -hex 16
3f9c1e7a2b8d4c6e0f1a2b3c4d5e6f70
Crea el archivo .env que leerá Docker Compose:
sudo nano /opt/drone/.env
Añade las variables con tus valores:
DRONE_SERVER_HOST=drone.your_domain
DRONE_GITHUB_CLIENT_ID=your_client_id
DRONE_GITHUB_CLIENT_SECRET=your_client_secret
DRONE_RPC_SECRET=3f9c1e7a2b8d4c6e0f1a2b3c4d5e6f70
DRONE_ADMIN_USER=your_github_user
Este archivo contiene secretos, así que restringe sus permisos:
sudo chmod 600 /opt/drone/.env
Paso 3: Definir el servidor y el runner con Docker Compose
Crea el archivo de Compose:
sudo nano /opt/drone/compose.yaml
Añade este contenido:
services:
drone-server:
image: drone/drone:2
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- drone-data:/data
environment:
DRONE_GITHUB_CLIENT_ID: ${DRONE_GITHUB_CLIENT_ID}
DRONE_GITHUB_CLIENT_SECRET: ${DRONE_GITHUB_CLIENT_SECRET}
DRONE_RPC_SECRET: ${DRONE_RPC_SECRET}
DRONE_SERVER_HOST: ${DRONE_SERVER_HOST}
DRONE_SERVER_PROTO: https
DRONE_USER_CREATE: username:${DRONE_ADMIN_USER},admin:true
DRONE_USER_FILTER: ${DRONE_ADMIN_USER}
drone-runner:
image: drone/drone-runner-docker:1
restart: unless-stopped
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
DRONE_RPC_PROTO: http
DRONE_RPC_HOST: drone-server
DRONE_RPC_SECRET: ${DRONE_RPC_SECRET}
DRONE_RUNNER_CAPACITY: 2
DRONE_RUNNER_NAME: runner-1
volumes:
drone-data:
Puntos importantes de esta configuración:
- El servidor escucha solo en
127.0.0.1:8080. El acceso desde Internet pasará por Nginx con HTTPS, que configurarás en el paso 5. DRONE_USER_CREATEconvierte tu usuario de GitHub en administrador en el primer arranque.DRONE_USER_FILTERlimita quién puede iniciar sesión. Sin él, cualquier persona con cuenta de GitHub podría registrarse y ejecutar código en tu runner. Puedes indicar varios usuarios u organizaciones separados por comas, por ejemployour_github_user,your_org.- El runner se conecta al servidor por la red interna de Compose (
drone-server), sin salir a Internet. DRONE_RUNNER_CAPACITYfija cuántos pipelines se ejecutan a la vez.- Los datos (base de datos SQLite, usuarios, repositorios, secretos) se guardan en el volumen
drone-data.
Advertenciael runner monta el socket de Docker, lo que equivale a acceso root al servidor. Activa en Drone solo repositorios de confianza y no aceptes pipelines de forks sin revisarlos.
Paso 4: Arrancar Drone
Inicia los contenedores en segundo plano:
cd /opt/drone
sudo docker compose up -d
Comprueba que ambos servicios están en ejecución:
sudo docker compose ps
Los servicios drone-server y drone-runner deben aparecer con el estado Up, y el servidor con el puerto 127.0.0.1:8080->80/tcp.
Revisa los registros del runner para confirmar que se ha conectado al servidor:
sudo docker compose logs drone-runner
drone-runner-1 | time="2026-09-24T10:20:31Z" level=info msg="successfully pinged the remote server"
drone-runner-1 | time="2026-09-24T10:20:31Z" level=info msg="polling the remote server"
Si en lugar de esto ves errores de autenticación, el valor de DRONE_RPC_SECRET no llega igual a los dos contenedores. Revisa el archivo .env.
Paso 5: Publicar Drone con Nginx y HTTPS
GitHub necesita alcanzar Drone por HTTPS para completar el inicio de sesión y enviar los webhooks. Instala Nginx y Certbot:
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx
Crea el bloque de servidor para Drone:
sudo nano /etc/nginx/sites-available/drone
Añade esta configuración:
server {
listen 80;
listen [::]:80;
server_name drone.your_domain;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
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 Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
}
}
proxy_buffering off y el tiempo de espera largo permiten que los registros de las ejecuciones lleguen en tiempo real al navegador. Activa el sitio y comprueba la sintaxis:
sudo ln -s /etc/nginx/sites-available/drone /etc/nginx/sites-enabled/
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Recarga Nginx y abre los puertos HTTP y HTTPS en UFW si el cortafuegos está activo:
sudo systemctl reload nginx
sudo ufw allow 'Nginx Full'
Solicita el certificado de Let's Encrypt. Certbot modificará el bloque de servidor para añadir HTTPS y la redirección desde HTTP:
sudo certbot --nginx -d drone.your_domain
Comprueba que Drone responde por HTTPS:
curl -sI https://drone.your_domain
HTTP/2 200
server: nginx/1.24.0 (Ubuntu)
content-type: text/html; charset=UTF-8
Paso 6: Iniciar sesión y activar un repositorio
Abre https://drone.your_domain en el navegador y pulsa Continue. GitHub te pedirá autorizar la aplicación OAuth que creaste en el paso 1; acepta y volverás a Drone, que sincronizará la lista de tus repositorios.
Elige el repositorio que quieres integrar y pulsa Activate Repository. Drone creará automáticamente un webhook en GitHub. Puedes comprobarlo en el repositorio de GitHub, en Settings > Webhooks: debe aparecer una entrada que apunta a https://drone.your_domain/hook con una marca de entrega correcta.
Paso 7: Crear el primer pipeline
Drone lee la definición del pipeline del archivo .drone.yml en la raíz del repositorio. Este ejemplo, para un proyecto Node.js, instala las dependencias y ejecuta las pruebas en cada push y pull request:
kind: pipeline
type: docker
name: default
steps:
- name: test
image: node:22
commands:
- npm ci
- npm test
trigger:
event:
- push
- pull_request
Cada paso se ejecuta en un contenedor creado a partir de image, con el código del repositorio montado como directorio de trabajo. Los pasos comparten ese directorio, así que lo que genera un paso (por ejemplo node_modules o una carpeta dist/) está disponible para los siguientes.
Confirma el archivo y súbelo:
git add .drone.yml
git commit -m "Add Drone pipeline"
git push
En la interfaz de Drone aparecerá una nueva ejecución con el paso clone (que Drone añade automáticamente) y el paso test. Pulsa sobre cada paso para ver su salida. Un paso que termina con código distinto de cero marca la ejecución como fallida y detiene los pasos siguientes.
Paso 8: Usar secretos y plugins
Los plugins de Drone son imágenes Docker que reciben su configuración mediante settings. Un caso habitual es construir una imagen y publicarla en Docker Hub con el plugin plugins/docker. Las credenciales no deben estar en el repositorio, así que se guardan como secretos de Drone.
En la interfaz, abre el repositorio, ve a Settings > Secrets y crea dos secretos: docker_username con tu usuario de Docker Hub y docker_password con un token de acceso de Docker Hub.
Añade un segundo paso al .drone.yml:
kind: pipeline
type: docker
name: default
steps:
- name: test
image: node:22
commands:
- npm ci
- npm test
- name: publish
image: plugins/docker
settings:
repo: your_dockerhub_user/myapp
tags:
- latest
- ${DRONE_COMMIT_SHA:0:8}
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
branch:
- main
event:
- push
trigger:
event:
- push
- pull_request
from_secret inyecta el valor del secreto sin mostrarlo en los registros, y la sección when hace que la imagen solo se publique en los push a main, no en las pull requests. Drone ejecuta plugins/docker en modo privilegiado de forma automática porque está en su lista de plugins de confianza.
Notapor defecto, Drone no expone los secretos a las pull requests que vienen de forks. Mantén ese comportamiento para que nadie pueda leer tus credenciales abriendo una pull request.
Gestionar secretos con la CLI de Drone
También puedes gestionar secretos y ejecuciones desde la terminal. Descarga la CLI:
curl -fsSL https://github.com/harness/drone-cli/releases/latest/download/drone_linux_amd64.tar.gz | tar zx
sudo install -t /usr/local/bin drone
Copia tu token personal desde la página de tu cuenta en la interfaz de Drone (menú de usuario, User settings) y exporta las variables:
export DRONE_SERVER=https://drone.your_domain
export DRONE_TOKEN=your_drone_token
Comprueba la conexión y crea un secreto:
drone info
drone secret add --repository your_github_user/myapp --name docker_username --data your_dockerhub_user
Paso 9: Hacer copias de seguridad
Todo el estado de Drone está en el volumen drone-data, que Compose crea con el prefijo del proyecto (drone_drone-data). Para una copia consistente de la base de datos SQLite, detén el servidor un momento, guarda el volumen y vuelve a arrancarlo:
cd /opt/drone
sudo docker compose stop drone-server
sudo docker run --rm -v drone_drone-data:/data:ro -v /opt/drone:/backup alpine \
tar czf /backup/drone-data-$(date +%F).tar.gz -C /data .
sudo docker compose start drone-server
Comprueba que el archivo se ha creado:
ls -lh /opt/drone/drone-data-*.tar.gz
Guarda también el archivo .env: sin el mismo DRONE_RPC_SECRET y las credenciales OAuth tendrías que volver a configurar el runner y la aplicación de GitHub.
Solución de problemas
GitHub muestra The redirect_uri is not associated with this application: la Authorization callback URL de la aplicación OAuth no coincide con https://drone.your_domain/login, o DRONE_SERVER_PROTO y DRONE_SERVER_HOST no reflejan la URL pública. Corrige el valor y ejecuta sudo docker compose up -d para recrear el servidor.
Las ejecuciones se quedan en estado pendiente: el runner no está conectado. Revisa sudo docker compose logs drone-runner y comprueba que el DRONE_RPC_SECRET es el mismo en ambos servicios.
No puedes iniciar sesión aunque GitHub autoriza la aplicación: tu usuario u organización no está en DRONE_USER_FILTER. Añádelo y recrea el servidor.
Los push no lanzan ejecuciones: revisa en GitHub, en Settings > Webhooks, la última entrega del webhook de Drone. Un error de conexión suele indicar que el certificado no es válido o que el puerto 443 está cerrado.
Conclusión
Tienes Drone CI funcionando en Ubuntu 24.04 detrás de Nginx con HTTPS, conectado a GitHub, con un runner de Docker que ejecuta los pipelines definidos en .drone.yml y secretos guardados fuera del repositorio. Como siguientes pasos puedes añadir más runners en otros servidores apuntando al mismo DRONE_RPC_HOST, pasar la base de datos a PostgreSQL si el uso crece, o añadir un paso de despliegue que se conecte por SSH a tus servidores.