Continuous integration with Drone

Installing a Drone continuous integration (CI) Ubuntu 14.04 server.

Drone is a continuous integration server with a fully hosted version which you can self-host as well. We gave it a spin for our Rails application: RSpec integration tests with some PhantomJS stuff.


We started off with an Ubuntu 14.04 LTS base image on a 1.6Ghz CPU system with 1GB of RAM and a 10GB drive running on Google Cloud. As always, upgrade the system:

apt update
apt upgrade

See the new apt syntax? Since version 1.0 `apt-get` and `apt-cache` have been merged in a single interface (you even get some nice colours and a progress bar).


Let’s lock the system down a bit by enabling the firewall via UFW.

ufw allow ssh
ufw enable

You can lock yourself out if you are not allowing SSH connections, check to see if you can still log in.

Disable root access

Edit `/etc/ssh/sshd_config` and disable the root login.

PermitRootLogin no

Restart the SSH daemon.

service sshd restart

Automatic updates

Set up automatic updates. This will tell Ubuntu to look for and install security patches every so often, not a luxury as you probably won’t log in to the CI server daily.

dpkg-reconfigure --priority=low unattended-upgrades
Or in a more recent version of Ubuntu:

Make sure the `update-notifier-common` package is installed (it was for me) and edit `/etc/apt/apt.conf.d/50unattended-upgrades` to make the server reboots when it needs to.


Let’s install Docker. Bonus hipster points.

curl -fsSL | sh

A quick hello-world will show if Docker was installed correctly.

docker run hello-world


Drone needs a database to store its things. I went with SQLite as it’s super easy to install but PostgreSQL or MySQL are probably better suited for production systems. Drone doesn’t mind and can run with MySQL, PostgreSQL or SQLite.

apt install sqlite3 libsqlite3-dev

Now you can tell Docker to fetch the latest Drone image (0.4 at the time of writing):

docker pull drone/drone:0.4

Let’s configure Drone:

mkdir /etc/drone
vi /etc/drone/dronerc

Add Github as a remote driver: get the client id and secret from a developer oAuth application created on Github and point it to the database.


Once done you can run Drone:

docker run \
--volume /var/lib/drone:/var/lib/drone \
--volume /var/run/docker.sock:/var/run/docker.sock \
--env-file /etc/drone/dronerc \
--restart=always \
--publish=80:8000 \
--detach=true \
--name=drone \

There you go, open your browser a point it to the server’s IP address. Drone will do its oAuth dance with Github when you log in and list your repositories.


Drone looks for a `.drone.yml` configuration file in your project’s root directory. You start from a Docker image of your choosing, run some commands and wait for Drone to tell you if everything works.

  image: cimm/ruby-phantomjs
    - RAILS_ENV=test
    - bundle install --without production --without staging
    - cp config/database.drone.yml config/database.yml
    - bundle exec rake db:create
    - bundle exec rake db:test:prepare
    - bundle exec rspec spec

    image: postgres

    webhook_url: $$SLACK_WEBHOOK
    channel: general
    username: drone

The first ‘build’ part is the most important one. You can use whatever Docker image you want as a base to start from. We built our own as we need a more recent version of PhantomJS to run our tests.

The ‘commands’ section is where you configure your build and get it running, pretty standard Rails stuff here.

The ‘environment’ section can be used to set… well… environment variables. Useful for twelve-factor apps.

The ‘compose’ section behaves like Docker’s compose feature and lets you pull other Docker images needed for your build. Isn’t that awesome?

And finally, the ‘notify’ section to let everyone know how good of a tester you are.


Noticed the $$SLACK_WEBHOOK variable in the example? It’s possible to pull in variables from a `.drone.sec` file from your project’s root folder. This is useful for API tokens & passwords you rather don’t expose.

Drone knows how to read and decrypt this file but you’ll need to encrypt it yourself. Go to your project’s “Secrets” tab in the Drone web interface and add your variables.

  SLACK_WEBHOOK: https://hooks...

Generate and save the encrypted version in the `.drone.sec` file. Save, commit, push and watch Drone do its magic.