Docs: production deployment recipe + Arch gotchas
- README: expand the production section with a full systemd recipe (useradd, chown, uv sync --project, install -d for ReadWritePaths, .env perms 640), a Caddy block, and backup note. - AGENTS.md: add the Arch python-uv package-name note and the root-rooted venv caveat, plus a new "Deploy / production" section documenting the volundr unit, data location, .env perms, and forward-proxy expectations.
This commit is contained in:
@@ -28,6 +28,12 @@ uv run ruff format app tests # apply formatting
|
||||
There is **no `main.py` at the repo root** — the app is the `app` package,
|
||||
entry point `app.main:app`.
|
||||
|
||||
**Arch Linux note:** `uv` ships as `python-uv` (not `uv` or `python3-uv`) so
|
||||
`sudo pacman -S --needed python-uv` is the install command. If you create the
|
||||
venv with `sudo`, the interpreter will provision under `/root/.local/share/uv`
|
||||
and a non-root service user can never execute it; build the venv as the
|
||||
service user (or against a system Python — see README "systemd recipe").
|
||||
|
||||
## Configuration
|
||||
|
||||
All settings come from env vars (or a `.env` file) via `pydantic-settings`,
|
||||
@@ -45,6 +51,30 @@ All settings come from env vars (or a `.env` file) via `pydantic-settings`,
|
||||
lead time, default 60), `BIKE_ADMIN_RENEWAL_MONTHS` (MOT/insurance validity,
|
||||
default 12).
|
||||
|
||||
## Deploy / production
|
||||
|
||||
`deploy/bike_admin.service` is the systemd unit for the production server
|
||||
(volundr). Key points:
|
||||
|
||||
- Runs as the unprivileged `bike` system user (no home dir needed beyond the
|
||||
uv-provisioned interpreter in `/home/bike`.local/share/uv/...).
|
||||
- App data lives next to the checkout: `/opt/bike_admin/data`. The app creates
|
||||
`data/bike_admin.db` on startup, but systemd requires the `ReadWritePaths=`
|
||||
target to exist before start — hence the one-time
|
||||
`sudo install -d -o bike -g bike /opt/bike_admin/data` step (see README).
|
||||
- `.env` at `/opt/bike_admin/.env`, `chown bike:bike` and `chmod 640`.
|
||||
(systemd reads it at ExecStart.)
|
||||
- Hardening kept: `NoNewPrivileges`, `PrivateTmp`, `ProtectSystem=full`,
|
||||
`ProtectHome=true`. Do not remove `ProtectHome` unless the interpreter path
|
||||
moves back to `/home`; `StateDirectory=` is the cleaner alternative for
|
||||
data, but we chose `ReadWritePaths=` to keep data next to the app.
|
||||
|
||||
Caddy (hermodr, on a separate host) reverse-proxies
|
||||
`volundr.local.jakes-asgard.uk` to the app's IP:8000. The app trusts
|
||||
`X-Forwarded-For` (BIKE_ADMIN_TRUST_PROXY defaults true) and uvicorn's
|
||||
`--forwarded-allow-ips` whitelist in the unit governs which proxies it'll
|
||||
accept.
|
||||
|
||||
## Architecture / layout
|
||||
|
||||
- `app/config.py` – `Settings` (pydantic-settings) + `get_settings()` (cached).
|
||||
|
||||
Reference in New Issue
Block a user