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

@@ -6,3 +6,11 @@ services:
ports: !override ports: !override
- "8080:80" - "8080:80"
environment: !reset {} environment: !reset {}
# Local PEM files are commonly mode 0600 and owned by the host user.
# Production keeps the backend non-root and uses keys owned by UID 10001.
backend:
user: "0:0"
migrate:
user: "0:0"

View File

@@ -42,6 +42,7 @@ services:
start_period: 20s start_period: 20s
networks: networks:
- private - private
- egress
migrate: migrate:
build: build:
@@ -85,3 +86,4 @@ networks:
public: public:
private: private:
internal: true internal: true
egress:

View File

@@ -1,8 +1,9 @@
# Production deployment # Production deployment
This stack exposes only Caddy on ports 80 and 443. PostgreSQL and the FastAPI backend 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 share an internal Docker network. The backend additionally uses a non-published egress
`/api/*` requests to the backend after removing the `/api` prefix. 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 ## 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 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 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/` `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: 2. Start PostgreSQL and apply migrations:
```bash ```bash

View File

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

View File

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