# Gitea Actions: quick notes 🔧 ## What this adds - `.gitea/workflows/ci.yml` — runs backend Maven tests and builds the frontend on every `push`. ## Requirements (quick checklist) 1. **Enable Actions** for this repository: Repository Settings → Actions → Enable Repository Actions. 2. **Runner (act_runner)**: you must register at least one runner so jobs can execute. - Prefer running the runner on a separate machine from the Gitea server. - You can use the `gitea/act_runner` docker image or the binaries from Gitea downloads. ### Example runner registration (local machine) 1. On your host, download or pull the runner image: `docker pull gitea/act_runner:latest`. 2. Start a container for registration only (refer to docs for token and instance): - Get a token from Gitea UI: **Settings** → **Actions** → **Runners** → **Generate token** (repo/org/instance level). - Run the register command (example using container; adjust instance and token): ```bash docker run --rm -it -v $PWD:/data gitea/act_runner register --instance https://your.gitea.host --token ``` 3. Start the runner daemon (on the machine where you registered): ```bash ./act_runner daemon # or use the docker image as a long-lived container after registration ``` ## Secrets & env - If tests or builds need credentials, add them to **Settings → Secrets** at repo/org/instance level and reference via `${{ secrets.MY_SECRET }}`. ## Notes & tips - The workflow uses `actions/setup-java` and `actions/setup-node` which fetch from public actions. If your runner has restricted network access, adjust steps to install local toolchains instead. - If you want to run integration tests or deploy artifacts, tell me which target host or container you'll use and I can add deploy steps. --- ## Deploying the runner to all workers (recommended for docker-executor) If you want the runner to run on every worker node, use the provided `gitea-act-runner-stack.yml` which runs the service in `mode: global` with a placement constraint for workers: ```yaml deploy: mode: global placement: constraints: - node.role == worker ``` Notes: - This will start one runner instance on each worker node. If you need fewer runners, switch to `mode: replicated` and use `replicas` with a node label constraint (e.g., `node.labels.runner == true`). - Mounting `/var/run/docker.sock` gives the runner the ability to run job containers (docker-executor) but is a security-sensitive choice — only run this on trusted worker nodes. ### Quick deploy ```bash # from a manager node docker stack deploy -c gitea-act-runner-stack.yml act-runner ``` ### Optional: label nodes instead of using node.role If you prefer to run on a subset of workers, add a label to desired nodes and update the `placement.constraints`: ```bash docker node update --label-add runner=true ``` Then use: ```yaml placement: constraints: - node.labels.runner == true ``` --- ## Registration examples & troubleshooting 🔍 If you see errors like `instance address is empty`, it means the runner registration command wasn't given an instance URL (via `--instance` or `GITEA_INSTANCE_URL`). Use one of these approaches depending on your environment. 1) One-shot CLI (internal Swarm network) ```bash docker run --rm -it --network gitea -v act_runner-data:/data gitea/act_runner register \ --instance http://gitea_server:3000 --token --no-interactive --name swarm-runner ``` Use the internal service name (`gitea_server:3000`) when registering from inside the Swarm `gitea` network. 2) One-shot (public/Traefik URL) ```bash docker run --rm -it -v act_runner-data:/data gitea/act_runner register \ --instance https://git.mariuszpacek.pl --token --no-interactive --name swarm-runner ``` If you use an HTTPS URL, ensure the container trusts the cert (or use the internal HTTP address if available). 3) Auto-register & run with env vars (recommended for simple Docker usage) This will register (if needed) and start the runner in one step: ```bash docker run -d --name gitea-runner \ -v act_runner-data:/data -v /var/run/docker.sock:/var/run/docker.sock \ -e GITEA_INSTANCE_URL=https://git.mariuszpacek.pl \ -e GITEA_RUNNER_REGISTRATION_TOKEN= \ -e GITEA_RUNNER_NAME=swarm-runner \ gitea/act_runner:latest ``` 4) Portainer notes - For a temporary registration container, set image `gitea/act_runner:latest`, **Command** to: `register --instance http://gitea_server:3000 --token --no-interactive` - Or set environment variables `GITEA_INSTANCE_URL` and `GITEA_RUNNER_REGISTRATION_TOKEN` and start the container (detached) to auto-register. 5) Debugging checks - Test reachability from the registrator container: ```bash docker run --rm --network gitea curlimages/curl curl -sS http://gitea_server:3000/api/v1/version ``` - Verify `.runner` written to the volume: ```bash docker run --rm -v act_runner-data:/data alpine sh -c "ls -la /data && cat /data/.runner" ``` - Check logs of the register container / service for precise errors. If the error persists, paste the exact register command you ran and its container logs and I'll inspect them. --- ## Portainer: secure register + deploy (recommended) Use a one-shot *registration stack* (deploy it, wait for logs, then remove it) and then deploy the long-running daemon stack that uses a Docker secret for the registration token. 1) **Create a secret** in Portainer (or via CLI): - Portainer: *Secrets → Add secret* → name: `registration_token` → value: `` - CLI: `echo "" | docker secret create registration_token -` 2) **Register (one-shot)** — Stack: `.gitea/act-runner-register-stack.yml` - Deploy in Portainer → set stack variables: - `INSTANCE_URL` = `http://gitea_server:3000` (or `https://git.mariuszpacek.pl`) - `REGISTRATION_TOKEN` = *your token* (or use a temporary secret and modify command to read it) - Check service logs for success, then remove this stack. 3) **Deploy daemon (global on workers)** — Stack: `.gitea/act-runner-deploy-stack.yml` or `gitea-stack-secured.yml` - Ensure secret `registration_token` exists (see step 1). - Deploy the secure stack (`gitea-stack-secured.yml`) which references the `registration_token` secret and applies Traefik TCP IP whitelist for SSH. - Important: the `act_runner` service sets `GITEA_RUNNER_LABELS=swarm-runner,self-hosted` so runners register with the `swarm-runner` label used by workflows. If you already had runners registered, redeploying the stack *should* update labels; if labels don't appear, re-register the runner (see steps below). - Deploy stack via Portainer and set `INSTANCE_URL` and `RUNNER_NAME` as environment variables in Portainer if needed. - Runner will start as a global service on workers and read the token from `/run/secrets/registration_token` (no token stored in repo). --- ### If labels do not update after redeploy 1. Check current runner labels in Gitea UI: **Settings → Actions → Runners**. If `swarm-runner` is missing, re-register the runner to apply labels: - One-shot register stack (Portainer stack or docker run) with `--labels "swarm-runner,self-hosted"` or set `GITEA_RUNNER_LABELS` before registration. 2. Alternatively, remove the existing `.runner` file from the `act_runner-data` volume and restart the service so it re-registers using the environment labels: ```bash docker run --rm -v act_runner-data:/data alpine sh -c "rm -f /data/.runner && echo removed" # then redeploy stack docker stack deploy -c gitea-stack-secured.yml gitea ``` 3. After re-registration, confirm labels in Gitea UI and re-run a workflow to validate jobs are picked up. Notes: - **Do not commit tokens to the repo.** Use Docker secrets or Portainer's secret store. - If you prefer a quick test, the register stack accepts `REGISTRATION_TOKEN` as an env var (less secure). After successful registration, remove the env token and rely on the Docker secret for the daemon stack. --- ## Locking down SSH access via Traefik (recommended) The provided `gitea-stack-secured.yml` deploys a TCP middleware `ssh-ipwhitelist` and assigns it to the SSH router for Gitea. It restricts which source IP ranges can reach the SSH service exposed through Traefik (this prevents most unsolicited SSH attempts from the Internet). If you want to restrict only to your internal network and known IPs, ensure the following CIDRs are present in the stack file's labels (adjust as needed): `10.0.1.0/24`, `192.168.0.0/24`, and your public IP like `83.26.248.249/32`. You can edit the `ssh-ipwhitelist` ranges directly in `gitea-stack-secured.yml` under the `gitea_server` `deploy.labels` section: ```yaml - "traefik.tcp.middlewares.ssh-ipwhitelist.tcp.ipwhitelist.sourcerange=83.26.248.249/32,10.0.1.0/24,172.18.0.0/16,192.168.0.0/24" ``` After changing the ranges, redeploy the stack (Portainer: Update Stack → Deploy / CLI: `docker stack deploy -c gitea-stack-secured.yml gitea`). If you prefer to fully disable SSH through Traefik, remove the Traefik TCP labels from the Gitea service and instead use direct host-level rules (firewall) to allow only specific hosts to connect.