From 4a66962f19c134c371383a1f6650894a24006034 Mon Sep 17 00:00:00 2001 From: Hermes Date: Thu, 25 Jun 2026 15:48:09 -0700 Subject: [PATCH] DC-008: add Linux deployment section to CLAUDE.md + fix stale version field Inserts a comprehensive Linux (DNS2 / Contabo VPS) section between the existing Windows docs and the Project Info footer. The new section documents: - Production paths (/opt/dashcaddy/, /var/www/dashcaddy-status/, /etc/dashcaddy/) - Container mount points with the /app/data/ auto-resolve fallback - The three-filesystem frontend trap (source vs live vs build-context) - Common admin commands (Caddyfile reload, logs, rebuild, services.json) - Windows-vs-Linux differences table - Four Linux-specific gotchas (Caddy network_mode host, credentials.json perms, CORS_ORIGINS, TS_AUTHKEY) Also corrects the stale 'Version: 1.0' field to current 1.13.4 and adds the Linux-side default TLD (.home). All existing Windows content preserved verbatim per the LITERAL COPY RULE. --- BACKLOG.md | 5 +-- CLAUDE.md | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 4 deletions(-) diff --git a/BACKLOG.md b/BACKLOG.md index fa547d0..bda2458 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -64,9 +64,10 @@ ## P2 — Polish & DX ### DC-008: Update CLAUDE.md for cross-platform accuracy -- **status:** todo -- **owner:** +- **status:** done +- **owner:** hermes - **details:** CLAUDE.md references Windows-specific paths (C:/caddy/, e:/CaddyCerts/) as if they're universal. DashCaddy runs on Linux (Docker on DNS2) and Windows (SAMI-PC). Document both deployment targets clearly. +- **result:** Added a new "Linux Deployment (DNS2 / Contabo VPS)" section after the existing Windows docs (preserved verbatim) and before the "Project Info" footer. The new section documents: production paths (`/opt/dashcaddy/`, `/var/www/dashcaddy-status/`, `/etc/dashcaddy/`), container mount points with the `/app/data/` auto-resolve fallback, the three-filesystem frontend trap (source vs live vs build-context), common admin commands, a Windows-vs-Linux differences table, and four Linux-specific gotchas (Caddy network_mode host, credentials.json perms, CORS_ORIGINS vs Tailscale, TS_AUTHKEY provisioning). Also updated the "Project Info" version field from stale `1.0` to current `1.13.4` and added the Linux-side default TLD (`.home`). ### DC-009: Add CHANGELOG entry for any unreleased work - **status:** done diff --git a/CLAUDE.md b/CLAUDE.md index cf49bc5..86bbd11 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -222,9 +222,97 @@ DashCA's Caddyfile block (auto-generated on deployment): 3. **DNS server**: DNS2 (100.74.102.61) is PRIMARY, DNS1 is secondary 4. **Caddyfile not reloaded**: After editing, must POST to /load endpoint or restart Caddy +--- + +## Linux Deployment (DNS2 / Contabo VPS) + +The Windows path sections above describe the **SAMI-PC** deployment. DashCaddy also runs as a Docker container on Linux (DNS2 = `194.233.88.206` / Tailscale `100.121.150.22`). The Linux deployment uses a different layout driven by `start.sh` and `docker run` bind mounts. + +### Production paths (Linux) +``` +/opt/dashcaddy/ +├── dashcaddy-api/ # Built image source (rebuilt on update) +│ ├── Dockerfile +│ └── ... +├── status/ # Dashboard frontend SOURCE (build context) +├── credentials.json # Encrypted credentials (mounted to /app/data) +├── .encryption-key # AES key (mounted to /app/data) +└── services.json # Live service list (mounted to /app/data) + +/var/www/dashcaddy-status/ # Dashboard frontend LIVE (served by Caddy) + # Built bundle output from status/ — NOT the source + # tree, NOT the docker build context + +/etc/dashcaddy/ +└── Caddyfile # Active Caddy configuration + +/root/.dashcaddy/ # Per-user state, credentials backup, license +``` + +### Container mount points (Linux) +| Container path | Host path | +|---|---| +| `/app/data/credentials.json` | `/opt/dashcaddy/credentials.json` | +| `/app/data/.encryption-key` | `/opt/dashcaddy/.encryption-key` | +| `/app/data/services.json` | `/opt/dashcaddy/services.json` | +| `/caddyfile` | `/etc/dashcaddy/Caddyfile` | + +Note: the app must auto-resolve both `/app/data/...` AND the older `/app/...` layout (where files mounted directly to `/app/`). The `credential-manager.js` and `crypto-utils.js` modules handle this fallback. This is intentional — fresh installs get `/app/data/`, legacy installs keep working without env-var overrides. + +### Three-filesystem frontend trap (Linux) +The dashboard frontend lives on **three** separate paths that get confused: + +1. **Source** — `/opt/dashcaddy/status/` — what you edit +2. **Live** — `/var/www/dashcaddy-status/` — what Caddy serves to browsers +3. **Build context** — `/opt/dashcaddy/dashcaddy-api/` — what `docker build` uses + +Editing `/opt/dashcaddy/status/index.html` and restarting the container does **nothing** visible until you run the build (which writes to `/var/www/dashcaddy-status/`). Always rebuild + container-recreate together. See the `dashcaddy` skill § Deploy cycle for the exact sequence. + +### Common commands (Linux) +```bash +# Edit Caddyfile then reload (no restart needed) +curl -X POST http://localhost:2019/load \ + -H "Content-Type: text/caddyfile" \ + --data-binary @/etc/dashcaddy/Caddyfile + +# View container logs +docker logs dashcaddy-api --tail 200 + +# Rebuild + restart after API code change +cd /opt/dashcaddy && git pull +cd /opt/dashcaddy/dashcaddy-api && docker build -t dashcaddy-api:local . +docker stop dashcaddy-api && docker rm dashcaddy-api +# (then re-run the container with the mount table above) + +# Edit a service in the live list +vi /opt/dashcaddy/services.json # live-reloaded by the watcher +``` + +### Differences from Windows +| Concern | Windows (SAMI-PC) | Linux (DNS2) | +|---|---|---| +| Drive letter | `C:/`, `E:/` | `/opt/`, `/etc/`, `/var/www/` | +| Network share for state | `\\Sami-pc\e_share` | (none — all local) | +| Docker engine | Docker Desktop on WSL2 | Docker Engine on host | +| Backend admin | PowerShell | bash + curl | +| Caddyfile reload | POST to `localhost:2019/load` | POST to `localhost:2019/load` (same) | +| Caddy admin port | 2019 | 2019 | +| Self-update | host-side PowerShell updater | host-side bash updater (`start.sh`) | +| Tailscale | Same `100.x.x.x` magic DNS | Same | +| DNS server | DNS2 (100.74.102.61) primary | DNS2 (100.121.150.22 / 194.233.88.206) — **is** the primary | + +### Linux-specific gotchas +- **Caddy needs `network_mode: host`** (or `--network host`) so it can bind :80 and :443 directly. Bridge mode + port mapping also works, but `network_mode: host` is simpler for a single-host setup. +- **`credentials.json` permissions matter** — file mode `0600`, owned by the same UID the container runs as. If the host root creates it but the container runs as `node` (uid 1000), the API will fail to read it. Either `chown 1000:1000` or run the container as `--user 0`. +- **Don't use `localhost` in the API's CORS_ORIGINS** — it conflicts with the Tailscale IP. Use the actual `https://dashcaddy` URL. +- **Tailscale cert provisioning** — set `TS_AUTHKEY` in `/etc/dashcaddy/tailscale.env` (mode 0600) before first start. Without it, the magic DNS hostname will resolve but TLS will fail. + +--- + ## Project Info - **Name**: DashCaddy -- **Version**: 1.0 +- **Version**: 1.13.4 (current; CHANGELOG.md `[Unreleased]` tracks the next bump) - **Purpose**: Unified management for Docker + Caddy + DNS -- **Local TLD**: .sami +- **Local TLD (Windows)**: `.sami` +- **Local TLD (Linux, DNS2)**: `.home` (default; configurable via `siteConfig.tld`)