106 lines
3.2 KiB
Markdown
106 lines
3.2 KiB
Markdown
# VPS Server Structure — Context Prompt for Deployments
|
|
|
|
*Paste this at the start of any new chat where you're deploying or configuring something on the VPS.*
|
|
|
|
---
|
|
|
|
## Machine
|
|
|
|
IONOS VPS, type VPS 6-8-240 (6 vCore, 8 GB RAM, 240 GB NVMe)
|
|
OS: Debian 13 (trixie)
|
|
User: `patsy`
|
|
Domain: `bujour.de` / `bujour.info`
|
|
|
|
## Directory layout
|
|
|
|
```
|
|
/home/patsy/
|
|
├── stacks/ # Docker Compose stacks for infrastructure
|
|
│ ├── caddy/ # Reverse proxy
|
|
│ │ ├── compose.yaml
|
|
│ │ └── Caddyfile
|
|
│ └── forgejo/ # Git server
|
|
└── apps/ # Application source / runtime dirs
|
|
└── checkpoint/ # CheckPoint Ehrenamt app
|
|
```
|
|
|
|
## Running containers
|
|
|
|
| Container | Image | Ports | Network |
|
|
|------------|-------------------------------|------------------------------|---------|
|
|
| caddy | caddy:2 | 80, 443, 443/udp | proxy |
|
|
| forgejo | codeberg.org/forgejo/forgejo:10 | 3000 (internal), 2222 (SSH) | proxy |
|
|
| checkpoint | checkpoint-checkpoint | 8000 (internal) | proxy |
|
|
|
|
## Networking
|
|
|
|
- External Docker network: `proxy` — all containers that need to be reachable via Caddy must join this network
|
|
- Caddy is the only container with public-facing ports (80/443)
|
|
- App containers expose ports internally only (no `host:container` mapping needed)
|
|
|
|
## Caddy routing (~/stacks/caddy/Caddyfile)
|
|
|
|
```
|
|
git.bujour.de {
|
|
reverse_proxy forgejo:3000
|
|
}
|
|
|
|
cpe.bujour.info {
|
|
reverse_proxy checkpoint:8000
|
|
}
|
|
```
|
|
|
|
## Adding a new app — the pattern
|
|
|
|
1. Create `~/apps/<appname>/` for app source/config
|
|
2. Create `~/stacks/<appname>/compose.yaml` — join network `proxy`, expose port internally only
|
|
3. Add a block to `~/stacks/caddy/Caddyfile`: `subdomain.domain.tld { reverse_proxy <appname>:<port> }`
|
|
4. Reload Caddy: `docker exec caddy caddy reload --config /etc/caddy/Caddyfile`
|
|
5. Restart new stack: `cd ~/stacks/<appname> && docker compose up -d`
|
|
|
|
## Caddy compose (~/stacks/caddy/compose.yaml)
|
|
|
|
```yaml
|
|
services:
|
|
caddy:
|
|
image: caddy:2
|
|
container_name: caddy
|
|
restart: unless-stopped
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
- "443:443/udp"
|
|
volumes:
|
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
- caddy_data:/data
|
|
- caddy_config:/config
|
|
networks:
|
|
- proxy
|
|
|
|
volumes:
|
|
caddy_data:
|
|
caddy_config:
|
|
|
|
networks:
|
|
proxy:
|
|
external: true
|
|
```
|
|
|
|
## Shell & scripting rules
|
|
|
|
- Interactive: Bash + fzf (fuzzy history: Ctrl+R, files: Ctrl+T, dirs: Alt+C)
|
|
- All scripts touching the VPS: Bash/POSIX only — never Fish
|
|
- `sudo` required for most system commands (patsy is not root)
|
|
- `ufw` requires `sudo` — `/usr/sbin/` not in default PATH by design
|
|
|
|
## Firewall
|
|
|
|
- UFW active on VPS
|
|
- IONOS hardware firewall also configured (both must be opened for new ports)
|
|
- IONOS web console = emergency recovery path — always keep it accessible
|
|
|
|
## Hard rules (learned the hard way)
|
|
|
|
- Always seed the DB and create the first admin user before considering a deploy done
|
|
- Always verify SSH key access before applying any hardening
|
|
- New ports need opening in **both** UFW and the IONOS firewall panel
|