Documentation for my home lab CI/CD setup
192.168.1.122 (STATIC)192.168.1.125 (ENLIL)2a00:23c7:593:6501:ba27:ebff:fe0f:e3f2 (ENLIL)LORIC acts as the dedicated orchestrator node within the home-lab CI/CD infrastructure. It is responsible for polling the Gitea server on CASPER, orchestrating workflow execution, and dispatching jobs to worker nodes like AUREL while maintaining workflow scheduling and coordination. It is also capable of handling building and running docker related tasks however those are offloaded to AUREL.
pi3, armv7 (used only to select which workflows this runner can accept).LORIC was setup using the following steps and instructions:
We will use the following command to set a static IPv4 on our device and ensure that IPv4 and IPv6 dns are set correctly.
auzlex@LORIC:~ $ sudo nmcli connection modify "target connection" \
ipv4.addresses 192.168.1.122/24 \
ipv4.gateway 192.168.1.254 \
ipv4.dns 192.168.1.125 \
ipv4.ignore-auto-dns yes \
ipv4.method manual \
ipv6.dns 2a00:23c7:593:6501:ba27:ebff:fe0f:e3f2 \
ipv6.ignore-auto-dns yes \
ipv6.method auto
We then apply changes by rebooting
auzlex@LORIC:~ $ sudo reboot
verify
auzlex@LORIC:~ $ nmcli
auzlex@LORIC:~ $ sudo apt update && sudo apt install -y docker.io docker-compose && sudo systemctl enable docker --now
auzlex@LORIC:~ $ mkdir ~/gitea-runner && cd ~/gitea-runner
auzlex@LORIC:~/gitea-runner $ curl -LO https://dl.gitea.com/act_runner/0.2.13/act_runner-0.2.13-linux-arm-7.xz
auzlex@LORIC:~/gitea-runner $ unxz act_runner-0.2.13-linux-arm-7.xz
auzlex@LORIC:~/gitea-runner $ mv act_runner-0.2.13-linux-arm-7 act_runner
auzlex@LORIC:~/gitea-runner $ chmod +x act_runner
auzlex@LORIC:~/gitea-runner $ ./act_runner register --instance http://192.168.1.124:8083 --token <TOKEN> --name loric-runner --labels pi3,armv7 --no-interactive
<TOKEN>: token obtained from CASPER.--labels can be customized for workflow targeting.auzlex@LORIC:~/gitea-runner $ ./act_runner daemon
Create service file:
auzlex@LORIC:~ $ sudo nano /etc/systemd/system/gitea-runner.service
Paste:
[Unit]
Description=Gitea Actions Runner
After=network.target
[Service]
Type=simple
User=auzlex
WorkingDirectory=/home/auzlex/gitea-runner
ExecStart=/home/auzlex/gitea-runner/act_runner daemon
Restart=always
[Install]
WantedBy=multi-user.target
Enable and start the service:
auzlex@LORIC:~ $ sudo systemctl daemon-reload
auzlex@LORIC:~ $ sudo systemctl enable gitea-runner
auzlex@LORIC:~ $ sudo systemctl start gitea-runner
Check status:
auzlex@LORIC:~ $ sudo systemctl status gitea-runner
We will test running a task on LORIC to echo "Hello from AUREL!"
An SSH has also been setup between AUREL and LORIC so that LORIC can issue commands to the isolated user account called CI, at the moment we can manually configure out Gitea workflow runner to issue commands carefully.
In the example image above, you can see the worker is successfully running my gitea workflow test.yml within my CICD-Test repo. The test.yml is to instruct commands under the ssh.
name: Test Worker Connectivity
on:
push:
branches:
- main
jobs:
ping-worker:
runs-on: pi3 # label matches LORIC and AUREL worker
steps:
- name: Echo from Worker
run: ssh ci@192.168.1.123 'echo "Hello from AUREL!"'
These commands will setup docker context for LORIC. LORIC also has docker installed and running which can perform builds and other tasks, however their role is to simply only handle requests from CASPER and tell other devices within my setup to do more of the heavy lifting.
When a workflow runs:
If the runner is busy:
We use this command below to ensure what types of context is available.
docker context ls
NAME DESCRIPTION DOCKER ENDPOINT ERROR
aurel * ssh://ci@192.168.1.123
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
Docker contexts can be created with the following command:
docker context create aurel \
--docker "host=ssh://ci@192.168.1.123"
Next we tell LORIC to use AUREL for docker usage.
docker context use aurel
After this:
docker build runs on AUREL.docker run runs on AUREL.~/gitea-runner/act_runner.