Self-Hosted Gitea and Drone
Published: 2022-09-11This page is about setting up Gitea with Drone as a CI server.
Getting Started
To get started, ensure that you can SSH into a server and make a new directory called gitea
. We'll place three files in this directory, namely:
setup.sh
,docker-compose.yml
, andDRONE_GITEA_CLIENT_SECRET.env
.
Let's start at the beginning and write the following to setup.sh
:
set -e
mkdir -p /data/gitea
mkdir -p /data/gitea_config
mkdir -p /data/gitea_db
chown -R 1000:1000 /data/gitea*
chmod 775 /data/gitea*
chmod g+s /data/gitea*
mkdir -p /data/drone
chown -R 1001:1001 /data/drone
chmod 775 /data/drone
chmod g+s /data/drone
touch DRONE_GITEA_CLIENT_SECRET.env
chmod 600 DRONE_GITEA_CLIENT_SECRET.env
After creating the script, run it with:
$ sh setup.sh
This script is idempotent, so you can run it as often as you like.
The aim is to put everything in the right place for Docker Compose. This "putting in the right place" improves security. As is visible in the script, the gitea
folders get a 1000:1000 UID and GUID. The drone
folder gets a 1001:1001 UID and GUID. This allows running the gitea
and drone
containers as non-root which, in turn, makes it harder for attackers to gain root access and read our secret files such as DRONE_GITEA_CLIENT_SECRET.env
! Thanks to Docker volumes and file system permissions for the chmod
tips.
Gitea
To enable SSH, setup A
(IPv4) and AAAA
(IPv6) records in your domains DNS settings for git
and drone
. Point both to your server IP. Once you are sure that your DNS records for git.example.com
and drone.example.com
propagated, you can add the domains to your reverse proxy. (These sentences will certainly score you points at a LAN party.)
Specifically, if you use Caddy, then add:
git.example.com {
reverse_proxy 127.0.0.1:3000
}
drone.example.com {
reverse_proxy 127.0.0.1:444
}
Caddy will automatically setup HTTPS.
Next, the following docker-compose.yml
will give you a working Gitea instance:
version: '3'
services:
gitea:
image: 'gitea/gitea:1.21.1-rootless'
container_name: 'gitea'
ports:
- '3000:3000'
volumes:
- '/data/gitea:/data:rw'
- '/data/gitea_db:/var/lib/gitea:rw'
- '/data/gitea_config:/etc/gitea:rw'
user: '1000:1000'
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "10"
environment:
USER_UID: '1000'
USER_GID: '1000'
APP_NAME: 'git'
DEFAULT_UI_LOCATION: 'europe/amsterdam'
DISABLE_REGISTRATION: 'true'
DISABLE_SSH: 'true'
DOMAIN: 'git.example.com'
ENABLE_OPENID_SIGNIN: 'false'
INSTALL_LOCK: 'true'
LOCAL_ROOT_URL: 'http://localhost:3000/'
OFFLINE_MODE: 'true'
ROOT_URL: 'https://git.example.com'
restart: 'unless-stopped'
Run it via:
$ docker compose up
and check for errors in the printed output. If that looks good, test that you can access Gitea at https://git.example.com
.
Once the server is running and is accessible via the web, hit CTRL + C
and start the service as a background job:
$ docker compose up -d
Now setup an admin user by stepping into the container:
$ docker exec -it gitea sh
Verify that you're inside the container by testing that Gitea is installed:
/var/lib/gitea $ gitea --version
If that works, you can create an admin user:
/var/lib/gitea $ gitea admin user create --username=<username> --password=<password> --email=<email>
Finally, don't forget to verify the installation by setting up a test repository and shutting down the server (power cycle). After about 30 seconds, your Gitea instance should be running again and show your test repository.
CI
As a CI server, we'll use Drone here since it looked mature and easy to setup.
To set it up, go into the Gitea web interface and add a OAuth2 application to your account (https://git.example.com/user/settings/applications) with some Application Name and https://drone.example.com/login
as the Redirect URI.
After that, add the following Drone config including the Client ID and Client Secret that Gitea provided to the existing docker-compose.yml
:
version: '3'
services:
drone:
image: 'drone/drone:2.12'
container_name: 'drone'
ports:
- '444:444'
volumes:
- '/data/drone:/data:rw'
user: '1001:1001'
environment:
DRONE_GITEA_SERVER: 'https://git.example.com'
DRONE_GITEA_CLIENT_ID: '<client id>'
DRONE_RPC_SECRET: '<rpc secret>'
DRONE_SERVER_HOST: 'drone.example.com'
DRONE_SERVER_PORT: ':444'
DRONE_SERVER_PROTO: 'https'
DRONE_LOGS_DEBUG: 'false'
DRONE_USER_CREATE: 'username:<gitea admin username>,admin:true'
DRONE_TLS_AUTOCERT: 'false'
env_file:
- 'DRONE_GITEA_CLIENT_SECRET.env'
restart: 'unless-stopped'
To connect Drone to Gitea, restart the services:
$ docker compose down
and
$ docker compose up
Then, make sure that drone is running at a domain that you've set up (https://drone.example.com
).
Go to https://drone.example.com/
, click on login, and authorize Drone to Gitea. Once you've verified that Drone can see your Gitea repositories, restart the server and check that things still work.
Drone Runner
Finally, we can setup a Drone Runner 🏃️️. This should be the easiest step. No domain settings are required, just a system connected to the internet. It can even be the system that you're working on because you probably only need CI when you are working 💭. Otherwise, a small server for a few bucks per month should be fine too for most use-cases. On the Runner system of your chosing, setup something along the following lines:
version: '3'
services:
drone_runner:
image: 'drone/drone-runner-docker:1'
container_name: 'drone_runner'
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
environment:
DRONE_RPC_PROTO: 'https'
DRONE_SERVER_PROTO: 'http'
DRONE_SERVER_TOKEN: '<server token; see the Drone interface>'
DRONE_RPC_HOST: 'drone.example.com'
DRONE_RUNNER_CAPACITY: '2'
DRONE_RUNNER_NAME: '<a nice name like I donno "Red Lightning">'
env_file:
- 'DRONE_RPC_SECRET.env'
restart: 'unless-stopped'
See the Drone documentation for more information.
That's it, you should now have a working Gitea and Drone server! 🚀