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.

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:

CampoValor
Application nameDrone
Homepage URLhttps://drone.your_domain
Authorization callback URLhttps://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_CREATE convierte tu usuario de GitHub en administrador en el primer arranque.
  • DRONE_USER_FILTER limita 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 ejemplo your_github_user,your_org.
  • El runner se conecta al servidor por la red interna de Compose (drone-server), sin salir a Internet.
  • DRONE_RUNNER_CAPACITY fija cuántos pipelines se ejecutan a la vez.
  • Los datos (base de datos SQLite, usuarios, repositorios, secretos) se guardan en el volumen drone-data.

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.

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.