diff --git a/README.md b/README.md index a073e14..4a8287d 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ cat /etc/os-release Create these A records pointing to your VPS IP: -| Record | Value | -|--------|-------| +| Record | Value | +|-------------------------|------------| | `nextcloud.t-gstone.de` | `` | -| `git.t-gstone.de` | `` | +| `git.t-gstone.de` | `` | ## Quick Start @@ -40,17 +40,17 @@ cp monitoring/.env.example monitoring/.env # - Add Grafana Cloud credentials to monitoring/.env # 4. Deploy -./deploy.sh +./scripts/deploy.sh ``` ## Services -| Service | Subdomain | Stack | -|---------|-----------|-------| -| Nextcloud | `nextcloud.t-gstone.de` | Nextcloud + PostgreSQL 16 + Redis 7 | -| Gitea | `git.t-gstone.de` | Gitea (SQLite) | -| Caddy | — | Reverse proxy, auto HTTPS | -| Monitoring | — | Grafana Alloy -> Grafana Cloud | +| Service | Subdomain | Stack | +|------------|-------------------------|-------------------------------------| +| Nextcloud | `nextcloud.t-gstone.de` | Nextcloud + PostgreSQL 16 + Redis 7 | +| Gitea | `git.t-gstone.de` | Gitea (SQLite) | +| Caddy | — | Reverse proxy, auto HTTPS | +| Monitoring | — | Grafana Alloy -> Grafana Cloud | ## Data Layout @@ -88,9 +88,9 @@ done 1. Create a new directory: `mkdir myapp/` 2. Create `myapp/docker-compose.yml`: - - Join the `proxy` external network - - Bind mount data to `${DATA_ROOT}/myapp/` - - Add `myapp/.env.example` if the service needs secrets + - Join the `proxy` external network + - Bind mount data to `${DATA_ROOT}/myapp/` + - Add `myapp/.env.example` if the service needs secrets 3. Add a reverse proxy entry in `caddy/Caddyfile`: ``` myapp.t-gstone.de { @@ -99,47 +99,51 @@ done ``` 4. Reload Caddy: `docker exec caddy caddy reload --config /etc/caddy/Caddyfile` 5. Add a DNS A record for `myapp.t-gstone.de` -> VPS IP -6. Add data directory creation to `deploy.sh` -7. Add backup steps to `backup.sh` if the service has persistent data +6. Add data directory creation to `scripts/deploy.sh` +7. Add backup steps to `scripts/backup.sh` if the service has persistent data ## Backup & Restore ### Creating Backups ```bash -./backup.sh +./scripts/backup.sh ``` -This dumps the Nextcloud Postgres database, archives Nextcloud data/config and Gitea data, and stores them in `/opt/backups/` with date-stamped filenames. Backups older than 7 days are automatically removed. +This dumps the Nextcloud Postgres database, archives Nextcloud data/config and Gitea data, and stores them in +`/opt/backups/` with date-stamped filenames. Backups older than 7 days are automatically removed. Schedule daily backups: ```bash crontab -e # Add: -0 3 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1 +0 3 * * * /path/to/scripts/backup.sh >> /var/log/backup.log 2>&1 ``` ### Restoring ```bash -./restore.sh 2026-03-22 +./scripts/restore.sh 2026-03-22 ``` -This stops services, restores data from the specified date's backup files, restores the database, and restarts everything. +This stops services, restores data from the specified date's backup files, restores the database, and restarts +everything. ### Backup Strategy Options The current setup stores backups locally on the same VPS. For production use, consider an off-site strategy: -| Option | Pros | Cons | -|--------|------|------| -| **Local only** (`/opt/backups/`) | Simplest, no extra cost | Lost if VPS dies | -| **rsync to second VPS or home server** | Simple, full control | Need a second machine | -| **S3-compatible object storage** (Backblaze B2, Hetzner Object Storage, Wasabi) | Cheap, durable, off-site | Monthly cost (~$0.005/GB) | -| **Restic or BorgBackup** to any remote target | Encrypted, deduplicated, incremental | More setup complexity | +| Option | Pros | Cons | +|---------------------------------------------------------------------------------|--------------------------------------|---------------------------| +| **Local only** (`/opt/backups/`) | Simplest, no extra cost | Lost if VPS dies | +| **rsync to second VPS or home server** | Simple, full control | Need a second machine | +| **S3-compatible object storage** (Backblaze B2, Hetzner Object Storage, Wasabi) | Cheap, durable, off-site | Monthly cost (~$0.005/GB) | +| **Restic or BorgBackup** to any remote target | Encrypted, deduplicated, incremental | More setup complexity | -Recommendation for a personal setup: **Backblaze B2 or Hetzner Object Storage with Restic**. Both offer free egress (B2) or low cost, and Restic handles encryption + deduplication automatically. A cron job running `restic backup` after `backup.sh` completes the pipeline. +Recommendation for a personal setup: **Backblaze B2 or Hetzner Object Storage with Restic**. Both offer free egress (B2) +or low cost, and Restic handles encryption + deduplication automatically. A cron job running `restic backup` after +`backup.sh` completes the pipeline. ## Monitoring @@ -155,13 +159,13 @@ Recommendation for a personal setup: **Backblaze B2 or Hetzner Object Storage wi Set these up in Grafana Cloud UI (**Alerting** -> **Alert rules**): -| Alert | Condition | Severity | -|-------|-----------|----------| -| Disk usage high | `node_filesystem_avail_bytes` / `node_filesystem_size_bytes` < 0.2 | Critical | -| Container restarting | Container restart count > 3 in 10 min | Warning | -| High memory usage | `node_memory_MemAvailable_bytes` / `node_memory_MemTotal_bytes` < 0.1 | Warning | -| High CPU usage | `node_cpu_seconds_total` idle < 10% sustained 5 min | Warning | -| Nextcloud cron stale | No log line from `nextcloud-cron` in 15 min | Warning | +| Alert | Condition | Severity | +|----------------------|-----------------------------------------------------------------------|----------| +| Disk usage high | `node_filesystem_avail_bytes` / `node_filesystem_size_bytes` < 0.2 | Critical | +| Container restarting | Container restart count > 3 in 10 min | Warning | +| High memory usage | `node_memory_MemAvailable_bytes` / `node_memory_MemTotal_bytes` < 0.1 | Warning | +| High CPU usage | `node_cpu_seconds_total` idle < 10% sustained 5 min | Warning | +| Nextcloud cron stale | No log line from `nextcloud-cron` in 15 min | Warning | ### Recommended Dashboards diff --git a/backup.sh b/scripts/backup.sh similarity index 100% rename from backup.sh rename to scripts/backup.sh diff --git a/deploy.sh b/scripts/deploy.sh similarity index 100% rename from deploy.sh rename to scripts/deploy.sh diff --git a/restore.sh b/scripts/restore.sh similarity index 100% rename from restore.sh rename to scripts/restore.sh