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/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

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

Blame · docs/deploy/hetzner.md

Line attribution on main · 129 line(s)

b8e7a567
Keenan Nemetz
3d ago
1 # Vole on Hetzner Cloud
2
942c93cd
Keenan Nemetz
3d ago
3 One server, configured on its first boot by a file you paste into the console. No
4 API token, nothing to install locally: a rendered file, a server, a firewall, and
5 one DNS record.
b8e7a567
Keenan Nemetz
3d ago
6
7 ## What you need
8
942c93cd
Keenan Nemetz
3d ago
9 - A Hetzner Cloud account and a project.
10 - A DNS name, such as `forge.example.com`.
11 - Your SSH public key.
c1edfd3c
Keenan Nemetz
3d ago
12 - The URL of a Vole `.deb` for `amd64` — or `arm64` on a CAX server type — from
b7396a11
Keenan Nemetz
2h ago
13 [Vole's releases](https://rodent.software/vole/releases).
b8e7a567
Keenan Nemetz
3d ago
14
942c93cd
Keenan Nemetz
3d ago
15 ## Render the first-boot file
b8e7a567
Keenan Nemetz
3d ago
16
942c93cd
Keenan Nemetz
3d ago
17 From a clone of the Vole repository, on your own computer:
b8e7a567
Keenan Nemetz
3d ago
18
19 ```sh
942c93cd
Keenan Nemetz
3d ago
20 cd deploy/cloud-init
21
22 HOSTNAME=forge.example.com \
23 ADMIN_ACCOUNT=admin \
24 ADMIN_EMAIL=you@example.com \
25 ADMIN_SSH_KEY="$(cat ~/.ssh/id_ed25519.pub)" \
b7396a11
Keenan Nemetz
2h ago
26 VOLE_PACKAGE_URL=https://rodent.software/vole/releases/v0.2.0/artifacts/vole_0.2.0-1_amd64.deb \
942c93cd
Keenan Nemetz
3d ago
27 ./render.sh > user-data.yaml
b8e7a567
Keenan Nemetz
3d ago
28 ```
29
942c93cd
Keenan Nemetz
3d ago
30 Open `user-data.yaml` before you paste it. It is the whole setup, and it is the
31 last chance to notice a wrong account name: names are permanent.
b8e7a567
Keenan Nemetz
3d ago
32
942c93cd
Keenan Nemetz
3d ago
33 ## Create the server
b8e7a567
Keenan Nemetz
3d ago
34
942c93cd
Keenan Nemetz
3d ago
35 In the Hetzner console, **Add Server**:
36
37 | Field | What to choose |
38 |---|---|
39 | Location | wherever your team is |
40 | Image | Ubuntu 24.04 (Debian 13 works too) |
41 | Type | CX22 — 2 vCPU, 4 GB, 40 GB. Raise it if you expect big pushes or LFS |
42 | Networking | public IPv4 |
43 | SSH key | yours, the same one you put in the file |
44 | Backups | on. It is a snapshot, not a backup of the instance — see [Backups](README.md#backups-are-still-your-job) |
45 | **Cloud config** | paste the contents of `user-data.yaml` |
46
47 Before or after creating it, add a **Firewall** in the same project and apply it to
48 the server. Hetzner leaves a new server open if you do not:
49
50 | Direction | Protocol | Port | Source |
51 |---|---|---|---|
52 | in | tcp | 22 | your team's addresses, for shell access |
53 | in | tcp | 2222 | your team's addresses. This is Git over SSH, the write transport |
54 | in | tcp | 80 | anywhere, for the certificate challenge |
55 | in | tcp | 443 | anywhere |
56 | out | any | any | anywhere, so the server can fetch its package and certificate |
57
58 Restricting 2222 to your team is the cheapest way to keep the write side private.
59 If you leave it open, Vole still authenticates every connection by key.
b8e7a567
Keenan Nemetz
3d ago
60
942c93cd
Keenan Nemetz
3d ago
61 ## Point the name at it
62
63 Create an `A` record for `forge.example.com` pointing at the server's IPv4
64 address. Vole cannot obtain a certificate for a name that does not resolve to it
65 yet, and it retries, so a record created a few minutes after the server is fine.
66
67 ## Check it works
68
69 Open `https://forge.example.com`. The first request may take a few seconds while
70 the certificate is issued; if it fails, wait a minute and reload.
71
72 Issue a passkey for the admin account from your laptop:
b8e7a567
Keenan Nemetz
3d ago
73
74 ```sh
75 vole admin --remote ssh://git@forge.example.com:2222 account invite admin
76 ```
77
942c93cd
Keenan Nemetz
3d ago
78 Then create a repository, and clone it:
79
80 ```sh
81 vole admin --remote ssh://git@forge.example.com:2222 repo create demo --owner admin
82 vole admin --remote ssh://git@forge.example.com:2222 acl set-default-role demo read
83 git clone ssh://git@forge.example.com:2222/demo.git
84 ```
85
86 ## Adding a CI runner
87
88 Create a second server the same way, but give it the runner's file:
89
90 ```sh
91 ./render.sh runner > runner-user-data.yaml # FORGE_HOST=forge.example.com and VOLE_PACKAGE_URL
92 ```
93
94 It needs no inbound ports except 22. It needs one more step per repository before
95 it takes work; see [CI runners](runner.md).
96
b8e7a567
Keenan Nemetz
3d ago
97 ## The settings worth changing
98
942c93cd
Keenan Nemetz
3d ago
99 The values you pass to `render.sh`. Everything else has a working default.
b8e7a567
Keenan Nemetz
3d ago
100
942c93cd
Keenan Nemetz
3d ago
101 | Variable | Default | What it does |
b8e7a567
Keenan Nemetz
3d ago
102 |---|---|---|
942c93cd
Keenan Nemetz
3d ago
103 | `HOSTNAME` | required | The name the instance answers on. It becomes `public_url`, and passkeys bind to it |
104 | `ADMIN_ACCOUNT` | required | The first account, made an instance admin. Permanent |
105 | `ADMIN_SSH_KEY` | required | That account's public key |
106 | `VOLE_PACKAGE_URL` | required | The `.deb` for the machine's architecture |
107 | `ADMIN_EMAIL` | empty | Contact address for the certificate authority |
108 | `INSTANCE_NAME` | `Vole` | What the landing page calls this forge |
109 | `TLS_MODE` | `acme` | `proxy` leaves TLS to a proxy you run, and serves plain HTTP on loopback |
e21f6c5e
Keenan Nemetz
3d ago
110
b8e7a567
Keenan Nemetz
3d ago
111 ## If something is not right
112
113 - **The browser shows a certificate warning.** DNS is not answering with the
942c93cd
Keenan Nemetz
3d ago
114 server's address yet, or ports 80 and 443 are blocked by the firewall. Check
115 `dig +short forge.example.com`, then `journalctl -u vole | grep -i acme`.
116 - **The server is up but the forge is not.** First-boot output is in
117 `/var/log/vole-first-boot.log`; the service log is `journalctl -u vole`. The
118 usual cause is a package URL that 404s or is for the other architecture.
119 - **Nothing listens on 2222.** The firewall is not applied to the server, or its
120 source addresses do not include where you are pushing from.
121 - **Pushing is refused.** `vole whoami --remote ssh://git@forge.example.com:2222`
122 says which account your key is; if it is not the one you expected, the key was
123 not the one in `user-data.yaml`.
b8e7a567
Keenan Nemetz
3d ago
124
125 ## Next
126
942c93cd
Keenan Nemetz
3d ago
127 - [Deploying Vole](README.md) — what first boot does, backups, and upgrades
b8e7a567
Keenan Nemetz
3d ago
128 - [Packages](../packaging.md) — the `.deb`, the unit file, and upgrades on the machine
129 - [Accounts and access](../accounts-and-access.md) — the first accounts, roles, and passkeys