feat(deploy): add compose.yml for home-ctr-onyx (#29)

Consumes the image from #28 with the platform-contract bindings:
/mnt/quartermaster -> /data, QUARTERMASTER_DB_URL with four slashes,
proxy-net external, Traefik routed on quartermaster.unbiasedgeek.com
through the platform-owned basicauth + ratelimit middlewares, and the
required tenant / project / managed_by / watchtower-disable labels
for host hygiene. Image tag is parameterised via QUARTERMASTER_TAG
so the Actions workflow (#30) can pin a specific SHA per deploy
without editing the checked-in file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jeff Smith 2026-04-19 17:29:53 -06:00
parent 8ada740774
commit c7f9a56dc8
2 changed files with 74 additions and 0 deletions

View file

@ -111,3 +111,32 @@ tests/ pytest suite
A transaction log that rolls up into `applied` on a per-entry per-month A transaction log that rolls up into `applied` on a per-entry per-month
basis is deferred. Once implemented it may replace the hand-edited applied basis is deferred. Once implemented it may replace the hand-edited applied
field. field.
## Deploy (home-ctr-onyx)
`compose.yml` at the repo root describes the `quartermaster-web`
service. The platform team has already provisioned `/mnt/quartermaster/`
(owned `1000:1000`), the `proxy-net` Docker network, and the
`quartermaster-basicauth@file` + `quartermaster-ratelimit@file` Traefik
middlewares on home-ctr-onyx. See the [platform contract
wiki page](https://forgejo.labbity.unbiasedgeek.com/homelab/homelab-IaC/wiki/PlatformContractQuartermaster)
for the canonical list.
Roll out a new build:
```sh
docker compose pull
docker compose up -d
```
`compose.yml` references the image as
`…/quartermaster:${QUARTERMASTER_TAG:-latest}`. The deploy workflow
writes `QUARTERMASTER_TAG=<git-sha>` to an `.env` file next to
`compose.yml` on the host, so each deploy pins a specific SHA without
editing the checked-in compose file.
**Four-slash gotcha.** `QUARTERMASTER_DB_URL` is
`sqlite:////data/quartermaster.db` — four slashes for an absolute
path. Three would resolve relative to the working directory, and the
SQLite file would NOT land on the bind mount (on next restart the
database would be empty).

45
compose.yml Normal file
View file

@ -0,0 +1,45 @@
services:
quartermaster:
image: forgejo.labbity.unbiasedgeek.com/archeious/quartermaster/quartermaster:${QUARTERMASTER_TAG:-latest}
container_name: quartermaster
restart: unless-stopped
mem_limit: 1g
memswap_limit: 1g
environment:
QUARTERMASTER_DB_URL: sqlite:////data/quartermaster.db
volumes:
- /mnt/quartermaster:/data
networks:
- proxy-net
healthcheck:
test:
- CMD
- python
- -c
- "import sys, urllib.request; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8000/healthz', timeout=3).status == 200 else 1)"
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
logging:
driver: json-file
options:
max-size: 50m
max-file: "3"
labels:
- "tenant=quartermaster"
- "project=quartermaster"
- "managed_by=quartermaster"
- "com.centurylinklabs.watchtower.enable=false"
- "traefik.enable=true"
- "traefik.docker.network=proxy-net"
- "traefik.http.routers.quartermaster.rule=Host(`quartermaster.unbiasedgeek.com`)"
- "traefik.http.routers.quartermaster.entrypoints=websecure"
- "traefik.http.routers.quartermaster.tls=true"
- "traefik.http.routers.quartermaster.tls.certresolver=letsencrypt"
- "traefik.http.routers.quartermaster.middlewares=quartermaster-basicauth@file,quartermaster-ratelimit@file"
- "traefik.http.services.quartermaster.loadbalancer.server.port=8000"
networks:
proxy-net:
external: true