collin/anvil
f98caac96a50183c6fa615a9c40ead2a728d39c4 / compose.yaml
| 1 | # anvil on hagrid, deployed with `hag` -- the shared deploy tool for every |
| 2 | # project on that host (build, push to the private registry, then pull and |
| 3 | # recreate there). Both this machine and hagrid need |
| 4 | # `docker login registry.vibe.richardscollin.com` once. |
| 5 | # |
| 6 | # The image carries a PREBUILT binary: the Dockerfile only COPYs in |
| 7 | # docker/anvil/anvild, which deploy/build.sh cross-compiles as a static |
| 8 | # x86_64-musl executable. So `hag deploy` on its own is not enough -- use |
| 9 | # ./deploy/deploy.sh, which stages the binary and then calls it. |
| 10 | # |
| 11 | # IMAGE_TAG picks which build runs. hag sets it to the git sha it just pushed, |
| 12 | # so `hag status` names the exact build, and rolling back on the host is |
| 13 | # `IMAGE_TAG=<sha> docker compose up -d --no-build`. |
| 14 | services: |
| 15 | anvil: |
| 16 | image: registry.vibe.richardscollin.com/anvil:${IMAGE_TAG:-latest} |
| 17 | build: |
| 18 | # Context is the repo root (the binary is staged under docker/, and the |
| 19 | # baked config lives in deploy/), so the Dockerfile has to be named. |
| 20 | context: . |
| 21 | dockerfile: docker/anvil/Dockerfile |
| 22 | # hagrid is x86_64 and the staged binary is x86_64-musl. Pinning the |
| 23 | # platform stops an arm64 workstation from producing an image whose |
| 24 | # base layers the host cannot run. |
| 25 | platforms: |
| 26 | - linux/amd64 |
| 27 | container_name: anvil |
| 28 | restart: unless-stopped |
| 29 | |
| 30 | # Host config that must not be baked into the image -- today that is |
| 31 | # ANVIL_OIDC_CLIENT_SECRET (docs/oidc.md). Optional so the container still |
| 32 | # starts where there is none, matching how run.sh only passed the secret |
| 33 | # when it found one: an empty value here would override the baked config |
| 34 | # and turn a confidential OIDC client into a public one. |
| 35 | env_file: |
| 36 | - path: .env |
| 37 | required: false |
| 38 | |
| 39 | # [ci] deploy_webhook posts to a receiver on the host, so the container |
| 40 | # needs a route to it. Docker Desktop supplies this name; Linux does not. |
| 41 | extra_hosts: |
| 42 | - "host.docker.internal:host-gateway" |
| 43 | |
| 44 | ports: |
| 45 | # Git-over-SSH only. The web port stays unpublished -- Caddy reaches |
| 46 | # anvil:3000 over the hagrid network and terminates TLS. |
| 47 | # |
| 48 | # Published on the droplet's DEFAULT public IPv4 alone. The reserved IP |
| 49 | # (137.184.249.48) arrives on the anchor address 10.15.0.6, where the |
| 50 | # host's own sshd listens, so binding one specific IP here keeps the two |
| 51 | # off each other. |
| 52 | - "${ANVIL_SSH_BIND_IP:-165.232.162.167}:${ANVIL_SSH_PORT:-22}:2222" |
| 53 | |
| 54 | # NO DOCKER SOCKET. anvil does not execute CI any more -- runners dial in |
| 55 | # and run jobs on their own daemons (docs/remote-runners.md), so the |
| 56 | # container has no reason to reach Docker. Leaving the mount out is what |
| 57 | # removes the root-equivalent hold the internet-facing process used to have |
| 58 | # on the host. Agent sessions (crates/anvil-agent) are the one thing this |
| 59 | # gives up; they are off in deploy/anvil.toml and off by default. Read |
| 60 | # docs/untrusted-mode.md before putting the mount back. |
| 61 | volumes: |
| 62 | - anvil-data:/data |
| 63 | |
| 64 | networks: |
| 65 | - hagrid |
| 66 | |
| 67 | volumes: |
| 68 | # `name:` pins the volume to the exact name the pre-compose deploys used, so |
| 69 | # this adopts the existing SQLite DB, bare repos and SSH host key rather than |
| 70 | # coming up against an empty `anvil_anvil-data` that compose would otherwise |
| 71 | # derive from the project name. A named volume (not a bind mount) keeps it |
| 72 | # owned by the in-container `anvil` user. |
| 73 | anvil-data: |
| 74 | name: anvil-data |
| 75 | # (Compose warns that it did not create this volume, then adopts it. That |
| 76 | # is the intended path off the `docker run` deploys; `external: true` |
| 77 | # would silence it but break a first install on a fresh host.) |
| 78 | |
| 79 | # Caddy runs on this network and reverse-proxies to the container by name. |
| 80 | # The hagrid repo owns the network's lifecycle. |
| 81 | networks: |
| 82 | hagrid: |
| 83 | external: true |