80 lines
3.0 KiB
Markdown
80 lines
3.0 KiB
Markdown
# Production deployment
|
|
|
|
This stack exposes only Caddy on ports 80 and 443. PostgreSQL and the FastAPI backend
|
|
are isolated in the private Docker network. Caddy serves the Vite SPA and proxies public
|
|
`/api/*` requests to the backend after removing the `/api` prefix.
|
|
|
|
## First deployment
|
|
|
|
1. Point the `malenia.space` A record to the VPS public IPv4 address.
|
|
2. Install Docker Engine and the Docker Compose plugin on the VPS. Allow only TCP 22, 80,
|
|
and 443 through the host firewall.
|
|
3. Clone the repository to `/opt/malenia` and create `/opt/malenia/.env` from
|
|
`.env.example`. Set file mode `600` and replace all placeholder values.
|
|
4. Put `private.pem` and `public.pem` in `/opt/malenia/keys`, set `KEYS_DIR=/opt/malenia/keys`
|
|
in `.env`, then grant access only to the backend container user:
|
|
|
|
```bash
|
|
sudo chown -R 10001:10001 /opt/malenia/keys
|
|
sudo chmod 700 /opt/malenia/keys
|
|
sudo chmod 600 /opt/malenia/keys/*.pem
|
|
```
|
|
5. Build and start PostgreSQL, then apply migrations:
|
|
|
|
```bash
|
|
docker compose --env-file .env -f compose.production.yml up -d postgres
|
|
docker compose --env-file .env -f compose.production.yml --profile tools run --rm migrate
|
|
```
|
|
|
|
6. Start the application:
|
|
|
|
```bash
|
|
docker compose --env-file .env -f compose.production.yml up -d --build
|
|
```
|
|
|
|
7. Verify `https://malenia.space/api/health/` and the primary frontend flows.
|
|
|
|
## Releases
|
|
|
|
Before each release, run frontend checks locally. On the VPS, pull the intended revision,
|
|
apply migrations, then rebuild and recreate services:
|
|
|
|
```bash
|
|
git pull --ff-only
|
|
docker compose --env-file .env -f compose.production.yml --profile tools run --rm migrate
|
|
docker compose --env-file .env -f compose.production.yml up -d --build
|
|
```
|
|
|
|
The Pally callback URL is `https://malenia.space/api/payments/pally/result`.
|
|
|
|
## Local production-like test
|
|
|
|
This test uses the same images, API proxying, and rate-limit plugin as production, but
|
|
serves HTTP on `http://localhost:8080`. It does not need a domain, TLS certificate, or VPS.
|
|
|
|
1. Create a local `.env` from `.env.example` and fill the required backend integration
|
|
settings. `POSTGRES_HOST=postgres`, `PRIVATE_KEY_FP=/run/secrets/keys/private.pem`, and
|
|
`PUBLIC_KEY_FP=/run/secrets/keys/public.pem` must remain unchanged. The local `keys/`
|
|
directory must contain both PEM files.
|
|
2. Start PostgreSQL and apply migrations:
|
|
|
|
```bash
|
|
docker compose --env-file .env -f compose.production.yml -f compose.local.yml up -d postgres
|
|
docker compose --env-file .env -f compose.production.yml -f compose.local.yml --profile tools run --rm migrate
|
|
```
|
|
|
|
3. Build and run the stack:
|
|
|
|
```bash
|
|
docker compose --env-file .env -f compose.production.yml -f compose.local.yml up -d --build
|
|
```
|
|
|
|
4. Check the frontend at `http://localhost:8080` and the backend through Caddy at
|
|
`http://localhost:8080/api/health/`.
|
|
|
|
5. Stop the local stack while preserving its database volume:
|
|
|
|
```bash
|
|
docker compose --env-file .env -f compose.production.yml -f compose.local.yml down
|
|
```
|