chore(deploy): adjust local user permissions and Caddy routing blocks

This commit is contained in:
2026-08-17 13:02:35 +07:00
parent 261440c694
commit e2a9a4336b
5 changed files with 67 additions and 46 deletions

View File

@@ -1,8 +1,9 @@
# 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.
share an internal Docker network. The backend additionally uses a non-published egress
network for DNS and outbound requests to Pally and Remnawave. Caddy serves the Vite SPA and
proxies public `/api/*` requests to the backend after removing the `/api` prefix.
## First deployment
@@ -55,7 +56,9 @@ serves HTTP on `http://localhost:8080`. It does not need a domain, TLS certifica
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.
directory must contain both PEM files. The local Compose override runs backend commands as
root only to read host-owned PEM files with mode `0600`; this override must not be used in
production.
2. Start PostgreSQL and apply migrations:
```bash

View File

@@ -20,8 +20,9 @@ malenia.space {
}
@api path /api/*
route @api {
rate_limit {
handle @api {
route {
rate_limit {
zone auth {
match {
path /api/auth/login /api/auth/signup /api/auth/refresh
@@ -58,13 +59,16 @@ malenia.space {
window 1m
ipv6_prefix 64
}
}
}
uri strip_prefix /api
reverse_proxy backend:8000
uri strip_prefix /api
reverse_proxy backend:8000
}
}
root * /srv
try_files {path} /index.html
file_server
handle {
root * /srv
try_files {path} /index.html
file_server
}
}

View File

@@ -11,47 +11,51 @@
}
@api path /api/*
route @api {
rate_limit {
zone auth {
match {
path /api/auth/login /api/auth/signup /api/auth/refresh
handle @api {
route {
rate_limit {
zone auth {
match {
path /api/auth/login /api/auth/signup /api/auth/refresh
}
key {remote_host}
events 10
window 1m
}
key {remote_host}
events 10
window 1m
}
zone checkout {
match {
path /api/orders/checkout
zone checkout {
match {
path /api/orders/checkout
}
key {remote_host}
events 10
window 10m
}
key {remote_host}
events 10
window 10m
}
zone payment_callback {
match {
path /api/payments/pally/result
zone payment_callback {
match {
path /api/payments/pally/result
}
key {remote_host}
events 60
window 1m
}
key {remote_host}
events 60
window 1m
}
zone api {
match {
not path /api/health/
zone api {
match {
not path /api/health/
}
key {remote_host}
events 120
window 1m
}
key {remote_host}
events 120
window 1m
}
}
uri strip_prefix /api
reverse_proxy backend:8000
uri strip_prefix /api
reverse_proxy backend:8000
}
}
root * /srv
try_files {path} /index.html
file_server
handle {
root * /srv
try_files {path} /index.html
file_server
}
}