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.

Code

395 commit(s) on main

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