Setting up Drone CI for CI/CD homelab use - build log
Tags: docker, cicd, buildlog, devops
Published: 2023-10-27 01:16:41

Constantly on the search for something to replace jenkins as my be-all, end-all continuous build/deployment tool, I decided to try setting up a local instance of [`drone`](https://docs.drone.io/server/overview/), as it looked fairly promising. This is a build log of my results. 

## Step 1 - setup and configuration

As with my previous build-log setting up `goCD`, this is going to use docker-compose on portainer. It's where almost all of my home-lab things live at this point, and I haven't really had strong reason to change it. Having said that, I have weird volume configurations, so I'll share simplified versions of those when/if needed.

The [docs](https://docs.drone.io/server/overview/) for `drone` first have you go through the setup process of creating an application on your desired source control platform. I find this to be a little backwards personally, so I'm going to start with the compose file instead and see if I regret it.

The instructions for getting going with docker are pretty simple at first:

```bash
$ docker pull drone/drone:2

```

Which is absolutely nothing to write home about, but that just gets the image. Next up is the listed configuration options, most of which are required. Below is pulled straight from the setup instructions:

- `DRONE_GITHUB_CLIENT_ID`
Required string value provides your GitHub oauth Client ID generated in the previous step.

- `DRONE_GITHUB_CLIENT_SECRET`
Required string value provides your GitHub oauth Client Secret generated in the previous step.

- `DRONE_RPC_SECRET`
Required string value provides the shared secret generated in the previous step. This is used to authenticate the rpc connection between the server and runners. The server and runner must be provided the same secret value.

- `DRONE_SERVER_HOST`
Required string value provides your external hostname or IP address. If using an IP address you may include the port. For example drone.company.com.

- `DRONE_SERVER_PROTO`
Required string value provides your external protocol scheme. This value should be set to http or https. This field defaults to https if you configure ssl or acme. This value should be set to https if you deploy Drone behind a load balancer or reverse proxy with SSL termination.

- `DRONE_USER_FILTER`
Optional comma-separated list of GitHub users or organizations. Registration is limited to users in this list, or users that are members of organizations in this list. Registration is open to the public if this value is unset.

Given some of these values, it is easy to see why they want you to configure an application first, as you'll need those values. Oh well, [off to github I go to get credentials](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app).

Once I had those, I could put together the start of my compose file

```yaml=
version: "3.7"
services:
  drone:
    image: drone/drone:2
    environment:
      - DRONE_GITHUB_CLIENT_ID=super-secret-github-id
      - DRONE_GITHUB_CLIENT_SECRET=super-secret-github
      - DRONE_RPC_SECRET=super-shared-secret
      - DRONE_SERVER_HOST=drone.my-domain.local
      - DRONE_SERVER_PROTO=https
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/lib/drone:/data
    restart: unless-stopped
```

I've filled in a couple values here with example data for security reasons, but details do need to match what you got from github, except for the `DRONE_RPC_SECRET`. This is going to be a shared key between our main instance, and our runners, more on that later I think. You can use any random string, or use openssl to generate one:

```bash=
$ openssl rand -hex 16
```

A final note about that above compose. The ports will be different, or may need to be. Changing the _left_ side changes what is exposed on your machine, and you can set that to whatever you like, so long as you have a way of directing your domain to it. Nginx-proxy-manager is great for this.

This is, in theory, enough to spin the server up. So let's do that and see what we get.

## Step 2 - First user setup

This landed me at the login page, which prompted a quick authorization from github, follwed by, a user login prompt again? Seems strange, but filling in the details and following the prompts worked flawlessly, so I won't question it. 

This landed me on a screen with all the repositories I had granted access to this application, which was pretty neat to see. Clicking on any of them displayed another screen mentioning how this repository is not active, which makes sense, and is exciting, but now we are getting ahead of ourselves. We need to setup a runner.

## Step 3 - Drone runner node

We can add this to our existing docker compose file, directly below the main instance. This was also pretty short and simple.
```yaml=
drone-runner-1:
    image: drone/drone-runner-docker:1
    container_name: drone-runner-1
    environment:
      - DRONE_RUNNER_CAPACITY=4
      - DRONE_RUNNER_NAME=docker-runner
      - DRONE_RPC_SECRET=super-shared-secret
      - DRONE_RPC_HOST=drone.my-domain.local
      - DRONE_RPC_PROTO=https
    ports:
      - "3331:3000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped

```

I added this to my existing compose, and the instructions say to check the logs for the following:

```bash
$ docker logs runner

INFO[0000] starting the server
INFO[0000] successfully pinged the remote server 
```

I had that, so it seemed to be working.

## Step 4 - Test an actual pipeline

I seemed to be done with server setup, which shocked me, as that was really easy compared to some other options. Next up I needed to actually push a build-pipeline to a repo, and see if it would take.

I found the repo I wanted, and clicked on the "activate" button from the web ui in drone. 

The example pipeline they gave seemed like I good start, so I went with that:
```yaml=
#.drone.yml
kind: pipeline
type: docker
name: default

steps:
- name: greeting
  image: alpine
  commands:
  - echo hello
  - echo world
```

While I don't super love yaml for all the configuration, the naming and matter that the steps and commands were setup seemed pretty straight forward to me, which was nice. 

I added those changes to `.drone.yml` in my repo and pushed it up. 

This, produced a very nice result, as my push got a little green check-mark in github, and clicking on that "build passing" took me directly to drone where the job had run with a list of the steps, and a console log of the output. It was beautiful, and simple.

## Conclusion

So far, I really, really like using drone. I'm still very new to it, and getting the hang of the build steps and configuration will take time, but getting the initial setup took no time at all, and produced amazing results. Stay tuned for more, thanks for reading.