Monitoring primarily

This commit is contained in:
Aner Zakobar
2026-05-10 11:30:43 +03:00
parent 0e54760e34
commit af744e819c
20 changed files with 1269 additions and 43 deletions
+317
View File
@@ -0,0 +1,317 @@
#+TITLE: Gitea Actions Runner — Workflows & Usage Guide
#+DATE: 2026-05-04
#+AUTHOR: homey project
#+OPTIONS: toc:2 num:t
* Overview
This document covers the Gitea Actions runner setup on pi-main, how the runner
works, the label system, and example workflows for both host-based ("ubuntu")
and Nix-native jobs.
** Architecture
The runner is configured in =modules/services/gitea-runner.nix= and uses the
NixOS native =services.gitea-actions-runner= module. Jobs run with the *host*
executor: each step executes directly on the Pi 4 as the =gitea-runner-pi-main=
system user. There is no container isolation per job.
#+BEGIN_EXAMPLE
Gitea (podman container)
│ HTTPS → Cloudflare tunnel → Caddy → git.zakobar.com
│ (runner connects outbound via HTTPS, same path as a browser)
gitea-actions-runner (systemd service)
│ host executor
Jobs run as: gitea-runner-pi-main (unprivileged system user)
PATH includes: nix, git, bash + system packages
#+END_EXAMPLE
** Runner labels
Labels are advertised to Gitea and matched against =runs-on:= in workflow
files. The default labels configured in this project are:
| Label | Executor | Notes |
|---------------+----------+--------------------------------------------|
| =native:host= | host | Canonical label for "run on this machine" |
| =ubuntu-latest= | host | Matches common GitHub Actions workflows |
| =debian-latest= | host | Alternative for Debian-targeting workflows |
| =nix:host= | host | Explicit label for Nix-native jobs |
All four labels route to the same runner process and the same host environment.
The difference is purely semantic — pick the label that makes your workflow's
intent clear.
** Nix daemon trust
The runner user is added to =nix.settings.trusted-users=, which means it can:
- Evaluate flakes (=nix flake check=, =nix build=)
- Write derivation outputs to the Nix store
- Pass =--extra-experimental-features= flags to the daemon
- Use =nix copy= to push/pull store paths to a remote cache
It cannot modify NixOS system configuration or run privileged operations.
* Example workflows
Workflow files live in =.gitea/workflows/= inside each repository (or
=.github/workflows/= — Gitea Actions supports both paths).
** Minimal smoke test (host)
The simplest possible workflow — runs a shell command on the runner.
#+BEGIN_SRC yaml
# .gitea/workflows/smoke.yaml
on: [push]
jobs:
smoke:
runs-on: native:host
steps:
- uses: actions/checkout@v3
- run: echo "Runner is alive on $(hostname)"
#+END_SRC
** Standard shell-based CI (ubuntu-latest label)
Use this for repos that want to stay compatible with GitHub Actions. The
workflow looks identical to what you'd push to GitHub; it just runs on your Pi.
#+BEGIN_SRC yaml
# .gitea/workflows/ci.yaml
on:
push:
branches: [main, master]
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
# On the host executor, use nix-shell or system packages.
# apt/yum are NOT available — this is NixOS, not Ubuntu.
# Use nix-shell -p for one-off tools:
nix-shell -p nodejs --run "node --version"
- name: Run tests
run: |
nix-shell -p nodejs --run "npm test"
#+END_SRC
*Important:* Despite the label =ubuntu-latest=, the host is NixOS. =apt=,
=yum=, and FHS paths like =/usr/bin/python3= are not available. Use
=nix-shell -p <pkg>= to bring in any tool you need.
** Nix flake check
Validate a flake on every push — the most common use case for this runner.
#+BEGIN_SRC yaml
# .gitea/workflows/flake-check.yaml
on: [push, pull_request]
jobs:
check:
runs-on: nix:host
steps:
- uses: actions/checkout@v3
- name: Check flake
run: nix flake check --no-build
- name: Build default package
run: nix build
#+END_SRC
** Nix build with caching
Build a derivation and push the result to a binary cache so subsequent builds
are fast. Requires a Cachix account or an S3-compatible cache configured in
=nix.settings=.
#+BEGIN_SRC yaml
# .gitea/workflows/build-and-cache.yaml
on:
push:
branches: [main]
jobs:
build:
runs-on: nix:host
steps:
- uses: actions/checkout@v3
- name: Build
run: nix build --print-build-logs
- name: Push to cache
# nix copy requires the runner user to be in trusted-users (already set).
# Replace the URI with your actual cache.
run: |
nix copy --to "s3://your-cache-bucket?region=us-east-1" ./result
#+END_SRC
** NixOS configuration check (this repo)
Check that the homey flake evaluates cleanly on every change. Add this to the
homey repo itself.
#+BEGIN_SRC yaml
# .gitea/workflows/nixos-check.yaml
on: [push, pull_request]
jobs:
eval:
runs-on: nix:host
steps:
- uses: actions/checkout@v3
- name: Evaluate NixOS configurations
run: |
nix flake check --no-build
# Optionally build a specific host config (slow on Pi):
# nix build .#nixosConfigurations.pi-main.config.system.build.toplevel
- name: Check formatting (optional)
run: |
nix-shell -p nixpkgs-fmt --run "nixpkgs-fmt --check ."
#+END_SRC
** Multi-step pipeline with artifacts
#+BEGIN_SRC yaml
# .gitea/workflows/pipeline.yaml
on:
push:
tags: ['v*']
jobs:
build:
runs-on: nix:host
steps:
- uses: actions/checkout@v3
- name: Build release
run: nix build --out-link result
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: release-binary
path: result/bin/
deploy:
needs: build
runs-on: native:host
steps:
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: release-binary
- name: Deploy
run: ./deploy.sh
#+END_SRC
* Caveats and gotchas
** No apt/brew/yum
The host is NixOS. Package managers from other distros do not work. Use
=nix-shell -p <pkg> --run "..."= for ad-hoc tools, or add a =shell.nix= /
=flake.nix= devShell to your repo and enter it with =nix develop=.
** No Docker/Podman per job
The host executor does not launch a fresh container per job. All jobs share the
same filesystem (under =/home/gitea-runner-pi-main/=) and the same running
system. This means:
- No isolation between concurrent jobs (though concurrency defaults to 1).
- Side effects (files written, packages installed with nix) persist between
runs unless you clean up explicitly.
- Use =nix build= output symlinks (=./result=) rather than writing to system
paths.
** actions/checkout and git
The =actions/checkout@v3= action works fine on the host executor. It clones
into the runner's working directory. Subsequent steps run in that directory by
default.
If you use =actions/checkout@v4=, note that it requires a newer Node.js. On
NixOS you can't rely on a system Node, so either pin to v3 or use:
#+BEGIN_SRC yaml
- uses: actions/checkout@v3 # v3 bundles its own Node runtime
#+END_SRC
** Nix experimental features
Flake commands require =nix-command= and =flakes= experimental features. These
are typically enabled system-wide in =nix.settings.experimental-features= in
=modules/common.nix=. If a job fails with "experimental feature not enabled",
you can pass it inline:
#+BEGIN_SRC yaml
- run: nix --extra-experimental-features "nix-command flakes" flake check
#+END_SRC
Or ensure =common.nix= has:
#+BEGIN_SRC nix
nix.settings.experimental-features = [ "nix-command" "flakes" ];
#+END_SRC
** Token rotation
The registration token in =gitea/runner_token= is consumed on first
registration. The runner then stores its own credentials in
=/var/lib/gitea-runner/pi-main/.runner=. If you need to re-register (e.g.
after wiping the state directory), generate a new token from Gitea's admin UI
and update the sops secret before restarting the service.
** Pi 4 performance
The Pi 4 is capable but not fast for heavy builds. Tips:
- Enable the Nix binary cache (=nixos-cache.nixos.org= is on by default) so
pre-built derivations are fetched instead of compiled.
- Set =nix.settings.max-jobs= to =4= to use all cores for parallel builds.
- Avoid building large packages (LLVM, Chromium) locally — push to a remote
builder or use Cachix.
* Debugging
** Check runner status
#+BEGIN_SRC sh
systemctl status gitea-runner-pi-main
journalctl -u gitea-runner-pi-main -f
#+END_SRC
** Runner registration state
#+BEGIN_SRC sh
cat /var/lib/gitea-runner/pi-main/.runner
#+END_SRC
** Force re-registration
#+BEGIN_SRC sh
# Stop, wipe state, restart (runner will re-register using the token file)
systemctl stop gitea-runner-pi-main
rm /var/lib/gitea-runner/pi-main/.runner
systemctl start gitea-runner-pi-main
#+END_SRC
** Test a workflow locally
Use =act= (the local runner) to test workflow files before pushing:
#+BEGIN_SRC sh
nix-shell -p act --run "act push"
#+END_SRC
Note: =act= spins up Docker containers for each job, so results may differ
slightly from the host-executor runner, but it is useful for syntax checking
and logic testing.