Deploying a runner in a jail is a little bit involved, as it does involve some manual work the first time you deploy.
While I use Bastille to manage my jails, I have tried to provide some suggestions what you might do if you manage your jails manually too.
The following are needed to be added where necessary to the Bastillefile (note I build my jails for idempotency):
OVERLAY var
OVERLAY usr
# Below needed as we copy the registration data once created into the right
# place in the jail
CMD chown -R act_runner:act_runner /var/db/act_runner
PKG doas forgejo-act_runner
SYSRC act_runner_enable=YES
SERVICE act_runner restart
act_runner runs as user act_runner, which is why I bring doas into the jail. You can always use your preferred elevation tool!
An example doas.conf for this where I want the runner to make changes to files owned by the www user:
permit nopass act_runner as www
I deploy my act_runner.conf from my Bastille template, so copy the act_runner.conf.sample which is now in the jail to <template>/usr/local/etc/act_runner.conf.
The only change I needed to make was to the labels:. The only label I needed to set up was as follows:
labels: ["<jailname>:host"]
Either redeploy the template, or do the same inside the jail.
Deploy your changes to the jail (in my case that means reappling the Bastille template) and get a root console in the jail.
Since the act_runner account is set to /usr/sbin/nologin and we only need to register this once, I do this as the root user in the jail, which does not put the file in the right place, but that's fine for me as I will deploy the file as part of the Bastille template.
You need to generate a runner token from forgejo. You can do this site wide (in the site settings), organisation wide (in the organisation settings), or repo only (in the repo settings). In my case I did it organisation-wide as this client has multiple repos that we may want to automate. Organisation -> Settings -> Actions -> Runners -> Create new runner and copy the Registration token.
act_runner register
INFO Registering runner, arch=amd64, os=freebsd, version=12.5.0.
INFO Enter the Forgejo instance URL (for example, https://next.forgejo.org/):
# Enter your forgejo instance here (and make sure it can be reached from the jail)
INFO Enter the runner token:
# Enter the runner token you copied above here
INFO Enter the runner name (if set empty, use hostname: web-themrc):
# I used the jail name for this
INFO Enter the runner labels, leave blank to use the default labels (comma-separated, for example, ubuntu-20.04:docker://node:20-bookworm,ubuntu-18.04:docker://node:20-bookworm):
# Use the label you created in act_runner.conf
INFO Registering runner, name=jailname, instance=https://forgejo.tld/, labels=[jailname:host].
DEBU Successfully pinged the Forgejo instance server
INFO Runner registered successfully.
This generates a file called .runner in your current directory. Copy this into your template var/db/act_runner/ folder if you're using Bastille, or into /var/db/act_runner/ to make it work in this jail without a Bastille deployment. Make sure it is owned by act_runner:act_runner.
If you're using Bastille, re-apply the template and the runner should now be visible in forgejo.
If you're managing the jail manually then (re)start the act_runner service and it should now be visible in forgejo.
In your repo, create a folder called .forgejo/workflows and create a yaml file, call it whatever you want to be visible in forgejo. Mine is push_to_env.yaml. You can have as many of these as you want
The Forgejo Action reference docs are helpful for this, and include some useful examples for each function. Here is my runner (with some items redacted), which allows the users to deploy to Staging, optionally nominating a branch name, and deploy to Production with no branch choice. It also does some checks to report on the success of the deployments:
on:
workflow_dispatch:
inputs:
environment:
description: 'Environment'
required: true
default: 'Staging'
type: choice
options:
- Staging
- Production
branch:
description: 'Deploy branch name (Staging only)'
required: true
default: 'main'
type: string
jobs:
staging:
name: Deploy latest changes to Staging and switch branch
if: inputs.environment == 'Staging'
runs-on: web-themrc
steps:
- name: Display deployment info
run: echo "Deploying to ${{ inputs.environment }} and switching branch to ${{ inputs.branch }}"
- name: Switch branch and pull latest changes
run: doas -u www sh -c "cd /folder/for/staging; git fetch origin && git switch ${{ inputs.branch }} && git pull origin ${{ inputs.branch }}"
- name: Show git status
run: doas -u www sh -c "cd /folder/for/staging; git status"
- name: Show last commit
run: doas -u www sh -c "cd /folder/for/staging; git log -1 --oneline"
- name: List modified files of last commit
run: doas -u www sh -c "cd /folder/for/staging; git diff --name-only HEAD~1 HEAD"
production:
name: Deploy latest changes in master to Production
if: inputs.environment == 'Production'
runs-on: web-themrc
steps:
- name: Deploy latest changes in master to Production
run: doas -u www sh -c "cd /folder/for/production; git pull origin main"
- name: Show git status
run: doas -u www sh -c "cd /folder/for/production; git status"
- name: Show last commit
run: doas -u www sh -c "cd /folder/for/production; git log -1 --oneline"
- name: List modified files of last commit
run: doas -u www sh -c "cd /folder/for/production; git diff --name-only HEAD~1 HEAD"
Commit these changes to the repo, and now in that repo there is an Actions item added to the functions across the top, and the file that you created should be visible in the "All workflows" box on the left.
Click on the file, and a blue bar will appear offering you a drop down to provide the needed input (I think if there is no input required then it will just run at this point).
Provide the input needed, and click the Run workflow button.