anvilsign in

collin/anvil

RenderedSource

anvil

A git forge built using gitoxide.

Architecture

A Cargo workspace. The keystone is anvil-git: gix is a client library with no server-side protocol, so anvil supplies its own transport-agnostic upload-pack/receive-pack (smart-HTTP and SSH share one implementation).

CrateResponsibility
anvil-coreDomain model, SQLite persistence, on-disk bare-repo storage
anvil-gitServer-side git wire protocol on gix (upstream-candidate)
anvil-webaxum HTTP server: web UI + smart-HTTP git endpoints
anvil-sshgit-over-SSH (russh)
anvil-clianvild daemon + admin CLI

Quick start

cargo run -- migrate                              # create data/ + database
cargo run -- user create alice --password secret  # create a user
cargo run -- repo create alice/hello              # create a bare repo on disk
cargo run -- serve                                # start the server

Configuration is optional; see anvil.example.toml. PORT/HOST and ANVIL_BASE_URL (or PORTLESS_URL) override the listen address and public URL, so a proxy can place anvil without a config file.

To run it in Docker the way it runs in production, compose.override.yaml layers local settings over the deployment file and compose merges it automatically:

./deploy/build.sh --debug     # stage the binary the image COPYs in
docker compose up -d --build  # then http://127.0.0.1:20640
docker compose logs -f
docker compose down

The override swaps in deploy/anvil.dev.toml (so agent sessions are on and the SSO issuer is https://login.localhost), publishes to loopback instead of the droplet's public IP, uses the anvil-dev-data volume, and mounts the Docker socket that agent sessions need. hag passes -f compose.yaml explicitly, so none of it reaches the host.

./deploy/dev.sh is the fuller path and still there: it also generates the deploy/dev-ca.crt bundle the override mounts, waits for /-/healthz, and points portless at the container for https://anvil.localhost.

Deploying

compose.yaml describes the deployment; hag, the shared deploy tool for every project on hagrid, runs it there. The image carries a prebuilt static binary rather than compiling in Docker, so one step comes first:

./deploy/deploy.sh       # cross-compile, build, push, then restart on the host
./deploy/deploy.sh -n    # dry run: print every step, change nothing
hag status               # what the host is running
hag logs -f              # its logs

Full details, including first-run setup and the CD webhook, are in DEPLOY.md.

Docs