Template
feat: make "only the app publishes a port" a binding rule
A published database port puts the data on the public internet, and Docker's own iptables rules bypass ufw — the server looks firewalled while the port is open. Previously this was only a comment in compose.yaml, which an agent adding a db service later is free to ignore. Anchored at every point where a service could be added or shipped: - rules/security.md: the rule, the reasoning, and the audit commands - rules/backend.md + architecture SKILL: constraint when picking the data layer - agents/backend-dev.md: non-negotiable for any service it adds - agents/qa-engineer.md: a published port is a Critical finding - skills/deploy: blocking pre-flight audit - compose.yaml: db example now uses expose:, with depends_on healthcheck - docs/DEPLOYMENT.md + README: SSH tunnel instead of publishing for debugging
This commit is contained in:
@@ -435,6 +435,37 @@ docker compose up -d --build # Erststart
|
||||
./scripts/update.sh # neuen Stand ausrollen
|
||||
```
|
||||
|
||||
### Nur der App-Port geht nach außen
|
||||
|
||||
Im Stack veröffentlicht **ausschließlich der App-Service** einen Port, und auch den
|
||||
nur auf Loopback (`127.0.0.1`). Jeder weitere Service — Datenbank, Cache, Queue,
|
||||
Admin-UI — bekommt **keinen `ports:`-Eintrag**. Die Container erreichen sich über
|
||||
den Compose-Netzwerknamen, dafür muss nichts veröffentlicht werden:
|
||||
|
||||
```
|
||||
DATABASE_URL=postgres://user:pass@db:5432/app
|
||||
```
|
||||
|
||||
> `ports: "5432:5432"` bindet auf `0.0.0.0` — die Datenbank steht damit im offenen
|
||||
> Internet, geschützt nur durch ihr Passwort. Und Docker schreibt eigene
|
||||
> iptables-Regeln, die **ufw umgehen**: Der Server sieht abgeschottet aus, während
|
||||
> der Port offen ist. Das ist einer der häufigsten Wege, wie selbst gehostete Stacks
|
||||
> kompromittiert werden.
|
||||
|
||||
Die Regel ist an vier Stellen verankert, damit sie beim Vibe-Coden nicht verloren
|
||||
geht: `rules/security.md` (lädt automatisch beim Bearbeiten von `compose.yaml`), der
|
||||
Backend-Sub-Agent, der QA-Sub-Agent (Verstoß = **Critical**) und der Pre-Flight von
|
||||
`/deploy`, der den Deploy abbricht.
|
||||
|
||||
Prüfen, was wirklich gebunden ist:
|
||||
|
||||
```bash
|
||||
docker compose config | grep -B8 "published:"
|
||||
docker compose ps --format "{{.Service}}\t{{.Ports}}"
|
||||
```
|
||||
|
||||
Zugriff zum Debuggen holst du dir per SSH-Tunnel, nicht per veröffentlichtem Port.
|
||||
|
||||
### Was `update.sh` macht
|
||||
|
||||
```mermaid
|
||||
@@ -555,6 +586,7 @@ Vier Dinge, die nicht offensichtlich sind und je einmal wehtun:
|
||||
|
||||
| Fall | Was passiert |
|
||||
|------|--------------|
|
||||
| Ein DB-Service bekommt `ports: "5432:5432"` | Die Datenbank steht im offenen Internet — und Docker umgeht dabei ufw, der Server *wirkt* nur abgeschottet |
|
||||
| `NEXT_PUBLIC_APP_URL` weicht von der Domain ab | Alle Passkeys scheitern, ohne verwertbare Fehlermeldung |
|
||||
| Port 3000 ist von einem anderen Projekt belegt | Playwright testet still gegen den fremden Server — `E2E_PORT` setzen |
|
||||
| Jemand legt eine `tailwind.config.ts` an | Wird in v4 ignoriert; Tokens gehören in `globals.css` |
|
||||
|
||||
Reference in New Issue
Block a user