iac/ansible
Sergei Poljanski d0f6bcf6cf
All checks were successful
deploy / ansible (push) Successful in 4m43s
ansible: run the another-im/interop runner on asxpio-services
The interop project kept a cx23 (claude-test-interop-runner, about
EUR 6/month with its IPv4) only to run its Forgejo runner. Run it here
instead, with the same registration (UUID + token, token in the vault)
and the same three labels, pinned.

Its PR checks are untrusted, so unlike our own runner its jobs get
neither the Docker socket nor host volumes. nix-host, which on the old
host used the host's Nix store as a cache, is a throwaway container for
now; a second, trusted-only registration can bring the cache back.

Rollback: remove the role from site.yaml (or stop the container) and
start the old runner VM again.

Assisted-by: Claude:opus-5-5
2026-11-13 03:47:17 +04:00
..
inventory ansible: run the another-im/interop runner on asxpio-services 2026-11-13 03:47:17 +04:00
playbooks s3fs: turn it off on asxpio-services too 2026-11-12 22:52:12 +04:00
roles ansible: run the another-im/interop runner on asxpio-services 2026-11-13 03:47:17 +04:00
.gitignore ansible cleanup 2025-11-04 14:23:16 +02:00
ansible.cfg ansible rework 2025-11-04 11:06:35 +02:00
known_hosts ci: deploy site.yaml from Forgejo Actions 2026-11-12 06:47:09 +04:00
README.md docs: runner 13 marks the self-replacing run as failed 2026-11-13 03:15:31 +04:00
site.yaml ansible: run the another-im/interop runner on asxpio-services 2026-11-13 03:47:17 +04:00

Ansible

site.yaml is the desired state of both servers and is applied by the deploy pipeline on every push to main. The playbooks under playbooks/ are host bootstrap and are run by hand.

Running

echo '<vault password>' > .vault_pass && chmod 600 .vault_pass

ansible-playbook site.yaml --check --diff       # dry run, over WireGuard
ansible-playbook site.yaml                      # apply
ansible-playbook site.yaml --tags forgejo       # one role

On NixOS: nix shell nixpkgs#ansible -c ansible-playbook ….

Templates that carry secrets are never shown in --diff output.

Inventories

  • inventory/hosts.yaml: default. Connects as root to the WireGuard addresses.
  • inventory/ci.yaml: used by the pipeline. Connects as deploy over the private network, reaching asxpio-services through asxpio-ops.

known_hosts pins both servers' SSH host keys for the pipeline.

Variables

inventory/
├── group_vars/all/
│   ├── network.yaml         # VPC and WireGuard addresses
│   ├── paths.yaml           # /opt
│   ├── s3.yaml              # object storage buckets and s3fs mounts
│   ├── wireguard.yaml       # WireGuard peers
│   └── vault.yaml           # encrypted secrets
├── group_vars/ops_servers/
│   ├── traefik.yaml         # traefik_version
│   └── forgejo.yaml         # forgejo_version, domain and aliases
├── group_vars/services_servers/
│   ├── forgejo_runner.yaml  # runner version, labels' nix image
│   └── minecraft.yaml
└── host_vars/               # per-host addresses, SSH and s3fs settings

Compose files without variables are plain files under roles/<role>/files/; edit the image tag there.

Roles in site.yaml

base, traefik, crawler_alert, forgejo, forgejo_runner, sillytavern, minecraft, xmpp, xray, restic_backup. Service roles go through docker_service, which writes the files, runs docker compose up -d, restarts on a config change and waits for the service to answer.

crawler_alert installs a copy of traefik-crawlers-statistics; update roles/crawler_alert/files/ from there.

Bootstrap playbooks

Playbook Purpose
01-wireguard-setup.yaml WireGuard hub on asxpio-ops, peer on asxpio-services, client configs
02-ssh-hardening.yaml restrict SSH to WireGuard and the private network
03-setup-s3fs.yaml s3fs mounts on asxpio-services (off on asxpio-ops)
04-add-user-zerrtika.yaml add a user to running servers
05-swap.yaml 2 GB swapfile on asxpio-ops

Always dry-run these first with --check --diff.

  • 03-setup-s3fs.yaml rewrites /etc/s3fs/.passwd-s3fs, which the backup script on asxpio-ops also reads.
  • On asxpio-services the WireGuard interface is named asxpio-services, not wg0. Check 01-wireguard-setup.yaml against the host before re-running it there.

Runner notes

The nix-latest label runs nixos/nix:<forgejo_runner_nix_version> with a nix-store-<version> volume over /nix. To bump it: change the variable, let the pipeline apply it, then remove the old volume.

Runner and nix image upgrades

forgejo_runner_version and forgejo_runner_nix_version are bumped by Renovate PRs. Applying either one recreates the runner while it runs the very job that applies it:

  • that run ends as failed (runner 13; cancelled on older runners) after everything else has been applied, its log stopping in the forgejo_runner role, and its job container stays behind on asxpio-services (docker ps | grep FORGEJO-ACTIONS-TASK); remove it;
  • the next run confirms the result. The workflow only triggers on changes under ansible/ (or workflow_dispatch in the web UI), so an empty commit starts nothing;
  • after a nix bump, remove the old nix-store-<old version> volume.