Run #4266 dropped the /root/.docker bind silently: Custom container.HostConfig from options ==> &{Binds:[/root/.docker:/root/.docker:ro]…} [/root/.docker] is not a valid volume, will be ignored Merged container.HostConfig ==> &{Binds:[/var/run/docker.sock:/var/run/docker.sock /root/.docker:/root/.docker:ro]…} no basic auth credentials Wait, the merged binds list does include /root/.docker — but the line between them, "[/root/.docker] is not a valid volume, will be ignored", fires *during* the merge step's allowlist check, and the bind ends up absent in the actual container start (the `Binds:` list shown is pre-filter). Net result: the registry creds are not in the job container, push fails. Root cause: container.valid_volumes is an allowlist of source-path globs, not full bind specs. The entry `/root/.docker:/root/.docker:ro` was being treated as a literal pattern and never matched the bind's source `/root/.docker`. Same for the other two entries — they were just no-ops because the auto-mount / explicit options were the things actually creating the binds. Fix: rewrite valid_volumes entries as bare source paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
silvermetal-builder runner deployment
The Gitea Actions runner that handles runs-on: silvermetal-builder jobs from .gitea/workflows/build-iso-linux.yaml.
Layout
| File | Purpose |
|---|---|
docker-compose.yml |
act_runner service definition, deployed on SLAB docker host. |
Dockerfile.runner |
Adds docker-cli to the upstream gitea/act_runner image. |
config.yaml |
act_runner runtime config — privileged, 4h timeout, host network. |
.env.example |
Template for the registration-token env file (real .env not commit). |
Why privileged
live-build needs loop devices and chroot inside the build container. Without privileged: true, mksquashfs and debootstrap fail. This is the only Gitea runner in the SilverLABS fleet that runs privileged — keep its scope narrow (one repo, one job class).
Deploy
On the SLAB docker host (10.0.0.51):
sudo mkdir -p /opt/silvermetal-builder-runner
cd /opt/silvermetal-builder-runner
# Copy this directory's contents in (e.g. via scp or rsync from a checkout
# of SilverLABS/SilverMetal at linux/build/runner/).
# Then create the .env with a fresh registration token:
GITEA_TOKEN=<admin-token> \
curl -H "Authorization: token $GITEA_TOKEN" \
https://git.silverlabs.uk/api/v1/admin/runners/registration-token
cp .env.example .env
$EDITOR .env # paste the token
# Log in to the registry on the *host* — config.yaml mounts the resulting
# /root/.docker/config.json into both the act_runner container and every
# job container it spawns, so the builder-image job in build-iso-linux.yaml
# can `docker push` without its own login step.
docker login docker-registry.silverlabs.uk
# Pre-pull the builder image so the first job isn't a cold start. (Skip
# this on the very first deploy: the :latest tag won't exist until CI
# runs once. After that it's pushed by the builder-image job.)
docker pull docker-registry.silverlabs.uk/silvermetal-builder:latest || true
docker compose up -d
docker compose logs -f --tail 50 # watch for "Runner registered"
Check the runner shows up under git.silverlabs.uk/-/admin/actions/runners with label silvermetal-builder.
Bump the runner image / config
cd /opt/silvermetal-builder-runner
git pull # if you keep this dir as a checkout
docker compose up -d --build
Tear down
docker compose down -v # -v drops runner-data volume; runner has to re-register
The runner-data volume holds the registered runner identity — keep it across image bumps so we don't pollute the Gitea runners list with dead entries.