macOS CI on a budget
Have you ever dreamed of having your very own macOS CI? Perhaps a free one would be beyond your wildest imagination. What if I told you that, with a little effort, it is possible?
As a disclaimer, I would like to point out that this is not something you would want to do from a security perspective, as it clearly increases the attack surface of your NAS system. Also, GitHub does not recommend using it for anything other than private projects, as again it may pose some security risks to your internal network.
Although immediately after the launch of GitHub Actions CI/CD was a bit clumsy and lacked many important features, I decided to revisit this service once again. Turns out that the service has since been significantly improved and now fully covers my needs. Another important factor is that it is neatly integrated into the service that I already use, namely GitHub. An unexpected discovery that I made was that you can run your own Actions Runner on your device, which effectively makes this service free of charge for you. Luckily, I had a spare Synology NAS (DSM 6.2.3), so I decided why not use it as a personal build server.
To get started, you will need the aforementioned Synology NAS server with internet access and the
Docker package installed from the official Synology Package Center
. The device does not need to be accessible from the Internet. Since the Runner
initiates the connections itself, the server can be completely hidden behind the firewall. At the time of writing, my NAS had DSM 6.2.3 installed. The Docker folder is assumed to be /volume1/docker/
.
We are going to launch GitHub Actions Runner in a Docker container, as you might have guessed. The tricky part is that this Docker container will launch other containers creating a Docker-in-Docker
chain. Initially, this behaviour is not supported, so we are going to start with this part. In order to make this possible we have to expose the Docker socket to your future CI container.
As a first step, you need to access your NAS via SSH. You can enable it in the Control Panel -> Terminal & SNMP -> Terminal
checking the Enable SSH Service
box. You can now connect to the NAS using the administrator's name and the local IP address of the NAS.
Now we need to give Docker access rights to the socket.
sudo chown -R 1000:1000 /var/run/docker.sock
In order to give your containers access to the socket, we will create a link to the socket inside the volume1/docker
folder so that it can be used as a mounting point later on.
ln -s /var/run/docker.sock /volume1/docker/docker.sock
This link will disappear when NAS restarts. You can use the Control Panel -> Task Scheduler
to create a task that will execute the same linking command after booting the system.
Now let's create a directory for our container.
mkdir -p /volume1/docker/github-runner
This is all you need to do to prepare your NAS. Now let's move on to our actual task of launching GitHub Actions Runner.
The Runner itself is attached to a project or organisation (
which is now free of charge). As the only step at GitHub, you should get your token. You can get it by going to your Organisation/Project Settings -> Actions -> Add New -> New Runner
and copy your token from the Configure
section.
We are finally ready for launch. Let's go back to our SSH terminal and complete the final configuration. We will use
myoung34/github-runner for this. There are several versions, but if you plan to use it with Swift like me, you should stick to Ubuntu 18.04 (myoung34/github-runner:ubuntu-bionic
) or 20.04 (myoung34/github-runner:latest
).
Let's run this container. Please note that I use the same directory for RUNNER_WORKDIR
. This is important so that your "Docker-in-Docker" containers can find your project.
sudo docker run -d --restart always --name github-runner \
-e RUNNER_TOKEN="YOUR TOKEN FROM GITHUB" \
-e RUNNER_WORKDIR="/tmp/github-runner" \
-e RUNNER_ALLOW_RUNASROOT="true" \
-e ORG_RUNNER="true" \
-e ORG_NAME="YOUR ORGANISATION NAME" \
-v /volume1/docker/docker.sock:/var/run/docker.sock \
-v /volume1/docker/github-runner:/tmp/github-runner \
myoung34/github-runner:latest
If you use it with a project instead of an organisation, set ORG_RUNNER
to false and provide your REPO_URL
instead of ORG_NAME
.
You can see your Runner active at GitHub if you navigate to Organisation/Project Settings -> Actions
in the Self-hosted runners
' section. If something went wrong, you can check the Docker logs by opening the Docker app on your NAS, selecting the running container, and going to the logs.
That's all. I hope that with this new feature you can become more productive, save money or at least have a new toy for developers.
Have you ever dreamed of having your very own macOS CI? Perhaps a free one would be beyond your wildest imagination. What if I told you that, with a little effort, it is possible?
Microtask, Future or postFrameCallback, which one should I use?