Document secrets moved to .env files with Bitwarden fallback

Secrets were removed from the repo and moved to .env files on the
server. Added runbook step for restoring them from USB backup (or
recreating from Bitwarden), updated the protection table in README,
and added architecture note in CLAUDE.md.
This commit is contained in:
2026-04-07 16:47:12 -04:00
parent bc1b1d1232
commit bf02e29fd6
3 changed files with 22 additions and 6 deletions
+1
View File
@@ -16,6 +16,7 @@ Recovery steps are in `RUNBOOK.md`. Repo overview and workflows are in `README.m
- **Minecraft HTTP-only**: HTTPS causes WebSocket/CORS errors with the MCSManager daemon. No cert issued for this domain. - **Minecraft HTTP-only**: HTTPS causes WebSocket/CORS errors with the MCSManager daemon. No cert issued for this domain.
- **SSL cert issuance chicken-and-egg**: On fresh recovery, certs don't exist so SSL confs can't load. The `.hold` pattern moves SSL confs aside, starts nginx with HTTP-only confs, issues certs, then restores SSL confs. - **SSL cert issuance chicken-and-egg**: On fresh recovery, certs don't exist so SSL confs can't load. The `.hold` pattern moves SSL confs aside, starts nginx with HTTP-only confs, issues certs, then restores SSL confs.
- **SELinux is enforcing**: Caused issues with samba (symlinks blocked, parent directory traversal blocked). Don't use symlinks for config files — use the sync-system.sh copy approach instead. - **SELinux is enforcing**: Caused issues with samba (symlinks blocked, parent directory traversal blocked). Don't use symlinks for config files — use the sync-system.sh copy approach instead.
- **Secrets in .env files**: All secrets (DB passwords, API keys, tokens) live in `.env` files under each app's `docker/<app>/` directory on the server. These are gitignored (`**/.env` in root `.gitignore`). The `.env` files are included in the USB backup. If the backup is lost, all secrets can be recreated from Bitwarden. The `system/msmtprc` in the repo has its password REDACTED -- the real one is only on the server.
- **ZFS parent dataset mountpoints**: Pools have parent datasets (e.g., `nextcloud`, `threeteras`) that create mountpoints like `/mnt/nextcloud`. These are empty and expected — do not delete them. - **ZFS parent dataset mountpoints**: Pools have parent datasets (e.g., `nextcloud`, `threeteras`) that create mountpoints like `/mnt/nextcloud`. These are empty and expected — do not delete them.
- **msmtp**: Replaces sendmail for cron MAILTO and smartd email alerts. Configured via `/etc/msmtprc` (Fastmail SMTP). The symlink `/usr/sbin/sendmail -> /usr/bin/msmtp` is set up in recovery step 2. - **msmtp**: Replaces sendmail for cron MAILTO and smartd email alerts. Configured via `/etc/msmtprc` (Fastmail SMTP). The symlink `/usr/sbin/sendmail -> /usr/bin/msmtp` is set up in recovery step 2.
- **hantim-server**: Sister repo with similar nginx/certbot patterns. Located at `~/dev/hantim-server`. Useful as reference for deploy patterns. - **hantim-server**: Sister repo with similar nginx/certbot patterns. Located at `~/dev/hantim-server`. Useful as reference for deploy patterns.
+1
View File
@@ -85,4 +85,5 @@ See [RUNBOOK.md](RUNBOOK.md) for full disaster recovery steps.
| Nextcloud DB (PostgreSQL) | ZFS dataset + `pg_dumpall` + USB | `rsync` from USB | | Nextcloud DB (PostgreSQL) | ZFS dataset + `pg_dumpall` + USB | `rsync` from USB |
| Garage S3 data | 2-node replication + USB | Replication or USB | | Garage S3 data | 2-node replication + USB | Replication or USB |
| Gitea repos + DB | SQLite `.backup` + USB | `rsync` from USB | | Gitea repos + DB | SQLite `.backup` + USB | `rsync` from USB |
| Secrets (.env files) | USB backup + Bitwarden | `rsync` from USB, or recreate from Bitwarden |
| SSL certificates | Re-issued from Let's Encrypt | `./scripts/issue-cert.sh` | | SSL certificates | Re-issued from Let's Encrypt | `./scripts/issue-cert.sh` |
+20 -6
View File
@@ -124,7 +124,21 @@ zpool status # verify pools are ONLINE
rsync -a /mnt/backup/argento/ /opt/argento/ rsync -a /mnt/backup/argento/ /opt/argento/
``` ```
## 8. System configs ## 8. Restore .env files
Secrets are not in the repo -- they live in `.env` files on the server. Restore from USB backup:
```bash
# .env files are backed up alongside app data
# After the rsync in step 7, they should already be in place. Verify:
ls /opt/argento/docker/*/.env
# If USB backup is unavailable (full from-scratch rebuild),
# recreate .env files manually from Bitwarden.
# Each app's compose.yaml or runner-config.yaml references its .env file.
```
## 9. System configs
```bash ```bash
cp /opt/argento/system/docker-daemon.json /etc/docker/daemon.json cp /opt/argento/system/docker-daemon.json /etc/docker/daemon.json
@@ -137,7 +151,7 @@ systemctl restart docker smb smartd
crontab /opt/argento/system/root-crontab crontab /opt/argento/system/root-crontab
``` ```
## 9. Nginx + SSL ## 10. Nginx + SSL
```bash ```bash
# Create shared network # Create shared network
@@ -177,7 +191,7 @@ systemctl enable --now certbot-renew.timer
certbot renew --dry-run certbot renew --dry-run
``` ```
## 10. Docker apps ## 11. Docker apps
Deploy each app (nginx is already running and will return 502 until they start): Deploy each app (nginx is already running and will return 502 until they start):
@@ -193,7 +207,7 @@ done
docker ps # verify all containers are healthy docker ps # verify all containers are healthy
``` ```
## 11. Router ## 12. Router
Set up port forwarding on the home router: Set up port forwarding on the home router:
@@ -203,7 +217,7 @@ Set up port forwarding on the home router:
- 3901 -> 192.168.2.122:3901 (Garage RPC) - 3901 -> 192.168.2.122:3901 (Garage RPC)
- 25500-25600 -> 192.168.2.122:25500-25600 (Minecraft) - 25500-25600 -> 192.168.2.122:25500-25600 (Minecraft)
## 12. DNS ## 13. DNS
CNAME records pointing to the DDNS hostname. These don't need updating when the IP changes -- only the DDNS record does. CNAME records pointing to the DDNS hostname. These don't need updating when the IP changes -- only the DDNS record does.
@@ -216,7 +230,7 @@ CNAME records pointing to the DDNS hostname. These don't need updating when the
| `garage.timothykim.net` | CNAME | `argento.ddns.net` | | `garage.timothykim.net` | CNAME | `argento.ddns.net` |
| `minecraft.thekims.family` | CNAME | `argento.ddns.net` | | `minecraft.thekims.family` | CNAME | `argento.ddns.net` |
## 13. Verify ## 14. Verify
```bash ```bash
curl -I https://nextcloud.timothykim.net curl -I https://nextcloud.timothykim.net