4c522961a9
Removes the watchtower container in favour of a host-side script that runs daily at 2:00 AM via systemd timer. Mirrors the _backup pattern: auto-discovers stacks, pulls images, recreates changed containers, prunes dangling images, and notifies via n8n → Telegram. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
105 lines
3.5 KiB
Markdown
105 lines
3.5 KiB
Markdown
# Stacks
|
|
|
|
Self-contained Docker Compose stacks for `pivoine.art` infrastructure.
|
|
|
|
Each stack is independently deployable with its own `compose.yml` and `.env`. All persistent data lives in `../.data/<stack>/`.
|
|
|
|
## Stacks
|
|
|
|
| Stack | Description | Services |
|
|
|---|---|---|
|
|
| `traefik` | Reverse proxy, TLS termination | traefik |
|
|
| `mailpit` | SMTP relay (no web UI) | mailpit |
|
|
| `umami` | Web analytics | umami, db |
|
|
| `immich` | Photo & video management | immich, ml, redis, db |
|
|
| `affine` | Collaborative workspace & notes | affine, redis, db |
|
|
| `n8n` | Workflow automation & notification relay | n8n, db |
|
|
| `gitea` | Git hosting + CI runner | gitea, runner, db |
|
|
| `coolify` | Deployment platform | coolify, realtime, redis, db |
|
|
| `vaultwarden` | Password manager | vaultwarden |
|
|
|
|
## Tools
|
|
|
|
| Directory | Description |
|
|
|---|---|
|
|
| `_backup` | Daily restic backups to HiDrive (host script + systemd timer) |
|
|
| `_update` | Nightly image update check + prune (host script + systemd timer) |
|
|
|
|
## Deployment
|
|
|
|
```bash
|
|
# Copy example env and fill in secrets
|
|
cp <stack>/.env.example <stack>/.env
|
|
|
|
# Sync a stack to VPS
|
|
rsync -avz <stack>/ vps:~/stacks/<stack>/
|
|
|
|
# Start a stack
|
|
ssh vps 'cd ~/stacks/<stack> && docker compose up -d'
|
|
```
|
|
|
|
## Network
|
|
|
|
All stacks share the external `falcon_network` Docker network for inter-service communication (e.g. traefik routing, mailpit SMTP).
|
|
|
|
## Backup
|
|
|
|
The `_backup` stack runs a daily restic backup at 3:00 AM. It dumps all Postgres databases, then backs up the entire `.data/` directory to HiDrive. Retention: 7 daily, 4 weekly, 6 monthly snapshots. Notifications go to Telegram via n8n.
|
|
|
|
```bash
|
|
# Deploy backup stack
|
|
rsync -avz _backup/ vps:~/stacks/_backup/
|
|
|
|
# Initialize restic repo (first time only)
|
|
ssh vps 'source ~/stacks/_backup/.env && restic init -r /mnt/hidrive/users/valknar/Backup/stacks'
|
|
|
|
# Install systemd units
|
|
ssh vps 'ln -sf ~/stacks/_backup/stacks-backup.service /etc/systemd/system/ && \
|
|
ln -sf ~/stacks/_backup/stacks-backup.timer /etc/systemd/system/ && \
|
|
systemctl daemon-reload && systemctl enable --now stacks-backup.timer'
|
|
|
|
# Manual test run
|
|
ssh vps '~/stacks/_backup/backup.sh'
|
|
|
|
# Check timer status
|
|
ssh vps 'systemctl status stacks-backup.timer'
|
|
|
|
# View snapshots
|
|
ssh vps 'source ~/stacks/_backup/.env && restic -r /mnt/hidrive/users/valknar/Backup/stacks snapshots'
|
|
```
|
|
|
|
## Updates
|
|
|
|
The `_update` script runs nightly at 2:00 AM. It pulls the latest image for every stack, recreates any containers whose image changed, prunes dangling images, and sends a Telegram notification via n8n.
|
|
|
|
```bash
|
|
# Deploy update stack
|
|
rsync -avz _update/ vps:~/stacks/_update/
|
|
ssh vps 'chmod +x ~/stacks/_update/update.sh'
|
|
|
|
# Install systemd units
|
|
ssh vps 'ln -sf ~/stacks/_update/stacks-update.service /etc/systemd/system/ && \
|
|
ln -sf ~/stacks/_update/stacks-update.timer /etc/systemd/system/ && \
|
|
systemctl daemon-reload && systemctl enable --now stacks-update.timer'
|
|
|
|
# Manual test run
|
|
ssh vps '~/stacks/_update/update.sh'
|
|
|
|
# Check timer status
|
|
ssh vps 'systemctl status stacks-update.timer'
|
|
```
|
|
|
|
## Notifications
|
|
|
|
The update script and the backup script both POST to an n8n webhook, which forwards messages to Telegram.
|
|
|
|
The webhook URL is set in:
|
|
- `_backup/.env` → `WEBHOOK_URL`
|
|
- `_update/.env` → `WEBHOOK_URL`
|
|
|
|
Both point to the same n8n workflow at `https://n8n.pivoine.art`. The workflow accepts `{ "message": "..." }` and forwards it to Telegram.
|
|
|
|
## Data
|
|
|
|
Persistent data is stored in `~/stacks/.data/<stack>/` on the VPS using bind mounts. Database stacks use dedicated Postgres instances with simple credentials.
|