DocsSelf-hosting
Docs/Reference

Self-hosting

Anvil is open to run on your own server. One Docker Compose bundle brings up Anvil, its Postgres database and the Gitea instance behind hosted repositories, sets Gitea up the way Anvil needs, and gives you a one-time link to create the first admin. Moving an install to another server is a backup and a restore.

This page is the short version. The full guide, with every option, is docs/SELF-HOSTING.md in the repository.

What you need #

  • A Linux server with Docker and the Compose plugin: 2 vCPU and 4 GB of memory to start, more with runners.
  • A domain with two names pointing at it: anvil.example.com and git.anvil.example.com.
  • Ports 80 and 443 open (web and certificates) and 2222 (git over SSH).
  • An Anthropic API key. SMTP for emails and a GitHub account for the GitHub App are optional.

Install #

bash
git clone https://github.com/davidwickerhf/anvil.git /srv/anvil
cd /srv/anvil/deploy/compose
./init.sh anvil.example.com you@example.com
$EDITOR .env      # ANTHROPIC_API_KEY, and SMTP_URL if you have one
docker compose up -d

init.sh writes .env with fresh secrets. The bundle includes Caddy, which gets certificates for both names on its own; to use your own reverse proxy instead, remove proxy from COMPOSE_PROFILES and point it at 127.0.0.1:3000 (Anvil) and 127.0.0.1:3001 (Gitea).

The first admin #

While there is no admin, Anvil prints a one-time link when it starts:

bash
docker compose logs anvil | grep -A2 "No admin yet"

Open it, choose a login and enter your email address. You're signed in as the admin. Then open Settings → Setup: it shows what's configured (Gitea, the webhook, mail, GitHub, runners, SSH, backups) and what to do about anything missing. Invite others from Settings → Access and create the GitHub App from Settings → GitHub.

What the setup does for you #

Before Anvil starts, a setup step signs in to Gitea and creates what Anvil needs if it's missing: an admin token, the review bot @anvil and its token, the OAuth app behind "Continue with Gitea", and a system webhook with every event Anvil uses. It runs on every start and repairs anything that went missing, for example the OAuth redirect URI after a change of address.

Backups and moving servers #

bash
scripts/anvil-backup --keep 14       # one archive: databases, repositories, LFS, SSH host keys, settings
scripts/anvil-restore <archive>      # on the new server; --domain new.example.com if the address changes

The archive holds every secret of the install, so encrypt it before copying it off the server. Because the SSH host keys move with it, people's git clients keep trusting the server. When the address changes, the restore lists what to update: the GitHub App's URLs, people's clone remotes and MCP clients.

Runners #

CI jobs with runs-on: anvil-* need the runner manager (COMPOSE_PROFILES=proxy,runners). It controls Docker on the machine it runs on, so run other people's workflows on a separate machine. See CI and Security and data.