Gitea Actions runner for docker-1 (deploy/runner), DEPLOY.md and PLAN.md notes
ci / frontend (push) Successful in 10m18s
ci / server (push) Successful in 13m14s
ci / e2e (push) Failing after 39s
ci / image (push) Failing after 3m5s

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
2026-10-16 10:05:40 -06:00
co-authored by Claude Fable 5.1
parent 37d9a0cb50
commit 0df0ea62e9
6 changed files with 136 additions and 1 deletions
+54
View File
@@ -0,0 +1,54 @@
# Gitea Actions runner on docker-1
`.gitea/workflows/ci.yml` runs on a Gitea Actions runner. This folder holds the runner's compose file and
configuration. It lives on docker-1 at `~/gitea/runner`, next to the Gitea compose project, and runs as
the `spencerm` user through the Docker socket. No sudo is needed.
## What it runs
- One `act_runner` container (`docker.gitea.com/act_runner`, pinned by digest in compose.yaml), named
`docker-1` in Gitea, with the label `ubuntu-latest` mapped to `docker.gitea.com/runner-images:ubuntu-latest`
(Ubuntu 24.04 with git, node, python 3.12, docker and compose).
- Every job of ci.yml runs in a fresh job container from that image. The server job's PostgreSQL service
container and the e2e job's compose stack (postgres, migrate, app, worker, the Samba DC, Playwright) are
started through the runner's Docker proxy on docker-1's daemon. The proxy maps the job workspace so the
compose bind mounts (`deploy/postgres/initdb`, `tests/e2e`, the CI secrets) resolve, and it removes what
the job started when the job ends.
- Capacity 2: server and frontend run at the same time; e2e waits for both.
## Install (once)
```bash
mkdir -p ~/gitea/runner/data
cp deploy/runner/compose.yaml ~/gitea/runner/
cp deploy/runner/config.yaml ~/gitea/runner/data/
cd ~/gitea/runner
docker compose run --rm --entrypoint act_runner runner register --no-interactive \
--instance https://gt.pescoinc.biz --name docker-1 --config /data/config.yaml \
--labels ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest \
--token "$(docker exec -u git gitea gitea actions generate-runner-token)"
docker compose up -d
docker compose logs --tail 20 runner
```
The registration token is generated by Gitea's own CLI inside the `gitea` container and goes straight
into the register command. It is never printed or written to a file. The result is `data/.runner`,
which holds the runner's own token: keep the `data` folder private (it is owned by `spencerm`).
## Operate
- Logs: `docker compose -f ~/gitea/runner/compose.yaml logs -f runner`. Job logs are also kept under
`~/gitea/runner/data/logs` for a week.
- Update: change the digest in compose.yaml (`docker buildx imagetools inspect docker.gitea.com/act_runner:0.4`),
then `docker compose up -d`. The registration survives updates.
- Re-register (new instance URL or labels): remove `data/.runner` and run the register command again.
Gitea keeps the old runner row; delete it in Site administration, Actions, Runners.
- The runner shows in Gitea under Site administration, Actions, Runners. Repository secrets for the
image job (`REGISTRY_USER`, `REGISTRY_TOKEN`) are set per repository under Settings, Actions, Secrets.
## Known limits
- The job images and the actions (`actions/checkout`, `setup-python`, `setup-node`, the docker ones) are
fetched from docker.gitea.com, GitHub and GitHub releases, so docker-1 needs outbound internet.
- The Samba DC in the e2e stack needs `cap_add: SYS_ADMIN`. The first run on this runner shows whether the
Docker proxy allows it; if not, the e2e job stays a by-hand step (docs/DEPLOY.md).
+36
View File
@@ -0,0 +1,36 @@
# Gitea Actions runner for docker-1. One act_runner container with the host Docker socket.
# Jobs run in docker.gitea.com/runner-images:ubuntu-latest containers started through the socket;
# the runner's Docker proxy lets a job's `docker compose` bind-mount the workspace by its own path,
# which is what the e2e job needs for deploy/compose.ci.yaml.
#
# Install on docker-1 (see README.md): copy this folder to ~/gitea/runner, register once, then up -d.
# cd ~/gitea/runner
# docker compose run --rm --entrypoint act_runner runner register --no-interactive \
# --instance https://gt.pescoinc.biz --name docker-1 --config /data/config.yaml \
# --labels ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest \
# --token "$(docker exec -u git gitea gitea actions generate-runner-token)"
# docker compose up -d
# The registration token goes straight from Gitea into the register command. It is never written down.
name: gitea-runner
services:
runner:
# docker.gitea.com/act_runner:0.4 (act_runner v0.4.1), pinned by digest 2026-10-16.
# To refresh: docker buildx imagetools inspect docker.gitea.com/act_runner:0.4
image: docker.gitea.com/act_runner:0.4@sha256:696a59b51ad3d149521e3beb0229d5fb88f87295e1616f940199793274415b56
environment:
CONFIG_FILE: /data/config.yaml
# Registration happens once, by hand, with the command above. These two are only read on an
# unregistered start and are left here so the names are known; no token is set in this file.
GITEA_INSTANCE_URL: https://gt.pescoinc.biz
GITEA_RUNNER_NAME: docker-1
volumes:
- ./data:/data # .runner (the registration), config.yaml, cache, job logs
- /var/run/docker.sock:/var/run/docker.sock # job containers and the Docker proxy
restart: unless-stopped
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
+27
View File
@@ -0,0 +1,27 @@
# act_runner configuration for the docker-1 runner. Every value not set here keeps the runner's default.
# Reference: https://gitea.com/gitea/act_runner/src/branch/main/internal/pkg/config/config.example.yaml
log:
level: info
job:
dir: /data/logs # a copy of each job log, kept a week
retention: 168h
runner:
file: /data/.runner
capacity: 2 # server and frontend jobs run side by side; the e2e job is heavy on its own
timeout: 1h
labels:
- "ubuntu-latest:docker://docker.gitea.com/runner-images:ubuntu-latest"
cache:
enabled: true
dir: /data/cache
container:
# The job workspace is a Docker volume; the Docker proxy maps workspace paths for sibling
# containers, so `docker compose` in the e2e job can bind-mount tests/e2e and deploy/postgres/initdb.
privileged: false
valid_volumes: []
# The proxy removes what a job started (the CI compose stack included) when the job ends.
sweep: true