Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Ship the runner's unit and let a deployment create a runner machine

d0d4239f3f7236197c87a752d7965de238430f98 · Keenan Nemetz · 3d ago · parent dbae2e01

Ship the runner's unit and let a deployment create a runner machine

The package installs one binary that is the forge, the runner, and the CLI,
so it now carries a second unit. It is not enabled, and it refuses to start
with a message until an operator fills in /etc/vole/runner.env: who runs
builds on a machine is that machine owner's decision.

The unit runs as a dedicated account, because rootless podman needs a home
directory and a range of subordinate ids, and because a job should not find
the forge's own account on the same disk. The arguments live in that one
file rather than in the unit, split at spaces by systemd, so a single unit
serves every machine.

Each Terraform configuration takes runner=true and creates that machine
beside the forge: its own firewall, no backups (its checkouts and caches are
copies), the same key for a shell, and Cloud-init that installs the package,
creates the account and its subuids, generates the runner's key, pins the
instance's host key once, and enables the unit. The runner_setup output
prints the three commands that let it take work, filled in with the
addresses this apply created.

The first-boot file cannot register the runner: the allowlist is per
repository, and at first boot there are no repositories. That step stays
with an instance admin, and the docs say so.

deploy/terraform/aws/outputs.tf +14

@@ -27,3 +27,17 @@ output "dns_record" {
27 27 description = "The record created when create_dns is true."
28 28 value = var.create_dns ? "${var.domain} A ${aws_eip.vole.public_ip}" : "not managed here; point ${var.domain} at ${aws_eip.vole.public_ip}"
29 29 }
30
31 output "runner_ipv4" {
32 description = "The runner's public address, or null when runner is false. Its only use is a shell."
33 value = var.runner ? aws_instance.runner[0].public_ip : null
34 }
35
36 output "runner_setup" {
37 description = "The commands that let the runner take jobs. Run them from a machine that holds your admin key."
38 value = var.runner ? join("\n", [
39 "ssh -i <private-key> ubuntu@${aws_instance.runner[0].public_ip} sudo cat /var/lib/vole-runner/.ssh/id_ed25519.pub | vole admin --remote ssh://git@${var.domain}:2222 account create ci-runner-1 --bot --key -",
40 "vole admin --remote ssh://git@${var.domain}:2222 acl runners add <repo> ci-runner-1",
41 "vole admin --remote ssh://git@${var.domain}:2222 acl set-role <repo> ci-runner-1 read",
42 ]) : "runner is false: pass -var runner=true to create one"
43 }