gerhards 50ab46dbe1 security: harden remote-access stack (pentest remediation R1-R4)
App layer (R1): bind frps NewProxy to token-owned subdomain (anti-hijack),
default-deny unknown webhook ops, HMAC-verify stripe-stub billing webhook,
enforce bandwidth quota kill-switch (Ping op), least-privilege table grants
(migrations 0002/0003), GOTRUE_PASSWORD_MIN_LENGTH=12.

Infra/net (R2): unpublish internal host ports (kong/pooler/analytics/frps-dash),
read-only docker-socket-proxy for vector (no host breakout), on-demand-TLS
allow-list authorizer, edge-block machine-only webhooks, no-new-privileges on
custom containers.

Secrets (R3): rotate Postgres password (all roles) + frps dashboard; replace
predictable supavisor defaults; secrets externalized to gitignored .env.

Med/Low (R4): security response headers (HSTS/XCTO/XFO/Referrer/Permissions/COOP),
restrict frp proxy_type to http (no open relay), disable destructive redis
commands, tighten frps.toml perms.

No secrets committed; rotated values live only in gitignored .env files.
2026-05-30 10:45:07 +02:00
2026-05-29 17:12:19 +02:00
2026-05-29 17:12:19 +02:00

/docker — linumiq.net remote access stack

Networks

Shared external docker network: edge (created with docker network create edge).

Shared env

/docker/.env — DOMAIN, LE_EMAIL.

Per-service secrets

/docker/<svc>/.env, all chmod 600, owned root:root. See /docker/SECRETS.md for the inventory.

Service inventory (Wave A + Wave B)

Service Compose dir Container name Listens Image
Supabase stack /docker/supabase supabase-* kong :8000, edge :9000 (internal) supabase/* (pinned per compose)
Caddy /docker/caddy caddy :80, :443 caddy:2.10.2-alpine
frps /docker/frps frps :7000 ctrl, :7080 vhost, :7500 dash snowdreamtech/frps:0.65.0
Redis /docker/redis redis :6379 (edge net only) redis:7.2-alpine
stripe-stub /docker/stripe-stub stripe-stub 127.0.0.1:4242 stripe-stub:1.0.0 (local build)
bandwidth-worker /docker/bandwidth-worker bandwidth-worker (no inbound) bandwidth-worker:1.0.0 (local build)

Start order

  1. cd /docker/redis && docker compose --env-file .env up -d
  2. cd /docker/supabase && docker compose up -d
  3. cd /docker/frps && docker compose up -d
  4. cd /docker/caddy && docker compose up -d
  5. cd /docker/stripe-stub && docker compose up -d
  6. cd /docker/bandwidth-worker && docker compose up -d
  7. (later) cd /docker/web && docker compose up -d

Stop order

Reverse of the above. docker compose down per directory.

Edge functions

Mounted from /docker/supabase/volumes/functions/. The main function is a router that reads the first URL path segment as the function name.

  • Via Kong: POST http://127.0.0.1:8000/functions/v1/<name>
  • Direct (intra-edge network, e.g. frps auth plugin): POST http://supabase-edge-functions:9000/<name>

After editing a function, cd /docker/supabase && docker compose restart functions (or up -d functions if env changed).

Wave B specifics

  • frps.toml enables [[httpPlugins]] name="auth" pointing at http://supabase-edge-functions:9000/auth-webhook.
  • supabase-edge-functions reads REDIS_URL from /docker/supabase/.env.
  • bandwidth-worker polls http://frps:7500/api/proxy/http every 60s; deltas go to public.usage_samples and public.tunnels.bytes_used via PostgREST.
S
Description
No description provided
Readme 97 KiB
Languages
Python 49.8%
PLpgSQL 45.5%
Shell 2.8%
Dockerfile 1.9%