Drone CI is an open-source, container-native continuous integration and delivery platform that runs every pipeline step inside an isolated Docker container. It integrates natively with GitHub, Gitea, GitLab, and Bitbucket, making it a lightweight alternative to Jenkins for teams already working with containers. Drone’s configuration lives in a .drone.yml file committed alongside your code, keeping CI/CD logic version-controlled and auditable. This guide walks through installing and configuring Drone CI on RHEL 9 using Docker, connecting it to a GitHub repository, and running your first automated pipeline.
Prerequisites
- RHEL 9 server with at least 2 CPU cores and 2 GB RAM
- Docker and Docker Compose installed and running (
systemctl enable --now docker) - A registered GitHub OAuth application (Settings → Developer settings → OAuth Apps) with the callback URL set to
http://YOUR_SERVER_IP/login - Ports 80 and 443 reachable from the internet (or from your internal network)
- A domain name or static IP for the Drone server
Step 1 — Install Docker on RHEL 9
# Add the Docker CE repository
dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
# Install Docker Engine
dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Start and enable Docker
systemctl enable --now docker
# Verify the installation
docker version
Step 2 — Open Firewall Ports
# Allow HTTP and HTTPS through firewalld
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
# Confirm the rules are active
firewall-cmd --list-services
Step 3 — Generate a Shared RPC Secret
# Generate a cryptographically random secret used by server and runner
openssl rand -hex 16
# Example output: 8f2d4a7b9c1e3f05a6b8d2e4f7c9a1b3
# Save this value — you will use it as DRONE_RPC_SECRET below
Step 4 — Run the Drone Server Container
# Replace all placeholder values with your real credentials
docker run
--detach
--restart=always
--volume=/var/lib/drone:/data
--publish=80:80
--publish=443:443
--env=DRONE_GITHUB_CLIENT_ID=YOUR_GITHUB_CLIENT_ID
--env=DRONE_GITHUB_CLIENT_SECRET=YOUR_GITHUB_CLIENT_SECRET
--env=DRONE_RPC_SECRET=8f2d4a7b9c1e3f05a6b8d2e4f7c9a1b3
--env=DRONE_SERVER_HOST=drone.example.com
--env=DRONE_SERVER_PROTO=http
--env=DRONE_TLS_AUTOCERT=false
--env=DRONE_LOGS_PRETTY=true
--name=drone
drone/drone:2
# Verify the container is running
docker ps | grep drone
Step 5 — Run the Drone Docker Runner
# The runner polls the server for pending pipelines and executes them
docker run
--detach
--restart=always
--volume=/var/run/docker.sock:/var/run/docker.sock
--env=DRONE_RPC_PROTO=http
--env=DRONE_RPC_HOST=drone.example.com
--env=DRONE_RPC_SECRET=8f2d4a7b9c1e3f05a6b8d2e4f7c9a1b3
--env=DRONE_RUNNER_CAPACITY=2
--env=DRONE_RUNNER_NAME=rhel9-runner
--name=runner
drone/drone-runner-docker:1
# Confirm the runner connected successfully
docker logs runner 2>&1 | grep "successfully pinged"
Step 6 — Create a .drone.yml Pipeline File
# Commit this file to the root of your repository as .drone.yml
kind: pipeline
type: docker
name: default
steps:
- name: install-deps
image: node:20-alpine
commands:
- npm ci
- name: test
image: node:20-alpine
commands:
- npm test
- name: build
image: node:20-alpine
commands:
- npm run build
when:
branch:
- main
services:
- name: database
image: postgres:15
environment:
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
trigger:
event:
- push
- pull_request
Conclusion
You now have a fully functional Drone CI installation on RHEL 9. The Drone Server handles authentication and pipeline orchestration while the Docker Runner executes each pipeline step in an isolated container, keeping build environments clean and reproducible. The .drone.yml file committed to your repository ensures that pipeline changes go through the same code review process as application code. For production use, enable TLS by setting DRONE_TLS_AUTOCERT=true and pointing your domain’s DNS at the server, store secrets in Drone’s encrypted secret store rather than committing them to YAML, and consider running multiple runners across different hosts to handle parallel workloads.
Next steps: How to Install Jenkins on RHEL 9, How to Build and Push Docker Images in CI/CD Pipelines on RHEL 9, and How to Set Up a Local Container Registry with Harbor on RHEL 9.