From 414c962d3c7e909b3f659ecc1f8c91dc644e391d Mon Sep 17 00:00:00 2001 From: Hermes Date: Sat, 15 Aug 2026 03:28:15 -0700 Subject: [PATCH] docs(catalog): audit and fix 10 hallucinations in install guides MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round-1 docs claimed things the code does not do. This commit rewrites all 77 per-template pages + the catalog index to match reality: CORRECTED: - REST API payload shape: was {template, subdomain, port, environment} Real Joi schema (src/utilities/validate.js appDeploy) is {appId, config: {subdomain, port, mediaPath?, plexClaimToken?, ...}} All optional fields now documented per-schema. - Auth methods: was just "Authorization: Bearer" — real middleware accepts three (TOTP session cookie, Authorization: Bearer JWT, X-API-Key header). All three now shown. - Deploy is synchronous: was "poll GET /api/v1/apps/{id}/status" — there is no status endpoint. Response shape documented as {success, containerId, url, message, setupInstructions}. - AI Intent Router: was "starts the deployment" — it returns a structured intent; the caller must POST /api/v1/apps/deploy to actually provision. Documented accurately. - MCP dashcaddy_deploy_app: was treated as full deploy — it only writes the Caddy route + services.json entry, NOT the container. Documented as such with manual docker pull as next step. - Watchtower: was claimed to auto-update every 24h — DashCaddy does NOT poll for new digests. Watchtower is a separate template with default schedule 0 0 4 * * * (cron 04:00). Documented. - Update button: was "Apps → {Name} → Update" — no such endpoint exists. Manual docker pull + restart now documented. - Restore-on-install: was "prompt to restore from snapshot during install" — no such prompt. POST /api/v1/apps/{appId}/restore documented. - Backups: was "default daily snapshot" — backup schedule is configurable via backup-config.json, not "nightly" by default. Volumes ARE included; documented. - Dashboard menu: was "Apps → Catalog" — actual entry is the "App Selector" button on the dashboard home. Documented. - Dashboard URL: status.sami confirmed correct (configurable via dashboardHost). Also fixes default port resolution: was using portList[0].split(":")[0] which leaks "{{PORT}}" literal when the template uses the placeholder. Now uses t.defaultPort (Joi-validated) first, falling back to portList. Build: 78 routes prerender as static, TypeScript clean. --- src/app/docs/catalog/actual-budget/page.tsx | 180 +++++++------- src/app/docs/catalog/adminer/page.tsx | 182 +++++++------- src/app/docs/catalog/airsonic/page.tsx | 194 ++++++++------- src/app/docs/catalog/audiobookshelf/page.tsx | 198 +++++++-------- src/app/docs/catalog/authentik/page.tsx | 192 +++++++-------- src/app/docs/catalog/bazarr/page.tsx | 196 ++++++++------- src/app/docs/catalog/bind9/page.tsx | 195 ++++++++------- src/app/docs/catalog/bookstack/page.tsx | 202 ++++++++------- src/app/docs/catalog/calibre-web/page.tsx | 206 ++++++++-------- src/app/docs/catalog/changedetection/page.tsx | 180 +++++++------- src/app/docs/catalog/coredns/page.tsx | 184 +++++++------- src/app/docs/catalog/crowdsec/page.tsx | 185 +++++++------- src/app/docs/catalog/dashca/page.tsx | 181 +++++++------- src/app/docs/catalog/digital-clock/page.tsx | 176 ++++++------- src/app/docs/catalog/dozzle/page.tsx | 181 +++++++------- src/app/docs/catalog/drone/page.tsx | 193 +++++++-------- src/app/docs/catalog/emby/page.tsx | 207 ++++++++-------- src/app/docs/catalog/excalidraw/page.tsx | 180 +++++++------- src/app/docs/catalog/filebrowser/page.tsx | 182 +++++++------- src/app/docs/catalog/gitea/page.tsx | 192 +++++++-------- src/app/docs/catalog/grafana/page.tsx | 185 +++++++------- src/app/docs/catalog/homarr/page.tsx | 184 +++++++------- src/app/docs/catalog/homeassistant/page.tsx | 186 +++++++------- src/app/docs/catalog/homepage/page.tsx | 182 +++++++------- src/app/docs/catalog/immich/page.tsx | 199 ++++++++------- src/app/docs/catalog/it-tools/page.tsx | 180 +++++++------- src/app/docs/catalog/jdownloader/page.tsx | 183 +++++++------- src/app/docs/catalog/jellyfin/page.tsx | 203 +++++++-------- src/app/docs/catalog/jenkins/page.tsx | 180 +++++++------- src/app/docs/catalog/kavita/page.tsx | 196 +++++++-------- src/app/docs/catalog/komga/page.tsx | 200 +++++++-------- src/app/docs/catalog/lidarr/page.tsx | 196 ++++++++------- src/app/docs/catalog/mailserver/page.tsx | 202 ++++++++------- src/app/docs/catalog/matrix/page.tsx | 187 +++++++------- src/app/docs/catalog/mealie/page.tsx | 193 +++++++-------- src/app/docs/catalog/minecraft/page.tsx | 201 ++++++++------- src/app/docs/catalog/mongodb/page.tsx | 187 +++++++------- src/app/docs/catalog/navidrome/page.tsx | 189 +++++++------- src/app/docs/catalog/nextcloud/page.tsx | 193 +++++++-------- src/app/docs/catalog/nodered/page.tsx | 184 +++++++------- src/app/docs/catalog/nzbget/page.tsx | 193 +++++++-------- src/app/docs/catalog/outline/page.tsx | 190 +++++++------- src/app/docs/catalog/page.tsx | 6 +- src/app/docs/catalog/paperless-ngx/page.tsx | 203 ++++++++------- src/app/docs/catalog/photoprism/page.tsx | 192 +++++++-------- src/app/docs/catalog/pihole/page.tsx | 190 +++++++------- src/app/docs/catalog/plex/page.tsx | 233 +++++++++--------- src/app/docs/catalog/portainer/page.tsx | 182 +++++++------- src/app/docs/catalog/postgres/page.tsx | 190 +++++++------- src/app/docs/catalog/powerdns/page.tsx | 203 ++++++++------- src/app/docs/catalog/prowlarr/page.tsx | 192 +++++++-------- src/app/docs/catalog/qbittorrent/page.tsx | 196 ++++++++------- src/app/docs/catalog/radarr/page.tsx | 196 ++++++++------- src/app/docs/catalog/readarr/page.tsx | 196 ++++++++------- src/app/docs/catalog/redis/page.tsx | 180 +++++++------- src/app/docs/catalog/rocketchat/page.tsx | 187 +++++++------- src/app/docs/catalog/roundcube/page.tsx | 189 +++++++------- src/app/docs/catalog/sabnzbd/page.tsx | 193 +++++++-------- src/app/docs/catalog/sami-files/page.tsx | 188 +++++++------- src/app/docs/catalog/seerr/page.tsx | 186 +++++++------- src/app/docs/catalog/sonarr/page.tsx | 196 ++++++++------- src/app/docs/catalog/speedtest/page.tsx | 191 +++++++------- src/app/docs/catalog/standardnotes/page.tsx | 184 +++++++------- src/app/docs/catalog/stirling-pdf/page.tsx | 186 +++++++------- src/app/docs/catalog/syncthing/page.tsx | 192 +++++++-------- src/app/docs/catalog/tautulli/page.tsx | 192 +++++++-------- src/app/docs/catalog/technitium/page.tsx | 191 +++++++------- src/app/docs/catalog/transmission/page.tsx | 193 +++++++-------- src/app/docs/catalog/trilium/page.tsx | 180 +++++++------- src/app/docs/catalog/uptime-kuma/page.tsx | 181 +++++++------- src/app/docs/catalog/valheim/page.tsx | 197 ++++++++------- src/app/docs/catalog/vaultwarden/page.tsx | 188 +++++++------- src/app/docs/catalog/vintage-radio/page.tsx | 184 +++++++------- src/app/docs/catalog/vscode-server/page.tsx | 186 +++++++------- src/app/docs/catalog/watchtower/page.tsx | 193 +++++++-------- src/app/docs/catalog/weather/page.tsx | 176 ++++++------- src/app/docs/catalog/whoami/page.tsx | 178 ++++++------- src/app/docs/catalog/wireguard/page.tsx | 200 ++++++++------- 78 files changed, 7274 insertions(+), 7395 deletions(-) diff --git a/src/app/docs/catalog/actual-budget/page.tsx b/src/app/docs/catalog/actual-budget/page.tsx index fe40fee..888307c 100644 --- a/src/app/docs/catalog/actual-budget/page.tsx +++ b/src/app/docs/catalog/actual-budget/page.tsx @@ -16,111 +16,111 @@ export default function actualBudgetDocsPage() { intro="Privacy-focused budgeting app with envelope budgeting" >
- Category: Productivity - Difficulty: Easy - Docker image: actualbudget/actual-server:latest -
+ Category: Productivity + Difficulty: Easy + Docker image: actualbudget/actual-server:latest + -

What is Actual Budget?

-

Privacy-focused budgeting app with envelope budgeting

-

Actual Budget ships as a self-contained Docker image that DashCaddy provisions with one click. The platform handles the container lifecycle, DNS, reverse proxy, HTTPS certificate, and persistent storage so you can focus on using Actual Budget, not installing it.

+

What is Actual Budget?

+

Privacy-focused budgeting app with envelope budgeting

+

Actual Budget ships as a self-contained Docker image that DashCaddy provisions with one click. DashCaddy handles the container lifecycle, DNS record, Caddy reverse-proxy entry, and HTTPS certificate so you can focus on using Actual Budget, not installing it.

-

Prerequisites

- +

Prerequisites

+ -

Install via the DashCaddy dashboard

-
    -
  1. Sign in at https://status.sami (or your host's dashboard URL).
  2. -
  3. Open Apps → Catalog and select Actual Budget from the Productivity category.
  4. -
  5. Choose your host (or pick Local if you have one host).
  6. -
  7. Fill in any required fields (notably the media library path and any claim token).
  8. -
  9. Click Deploy. DashCaddy will: -
      -
    1. Pull the actualbudget/actual-server:latest image.
    2. -
    3. Create persistent volumes for config and data.
    4. -
    5. Reserve a host port and wire it through Caddy.
    6. -
    7. Issue a Let's Encrypt certificate for budget.<your-domain>.
    8. -
    9. Wait for the container health check (/) to pass.
    10. -
    -
  10. -
  11. After ~30–60 seconds the dashboard will turn the row Running and the URL will become clickable.
  12. -
+

Install via the DashCaddy dashboard

+
    +
  1. Sign in at https://status.sami (or your host's dashboard URL).
  2. +
  3. Click the 📱 App Selector button on the dashboard home page.
  4. +
  5. Pick Actual Budget from the Productivity category.
  6. +
  7. Fill in the deployment form: subdomain (default suggestion: budget), host port (default: 5006).
  8. +
  9. Click Deploy. DashCaddy will pull the image, create persistent volumes, write a Caddy route, create the DNS record, and wait up to 30 seconds for the container's health check (/) to pass.
  10. +
  11. When the dashboard shows the service as Running, the URL (built from your subdomain and configured TLD) is clickable. The deploy API returns a synchronous response with {success, containerId, url, message, setupInstructions} — there is no separate status-poll endpoint; the dashboard updates live.
  12. +
-

Install via the REST API

-

If you script deployments or use the MCP / AI Intent Router, install with:

-
curl -X POST https://your-dashcaddy-host/api/v1/apps/deploy \\
-  -H "Authorization: Bearer $DASHCADDY_API_TOKEN" \\
+

Install via the REST API

+

Authenticate with an API key (or a JWT minted via POST /api/v1/auth/jwt). Send as X-API-Key: dk_... or Authorization: Bearer <jwt>.

+
curl -X POST https://status.sami/api/v1/apps/deploy \\
+  -H "X-API-Key: dk_your_api_key" \\
   -H "Content-Type: application/json" \\
   -d '{
-    "template": "actual-budget",
-    "host": "local",
-    "subdomain": "budget",
-    "port": "{{PORT}}",
-    
-    "labels": { "managed-by": "dashcaddy" }
+    "appId": "actual-budget",
+    "config": {
+      "subdomain": "budget",
+      "port": 5006
+    }
   }'
-

Response returns a deployment ID. Poll GET /api/v1/apps/{id}/status until state === "running".

+

The full body schema is in src/utilities/validate.js (Joi schema appDeploy). All config.* fields except subdomain are optional. Notable options:

+
    +
  • config.port — host port (1–65535). Defaults to the template's defaultPort.
  • +
  • config.mediaPath — host directory to mount as the media library.
  • +
  • config.plexClaimToken — Plex claim token (when the upstream service needs one).
  • +
  • config.useExisting: true + existingContainerId — attach DashCaddy metadata to an already-running container instead of pulling a new image.
  • +
  • config.tailscaleOnly: true — restrict the reverse-proxy entry to your Tailscale network.
  • +
  • config.allowedIPs — array of CIDR ranges allowed past the reverse proxy.
  • +
  • config.createDns: false — skip DNS record creation (use when the subdomain already resolves).
  • +
  • config.resources{memory, cpus} limits applied to the container.
  • +
-

Install via the AI Intent Router

-

From any chat surface wired to DashCaddy's MCP server, just say:

-
-

"Deploy Actual Budget on my home host and expose it at budget.sami"

-
-

The Intent Router will pick the right template, prompt you for any missing fields, and start the deployment.

+

Install via the AI Intent Router (returns a structured intent)

+

The Intent Router returns a structured intent, not a deployed container. To deploy via AI, send natural language to:

+
curl -X POST https://status.sami/api/v1/ai/intent \\
+  -H "X-API-Key: dk_your_api_key" \\
+  -H "Content-Type: application/json" \\
+  -d '{ "message": "Deploy Actual Budget on my home host and expose it at budget.sami" }'
+

The response includes intent, action, parameters, and followup — your client (or the MCP server) must then call POST /api/v1/apps/deploy with those parameters to actually provision the container.

-

Post-install: first-run checklist

-
    -
  1. Create your first budget in the web interface
  2. -
  3. Import transactions from your bank (OFX, QFX, CSV)
  4. -
  5. Set up envelope categories for spending control
  6. -
+

Install via the MCP Server

+

For AI agents (Claude Desktop, Hermes, etc.) configure the MCP server (src/mcp/mcp-server.js) with:

+
DASHCADDY_URL=https://status.sami:3001  # internal API URL, may differ from dashboard URL
+DASHCADDY_API_KEY=dk_your_api_key
+

The server exposes dashcaddy_deploy_app. Note: this tool writes the Caddy route and creates the services.json entry, but it does NOT pull the Docker image or start the container. You must run docker pull actualbudget/actual-server:latest and start the container yourself for the URL to actually serve traffic. For a fully-managed deployment, call POST /api/v1/apps/deploy directly from your agent.

+

Post-install: first-run checklist

+
    +
  1. Create your first budget in the web interface
  2. +
  3. Import transactions from your bank (OFX, QFX, CSV)
  4. +
  5. Set up envelope categories for spending control
  6. +
+

Volumes and persistent data

+

DashCaddy creates these volume mounts in the container spec:

+
    +
  • /opt/actual-budget/data:/data
  • +
+

All paths are host paths (left side) mapped into the container (right side). Restarting the container preserves data; reinstalling the template preserves it unless you explicitly pass config.useExisting: false AND wipe the volume. Bind mounts use the host-path conventions above (e.g. /opt/plex/config becomes a bind mount to the host directory of the same path).

+

Environment variables

+

None. The container runs with its upstream defaults.

These are baked into the template at deploy time and shipped to the container. The deploy handler does NOT allow overriding them via the API payload — to change them you must edit the template definition in dashcaddy-api/src/docker/app-templates.js.

-

Volumes and persistent data

-

DashCaddy creates these volume mounts:

-
    -
  • /opt/actual-budget/data:/data
  • -
-

All paths are absolute host paths; the left side is the container-side mount. Restarting the container never deletes the data; reinstalling the template preserves it unless you explicitly check Wipe data on the deploy form.

+

Updating the image

+

There is no built-in auto-update — DashCaddy does NOT poll for new image digests. To pull a new version:

+
    +
  1. SSH into the DashCaddy host and run docker pull actualbudget/actual-server:latest.
  2. +
  3. Restart the container: docker restart <containerId> (find the ID via GET /api/v1/services or the dashboard).
  4. +
  5. Or deploy Watchtower from this catalog (separate template that polls Docker Hub and updates other containers automatically, default schedule 0 0 4 * * * = 04:00 daily).
  6. +
-

Environment variables

-

None. The container runs with its upstream defaults.

-

Override any of these from the deploy form's Environment panel, or programmatically in the API environment object.

+

Backups

+

The default backup policy includes the entire /app/data/ directory (services, config, credentials, stats) AND all Docker volumes. Backups are scheduled via backup-config.json — the default schedule is configurable, not "nightly" out of the box. To restore on a fresh host, redeploy the same template and then call POST /api/v1/apps/{appId}/restore with a backup ID from GET /api/v1/backups/history.

-

Updating

-

DashCaddy's built-in Watchtower integration will pull actualbudget/actual-server:latest every 24 hours and restart your container with zero downtime if the image digest changes. To force an update immediately, click Apps → Actual Budget → Update.

- -

Backups

-

The config volume for Actual Budget is included in DashCaddy's default nightly snapshot. To restore on a fresh host, redeploy the same template and DashCaddy will prompt to restore from the most recent snapshot during install.

- -

Troubleshooting

-

Common issues with Actual Budget:

-
    -
  • Container won't start: check the dashboard's Logs tab. Most startup failures are permission errors on the media/config volume.
  • - - -
  • Slow first scan: expected for large libraries on first run. Subsequent restarts are fast.
  • -
-

For layer-by-layer diagnostics, see the Troubleshooting guide.

- -

Related services

-

Actual Budget is in the Productivity category. Common pairings:

- - -
-

- Last reviewed against DashCaddy product version in dashcaddy-api/src/docker/app-templates.js. - Template ID: actual-budget. If anything here looks wrong, edit the file and the change will appear in the next docs rebuild. -

+

Troubleshooting

+

Common issues with Actual Budget:

+
    +
  • Container won't start: check the dashboard's Logs panel. Most startup failures are permission errors on the host-path volume.
  • +
  • URL not reachable after deploy: the Caddy route was written but DNS hasn't propagated, or port 80/443 is firewalled. Check GET /api/v1/dns/records and systemctl status caddy on the host.
  • +
  • Health check timeout (deploy returns 30s after start): the container is starting but / is not returning 200. Inspect docker logs <containerId> directly.
  • +
+

For layer-by-layer diagnostics, see the Troubleshooting guide.

+
+

+Template ID: actual-budget. Source: dashcaddy-api/src/docker/app-templates.js. +