fix: docs pages, navbar, footer updates from QA sprint

This commit is contained in:
Krystie
2026-08-12 17:34:14 -07:00
parent a3648f66d8
commit ee4066f19c
6 changed files with 1178 additions and 200 deletions
+334 -52
View File
@@ -10,16 +10,27 @@ export default function DocsFirstServicePage() {
title="Deploy Your First Service"
intro="This is where DashCaddy becomes real: take an app from a template, an existing container, or a raw target port to a DNS-backed, reverse-proxied, HTTPS-enabled service visible in one dashboard — in a few clicks."
>
<h2>Prerequisites</h2>
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg">
<p className="text-surface-300">
<strong className="text-brand-400">Before you begin:</strong> Complete the <a href="/docs/installation" className="text-brand-400 hover:text-brand-300 underline">Installation Guide</a> first. You need a running DashCaddy instance with the dashboard accessible, the API responding on <code>/healthz</code>, and Caddy's Admin API reachable. Technitium DNS is recommended but optional — services will still deploy without it using direct IP access.
</p>
</blockquote>
<h2>What DashCaddy handles for you</h2>
<p>When you deploy a service, DashCaddy automates the full infrastructure chain:</p>
<ul>
<li>Container deployment (from template) or adoption of an existing container.</li>
<li>Service record creation in the DashCaddy state store.</li>
<li>DNS record creation through Technitium DNS (when configured).</li>
<li>Caddy reverse-proxy route configuration via the Admin API.</li>
<li>Automatic TLS certificate issuance through Caddy&apos;s internal CA / DashCA.</li>
<li>Real-time health tracking and WebSocket status updates on the dashboard.</li>
<li>Container deployment (from template) or adoption of an existing container</li>
<li>Service record creation in the DashCaddy state store</li>
<li>DNS record creation through Technitium DNS (when configured)</li>
<li>Caddy reverse-proxy route configuration via the Admin API</li>
<li>Automatic TLS certificate issuance through Caddy's internal CA / DashCA</li>
<li>Real-time health tracking and WebSocket status updates on the dashboard</li>
</ul>
<p>
You provide the intent (which app, which hostname), and DashCaddy coordinates every layer atomically.
If any step fails, the operation rolls back cleanly you never end up with a half-wired service.
</p>
<h2>Three ways to add a service</h2>
@@ -29,69 +40,340 @@ export default function DocsFirstServicePage() {
databases, note apps, automation tools, and more. Each template bundles sane defaults for ports,
volumes, environment variables, and the recommended subdomain.
</p>
<ol>
<li>Open the dashboard and choose <strong>New Service From Template</strong>.</li>
<li>Browse or search the 76+ templates.</li>
<li>Select an app and confirm the service name, hostname, and any required secrets.</li>
<li>Click <strong>Deploy</strong>. DashCaddy pulls the image, starts the container, and wires DNS + Caddy + TLS automatically.</li>
</ol>
<h3>2. Use Service Discovery to auto-detect existing containers</h3>
<p>
Already running Docker containers? DashCaddy&apos;s <strong>Service Discovery</strong> scans the host and lists
Already running Docker containers? DashCaddy's <strong>Service Discovery</strong> scans the host and lists
every running container, marking any that are not yet managed.
</p>
<ol>
<li>Open <strong>Service Discovery</strong> from the sidebar.</li>
<li>Review the list of detected containers.</li>
<li>For each one you want to manage, click <strong>Adopt</strong>.</li>
<li>Provide a hostname/subdomain. DashCaddy generates the Caddy route, DNS record, and certificate.</li>
</ol>
<h3>3. Define a service manually</h3>
<p>
For custom images or apps not in the template library, define the service by hand:
</p>
<ol>
<li>Choose <strong>New Service Custom</strong>.</li>
<li>Provide the container image or the host:port backend target.</li>
<li>Set the hostname/subdomain DashCaddy should publish.</li>
<li>Optionally add environment variables, volumes, and port mappings.</li>
<li>Deploy the same DNS + Caddy + TLS wiring applies.</li>
</ol>
<h2>How Docker + Caddy + DNS wire together</h2>
<p>
The magic is that the three layers are coordinated as a single transaction rather than three manual steps:
</p>
<ol>
<li><strong>Docker</strong> starts (or adopts) the container and exposes the backend port.</li>
<li><strong>DashCaddy</strong> writes a Caddy route mapping your chosen hostname to that backend, then applies it through the Caddyfile-as-Code builder and the Caddy Admin API.</li>
<li><strong>Caddy</strong> automatically requests and renews a TLS certificate for the hostname via its internal CA (or DashCA).</li>
<li><strong>Technitium DNS</strong> creates the A/CNAME record pointing the hostname at the host.</li>
<li>The service appears <strong>Healthy</strong> on the dashboard once the health check passes.</li>
</ol>
<p>
If any layer is not configured (for example, no DNS integration), DashCaddy simply skips that step and
the service still deploys with whatever layers are available.
For custom images or apps not in the template library, define the service by hand with full control
over image, ports, volumes, and environment variables.
</p>
<h2>If the service is internal-only</h2>
<h2>Step-by-step: Deploy Plex</h2>
<p>
For services that should stay on the local network, verify three things:
Let's walk through deploying Plex Media Server using the template library. This is the most common
path for new users and demonstrates the full deployment chain.
</p>
<h3>Step 1: Open the template library</h3>
<p>
From the dashboard sidebar, click <strong>New Service From Template</strong>. The template library
opens with a searchable grid of 76+ applications.
</p>
<h3>Step 2: Find Plex</h3>
<p>
Type "Plex" in the search bar, or browse the "Media" category. Click the Plex template card to
open its configuration form.
</p>
<h3>Step 3: Configure the service</h3>
<p>The form is pre-filled with sensible defaults. Review and adjust:</p>
<ul>
<li>The client device trusts the DashCA root certificate (download it from the DashCA page).</li>
<li>The internal domain resolves properly via Technitium DNS or a local resolver.</li>
<li>The route is reachable on the network you intend to use.</li>
<li><strong>Service name:</strong> <code>plex</code> (used for internal identification)</li>
<li><strong>Hostname:</strong> <code>plex.local</code> (the subdomain DashCaddy will publish)</li>
<li><strong>Container image:</strong> <code>linuxserver/plex:latest</code></li>
<li><strong>Port:</strong> <code>32400</code> (Plex's default web interface port)</li>
<li><strong>Volumes:</strong> <code>/opt/plex/config:/config</code> and <code>/mnt/media:/media</code></li>
<li><strong>Environment variables:</strong> <code>PUID=1000</code>, <code>PGID=1000</code>, <code>VERSION=docker</code></li>
</ul>
<h2>If the service does not come up correctly</h2>
<h3>Step 4: Deploy</h3>
<p>
Debug in order, layer by layer: backend container, backend port reachability, reverse-proxy route, DNS
resolution, TLS trust, then dashboard/API state. See the <a href="/docs/troubleshooting">Troubleshooting</a>
guide for the full checklist.
Click <strong>Deploy</strong>. DashCaddy now executes the full deployment chain:
</p>
<ol>
<li>Pulls the <code>linuxserver/plex:latest</code> Docker image</li>
<li>Creates and starts the container with your configured volumes and environment</li>
<li>Creates a service record in the DashCaddy state store</li>
<li>Generates a Caddy route mapping <code>plex.local</code> → <code>localhost:32400</code></li>
<li>Applies the route through the Caddy Admin API</li>
<li>Requests a TLS certificate for <code>plex.local</code> via DashCA</li>
<li>Creates an A record in Technitium DNS pointing <code>plex.local</code> to your host IP</li>
<li>Starts health checks and reports status on the dashboard</li>
</ol>
<h3>Step 5: Verify</h3>
<p>
Within 30 seconds, the service card on the dashboard should show <strong>Healthy</strong> with a green
status indicator. Click the service to see its detail page, which shows:
</p>
<ul>
<li>Container logs (live-streamed via WebSocket)</li>
<li>Resource usage (CPU, memory, network I/O)</li>
<li>Caddy route configuration</li>
<li>DNS record details</li>
<li>Certificate expiration date</li>
<li>Health check history</li>
</ul>
<h2>Service Discovery: Adopt existing containers</h2>
<p>
If you already have Docker containers running that you want DashCaddy to manage, use Service Discovery
instead of redeploying from scratch.
</p>
<h3>How it works</h3>
<p>
Service Discovery scans the Docker socket and lists every running container on the host. Containers
that are already managed by DashCaddy are marked as "Managed." Unmanaged containers are listed with
their image name, exposed ports, and current status.
</p>
<h3>Adopt a container</h3>
<ol>
<li>Open <strong>Service Discovery</strong> from the sidebar</li>
<li>Review the list of detected containers</li>
<li>For each one you want to manage, click <strong>Adopt</strong></li>
<li>Provide a hostname/subdomain (e.g., <code>grafana.local</code>)</li>
<li>Specify which port to expose (if the container exposes multiple)</li>
<li>Click <strong>Adopt &amp; Configure</strong></li>
</ol>
<p>
DashCaddy creates a service record, generates the Caddy route, DNS record, and certificate — without
restarting or modifying the running container. The container continues running with its existing
configuration; DashCaddy simply adds the proxy and DNS layers on top.
</p>
<h2>Behind the scenes: The deployment chain</h2>
<p>
Understanding what happens during a deployment helps you troubleshoot when things go wrong. Here's
the full chain, layer by layer:
</p>
<h3>1. Docker: Container creation</h3>
<p>
The orchestration layer calls the Docker API to create a container from the specified image. It attaches
the container to the <code>dashcaddy-net</code> bridge network, mounts the configured volumes, and injects
environment variables. The container starts in the background and begins listening on its configured port.
</p>
<h3>2. DashCaddy: Service record</h3>
<p>
A service record is written to the DashCaddy state store (a SQLite database in <code>./data/services.db</code>).
The record includes the service name, hostname, backend port, container ID, deployment timestamp, and
configuration metadata. This record is the source of truth for the dashboard and API.
</p>
<h3>3. Caddy: Reverse proxy route</h3>
<p>
The Caddyfile-as-Code builder generates a route configuration:
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`plex.local {
reverse_proxy localhost:32400
encode gzip
header / {
Strict-Transport-Security "max-age=31536000;"
}
}`}</code></pre>
<p>
This configuration is applied atomically through the Caddy Admin API (<code>POST /load</code>). Caddy
reloads its configuration without downtime and begins routing traffic for <code>plex.local</code> to
<code>localhost:32400</code>.
</p>
<h3>4. DNS: Record creation</h3>
<p>
If Technitium DNS is configured, the orchestration layer calls the Technitium API to create an A record:
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`POST /api/zones/records/create
{
"zone": "local",
"type": "A",
"name": "plex",
"ipAddress": "192.168.1.100"
}`}</code></pre>
<p>
The DNS record propagates immediately (Technitium is authoritative for the <code>local</code> zone).
Clients on your network can now resolve <code>plex.local</code> to your host's IP address.
</p>
<h3>5. TLS: Certificate issuance</h3>
<p>
Caddy's built-in ACME client detects the new hostname and requests a certificate. For internal domains
like <code>plex.local</code>, Caddy uses its internal CA (DashCA) rather than Let's Encrypt. The certificate
is issued, stored in Caddy's data directory, and served automatically for all HTTPS connections to
<code>plex.local</code>.
</p>
<p>
The certificate is valid for 90 days and renewed automatically 30 days before expiration. DashCaddy
tracks certificate expiration dates and surfaces warnings on the dashboard when renewal is approaching.
</p>
<h3>6. Health: Continuous monitoring</h3>
<p>
Once the service is deployed, DashCaddy starts a health check loop that runs every 30 seconds. The health
check performs an HTTP GET to the backend port and expects a 2xx or 3xx response. If the check fails three
times in a row, the service is marked <strong>Unhealthy</strong> on the dashboard and an event is logged.
</p>
<p>
Health status updates are pushed to the dashboard over WebSocket, so you see status changes in real-time
without refreshing the page.
</p>
<h2>Configuration reference</h2>
<p>
When deploying a service, these are the configuration fields available in the deployment form:
</p>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm">
<thead>
<tr className="border-b border-surface-700">
<th className="py-3 pr-4 font-semibold text-surface-200">Field</th>
<th className="py-3 pr-4 font-semibold text-surface-200">Required</th>
<th className="py-3 font-semibold text-surface-200">Description</th>
</tr>
</thead>
<tbody className="text-surface-300">
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Service Name</td>
<td className="py-3 pr-4">Yes</td>
<td className="py-3">Internal identifier (lowercase, no spaces)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Hostname</td>
<td className="py-3 pr-4">Yes</td>
<td className="py-3">Subdomain for the service (e.g., plex.local)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Container Image</td>
<td className="py-3 pr-4">Yes</td>
<td className="py-3">Docker image (e.g., linuxserver/plex:latest)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Backend Port</td>
<td className="py-3 pr-4">Yes</td>
<td className="py-3">Port the container listens on internally</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Volumes</td>
<td className="py-3 pr-4">No</td>
<td className="py-3">Host:container path mappings for persistent storage</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Environment Variables</td>
<td className="py-3 pr-4">No</td>
<td className="py-3">Key-value pairs injected into the container</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Network</td>
<td className="py-3 pr-4">No</td>
<td className="py-3">Docker network to attach (default: dashcaddy-net)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">Restart Policy</td>
<td className="py-3 pr-4">No</td>
<td className="py-3">Container restart behavior (default: unless-stopped)</td>
</tr>
<tr>
<td className="py-3 pr-4 font-mono text-xs">Health Check Path</td>
<td className="py-3 pr-4">No</td>
<td className="py-3">HTTP path for health checks (default: /)</td>
</tr>
</tbody>
</table>
</div>
<h2>Common scenarios</h2>
<h3>Deploy an internal-only service</h3>
<p>
For services that should stay on the local network (not exposed to the internet), use a <code>.local</code>
or <code>.internal</code> TLD. Ensure client devices trust the DashCA root certificate (download it from
the DashCA page in the dashboard). The service will be accessible at <code>https://servicename.local</code>
with a trusted HTTPS connection, but only from devices on your network that have the root cert installed.
</p>
<h3>Deploy a service with custom environment variables</h3>
<p>
When deploying manually or editing a template, you can add custom environment variables in the deployment
form. Each variable is a key-value pair that gets injected into the container at startup. Common examples:
</p>
<ul>
<li><code>PUID=1000</code> / <code>PGID=1000</code> user/group ID for file permissions (LinuxServer images)</li>
<li><code>TZ=America/New_York</code> timezone for log timestamps</li>
<li><code>DB_PASSWORD=secret</code> database credentials for apps like Nextcloud</li>
</ul>
<h3>Deploy multiple services on the same host</h3>
<p>
DashCaddy handles multiple services on the same host automatically. Each service gets a unique subdomain,
and Caddy routes traffic based on the <code>Host</code> header. You can run Plex on <code>plex.local</code>,
Nextcloud on <code>nextcloud.local</code>, and Grafana on <code>grafana.local</code> all on the same
host, all on port 443, with no port conflicts.
</p>
<h3>Adopt a service that's already running</h3>
<p>
If you have a container running outside of DashCaddy (e.g., started manually with <code>docker run</code>),
use Service Discovery to adopt it. DashCaddy will add the proxy and DNS layers without restarting the
container. The container's existing volumes, environment, and network configuration are preserved.
</p>
<h2>Verification checklist</h2>
<p>After deploying a service, verify each layer:</p>
<ol>
<li>
<strong>Container status:</strong> The service card on the dashboard shows <strong>Running</strong> with
a green status indicator
</li>
<li>
<strong>Backend port:</strong> <code>curl http://localhost:32400</code> returns a response from the
application
</li>
<li>
<strong>Caddy route:</strong> <code>curl http://localhost:2019/config/</code> shows a route for your
hostname
</li>
<li>
<strong>DNS resolution:</strong> <code>ping plex.local</code> resolves to your host's IP address
</li>
<li>
<strong>TLS certificate:</strong> <code>curl -v https://plex.local</code> shows a valid certificate
(no warnings if DashCA root is installed)
</li>
<li>
<strong>Health check:</strong> The dashboard shows <strong>Healthy</strong> and the health check
history graph shows consistent success
</li>
</ol>
<h2>Troubleshooting</h2>
<p>If the service does not come up correctly, debug in order, layer by layer:</p>
<ol>
<li><strong>Container:</strong> Check <code>docker logs &lt;container_name&gt;</code> for startup errors</li>
<li><strong>Backend port:</strong> Verify the container is listening on the expected port</li>
<li><strong>Caddy route:</strong> Confirm the route exists in the Caddy Admin API</li>
<li><strong>DNS resolution:</strong> Check that the DNS record was created in Technitium</li>
<li><strong>TLS trust:</strong> Verify the DashCA root certificate is installed on the client device</li>
<li><strong>Dashboard state:</strong> Check the service detail page for error messages or failed health checks</li>
</ol>
<p>
See the <a href="/docs/troubleshooting" className="text-brand-400 hover:text-brand-300 underline">Troubleshooting Guide</a> for
the full checklist and common error patterns.
</p>
<h2>Next steps</h2>
<ul>
<li>
<a href="/docs/overview" className="text-brand-400 hover:text-brand-300 underline">
Product Overview
</a> understand the full architecture and design philosophy
</li>
<li>
Explore the <strong>Template Library</strong> to discover other applications you can deploy
</li>
<li>
Configure <strong>Service Discovery</strong> to adopt existing containers
</li>
<li>
Set up <strong>Prometheus metrics</strong> for external monitoring integration
</li>
</ul>
</DocsLayout>
<Footer />
</div>
+345 -55
View File
@@ -10,90 +10,380 @@ export default function DocsInstallationPage() {
title="Installation Guide"
intro="DashCaddy ships as a Docker-based deployment with a guided installer that handles dependency checks, configuration generation, and first launch. This guide covers prerequisites, the installer flow, and what to expect on first run."
>
<h2>Prerequisites</h2>
<p>Before installing, make sure the host has the following:</p>
<ul>
<li><strong>Docker</strong> and <strong>Docker Compose</strong> the runtime foundation for all DashCaddy services.</li>
<li><strong>Node.js 20+</strong> required for the DashCaddy API server.</li>
<li><strong>Caddy</strong> with Admin API access enabled the reverse proxy and HTTPS layer.</li>
<li><strong>Technitium DNS</strong> optional, but recommended for automatic DNS record management.</li>
<li>A static host or stable IP if you plan to expose services beyond the local network.</li>
</ul>
<h2>System requirements</h2>
<p>Before installing DashCaddy, verify that your host meets these minimum requirements:</p>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm">
<thead>
<tr className="border-b border-surface-700">
<th className="py-3 pr-4 font-semibold text-surface-200">Component</th>
<th className="py-3 pr-4 font-semibold text-surface-200">Minimum</th>
<th className="py-3 font-semibold text-surface-200">Recommended</th>
</tr>
</thead>
<tbody className="text-surface-300">
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Operating System</td>
<td className="py-3 pr-4">Linux (Ubuntu 20.04+, Debian 11+, CentOS 8+)</td>
<td className="py-3">Ubuntu 22.04 LTS or Debian 12</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">CPU</td>
<td className="py-3 pr-4">2 cores</td>
<td className="py-3">4+ cores</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">RAM</td>
<td className="py-3 pr-4">2 GB</td>
<td className="py-3">4+ GB (8 GB for 20+ services)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Disk</td>
<td className="py-3 pr-4">10 GB free</td>
<td className="py-3">50+ GB SSD</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Docker</td>
<td className="py-3 pr-4">20.10+</td>
<td className="py-3">Latest stable</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Docker Compose</td>
<td className="py-3 pr-4">v2.0+</td>
<td className="py-3">Latest stable</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Node.js</td>
<td className="py-3 pr-4">20.x LTS</td>
<td className="py-3">20.x LTS or 22.x LTS</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Caddy</td>
<td className="py-3 pr-4">2.6+ with Admin API</td>
<td className="py-3">Latest stable</td>
</tr>
<tr>
<td className="py-3 pr-4">Technitium DNS</td>
<td className="py-3 pr-4">Optional</td>
<td className="py-3">Latest stable (for auto DNS)</td>
</tr>
</tbody>
</table>
</div>
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg mt-6">
<p className="text-surface-300">
<strong className="text-brand-400">Note:</strong> DashCaddy can run on Windows and macOS for development, but production deployments should target Linux. Docker Desktop works for testing but is not recommended for production workloads.
</p>
</blockquote>
<h2>Quick start with start.sh</h2>
<p>
The fastest path to a running DashCaddy is the bundled <code>start.sh</code> script. It performs environment
checks, pulls the required containers, generates configuration, and brings the stack up.
checks, pulls the required containers, generates configuration, and brings the stack up in a single command.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Clone the repository
git clone https://github.com/samiahmed7777/dashcaddy.git
cd dashcaddy
# Make the launcher executable and run it
chmod +x start.sh
./start.sh`}</code></pre>
<h3>Step 1: Clone the repository</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`git clone https://github.com/samiahmed7777/dashcaddy.git
cd dashcaddy`}</code></pre>
<h3>Step 2: Make the launcher executable</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`chmod +x start.sh`}</code></pre>
<h3>Step 3: Run the installer</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`./start.sh`}</code></pre>
<p>
The script is idempotent re-running it will reconcile the stack rather than clobber an existing install.
If DashCaddy is already running, <code>start.sh</code> detects this and offers to update configuration or
restart services instead of reinstalling from scratch.
</p>
<h2>The guided installer</h2>
<p>
For users who prefer a walk-through, DashCaddy includes a dedicated installer that steps through:
</p>
<h3>What start.sh does</h3>
<p>Under the hood, the script performs these steps:</p>
<ol>
<li><strong>Dependency checks</strong> verifies Docker, Node.js, and Caddy are present and reachable.</li>
<li><strong>Path selection</strong> chooses where state, configs, and certificates are stored.</li>
<li><strong>Configuration generation</strong> writes environment files and Caddy/DNS integration settings.</li>
<li><strong>Container deployment</strong> pulls images and starts the API, dashboard, and supporting services.</li>
<li><strong>First-launch validation</strong> confirms the API responds and the dashboard loads.</li>
<li><strong>Dependency validation</strong> checks for Docker, Docker Compose, Node.js, and Caddy</li>
<li><strong>Port availability check</strong> verifies ports 80, 443, and 2019 (Caddy Admin API) are free</li>
<li><strong>Configuration generation</strong> creates <code>.env</code> file with sensible defaults</li>
<li><strong>Docker image pull</strong> fetches the DashCaddy API and dashboard images</li>
<li><strong>Container startup</strong> launches the stack via Docker Compose</li>
<li><strong>Health check</strong> waits for the API to respond on <code>/healthz</code></li>
<li><strong>Dashboard URL display</strong> prints the access URL and initial admin credentials</li>
</ol>
<h2>First launch &amp; the Smart Defaults Wizard</h2>
<h2>Docker Compose configuration</h2>
<p>
On first launch the dashboard opens to the <strong>Smart Defaults Wizard</strong>. It surveys your host and
pre-fills sensible choices so you can go from install to a working deployment in minutes:
If you prefer to inspect or customize the Docker Compose configuration before launching, here's the
default <code>docker-compose.yml</code> that <code>start.sh</code> generates:
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`version: '3.8'
services:
dashcaddy-api:
image: samiahmed7777/dashcaddy-api:latest
container_name: dashcaddy-api
restart: unless-stopped
ports:
- "3001:3001" # API port
volumes:
- ./data:/app/data
- ./config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- NODE_ENV=production
- DASHCADDY_PORT=3001
- CADDY_ADMIN_URL=http://caddy:2019
- TECHNITIUM_API_URL=http://technitium:5380
- TECHNITIUM_API_TOKEN=\${TECHNITIUM_API_TOKEN}
- JWT_SECRET=\${JWT_SECRET}
- DASHCA_ENABLED=true
depends_on:
- caddy
- technitium
networks:
- dashcaddy-net
dashcaddy-dashboard:
image: samiahmed7777/dashcaddy-dashboard:latest
container_name: dashcaddy-dashboard
restart: unless-stopped
ports:
- "3000:3000" # Dashboard port
environment:
- NEXT_PUBLIC_API_URL=http://localhost:3001
depends_on:
- dashcaddy-api
networks:
- dashcaddy-net
caddy:
image: caddy:2-alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "2019:2019" # Admin API
volumes:
- ./caddy/Caddyfile:/etc/caddy/Caddyfile
- ./caddy/data:/data
- ./caddy/config:/config
networks:
- dashcaddy-net
technitium:
image: technitium/dns-server:latest
container_name: technitium
restart: unless-stopped
ports:
- "5380:5380" # Web console
- "53:53/udp"
- "53:53/tcp"
volumes:
- ./technitium:/etc/dns
environment:
- DNS_SERVER_DOMAIN=local
networks:
- dashcaddy-net
networks:
dashcaddy-net:
driver: bridge`}</code></pre>
<h2>Environment variables reference</h2>
<p>
DashCaddy's behavior is controlled through environment variables in the <code>.env</code> file. Here's
a complete reference:
</p>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm">
<thead>
<tr className="border-b border-surface-700">
<th className="py-3 pr-4 font-semibold text-surface-200">Variable</th>
<th className="py-3 pr-4 font-semibold text-surface-200">Default</th>
<th className="py-3 font-semibold text-surface-200">Description</th>
</tr>
</thead>
<tbody className="text-surface-300">
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">NODE_ENV</td>
<td className="py-3 pr-4">production</td>
<td className="py-3">Runtime environment (development or production)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">DASHCADDY_PORT</td>
<td className="py-3 pr-4">3001</td>
<td className="py-3">Port for the DashCaddy API server</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">CADDY_ADMIN_URL</td>
<td className="py-3 pr-4">http://caddy:2019</td>
<td className="py-3">Caddy Admin API endpoint</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">TECHNITIUM_API_URL</td>
<td className="py-3 pr-4">http://technitium:5380</td>
<td className="py-3">Technitium DNS API endpoint</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">TECHNITIUM_API_TOKEN</td>
<td className="py-3 pr-4">(required)</td>
<td className="py-3">API token for Technitium DNS authentication</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">JWT_SECRET</td>
<td className="py-3 pr-4">(auto-generated)</td>
<td className="py-3">Secret key for JWT token signing</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">DASHCA_ENABLED</td>
<td className="py-3 pr-4">true</td>
<td className="py-3">Enable internal certificate authority</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">BASE_DOMAIN</td>
<td className="py-3 pr-4">local</td>
<td className="py-3">Base domain for service hostnames</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">PROMETHEUS_ENABLED</td>
<td className="py-3 pr-4">true</td>
<td className="py-3">Expose Prometheus metrics at /metrics</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4 font-mono text-xs">LOG_LEVEL</td>
<td className="py-3 pr-4">info</td>
<td className="py-3">Logging verbosity (debug, info, warn, error)</td>
</tr>
<tr>
<td className="py-3 pr-4 font-mono text-xs">DATA_DIR</td>
<td className="py-3 pr-4">./data</td>
<td className="py-3">Path for persistent state storage</td>
</tr>
</tbody>
</table>
</div>
<h2>The Smart Defaults Wizard</h2>
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg">
<p className="text-surface-300">
<strong className="text-brand-400">Smart Defaults Wizard:</strong> On first launch, the dashboard opens to the Smart Defaults Wizard. It surveys your host and pre-fills sensible choices so you can go from install to a working deployment in minutes. Every default is editable — the wizard simply gives you a known-good starting point instead of a blank slate.
</p>
</blockquote>
<p>The wizard performs these tasks automatically:</p>
<ul>
<li>Detects the Caddy Admin API endpoint and validates connectivity.</li>
<li>Detects Technitium DNS (if installed) and configures the API token and zone.</li>
<li>Proposes a base domain and naming convention for new services.</li>
<li>Initializes the internal certificate authority (DashCA) and offers the root certificate for download.</li>
<li>Creates the initial admin account and offers TOTP 2FA enrollment.</li>
<li><strong>Caddy detection</strong> — detects the Caddy Admin API endpoint and validates connectivity</li>
<li><strong>Technitium detection</strong> — detects Technitium DNS (if installed) and configures the API token and zone</li>
<li><strong>Domain suggestion</strong> — proposes a base domain and naming convention for new services</li>
<li><strong>DashCA initialization</strong> — initializes the internal certificate authority and offers the root certificate for download</li>
<li><strong>Admin account creation</strong> — creates the initial admin account and offers TOTP 2FA enrollment</li>
<li><strong>Network scanning</strong> — scans for existing Docker containers and offers to adopt them via Service Discovery</li>
</ul>
<p>
Every default is editable the wizard simply gives you a known-good starting point instead of a blank slate.
</p>
<h2>Manual setup</h2>
<p>
If you want direct control over paths, services, Caddy, and DNS integration, you can deploy manually:
If you want direct control over paths, services, Caddy, and DNS integration, you can deploy manually
instead of using <code>start.sh</code>:
</p>
<ol>
<li>Clone the repository.</li>
<li>Install the API dependencies (<code>npm ci</code>).</li>
<li>Prepare Caddy and confirm the Admin API is reachable.</li>
<li>Prepare Technitium DNS if you want automatic DNS changes.</li>
<li>Configure environment variables and state paths.</li>
<li>Start the DashCaddy API (<code>npm run start</code> or via your process manager).</li>
<li>Serve the dashboard through Caddy.</li>
<li>Clone the repository: <code>git clone https://github.com/samiahmed7777/dashcaddy.git</code></li>
<li>Install the API dependencies: <code>cd dashcaddy && npm ci</code></li>
<li>Prepare Caddy and confirm the Admin API is reachable on port 2019</li>
<li>Prepare Technitium DNS if you want automatic DNS changes (optional)</li>
<li>Copy <code>.env.example</code> to <code>.env</code> and configure environment variables</li>
<li>Start the DashCaddy API: <code>npm run start</code> (or use your process manager like systemd or PM2)</li>
<li>Serve the dashboard through Caddy by adding a reverse proxy rule to your Caddyfile</li>
</ol>
<h2>Post-install checks</h2>
<p>After the stack is up, verify each layer:</p>
<ul>
<li>The dashboard loads in your browser.</li>
<li>The API responds check <code>/healthz</code> and <code>/readyz</code>.</li>
<li>The Caddy Admin API is reachable from the API server.</li>
<li>The service management UI loads and lists the host&apos;s containers.</li>
<li>DNS and certificate integration report healthy (if configured).</li>
<li>Prometheus metrics are exposed at <code>/metrics</code> (if scraping is enabled).</li>
</ul>
<h2>Common installation issues</h2>
<p>If you encounter problems during installation, check this troubleshooting table:</p>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm">
<thead>
<tr className="border-b border-surface-700">
<th className="py-3 pr-4 font-semibold text-surface-200">Symptom</th>
<th className="py-3 pr-4 font-semibold text-surface-200">Cause</th>
<th className="py-3 font-semibold text-surface-200">Solution</th>
</tr>
</thead>
<tbody className="text-surface-300">
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Port 80 or 443 already in use</td>
<td className="py-3 pr-4">Another web server (nginx, Apache) is running</td>
<td className="py-3">Stop the conflicting service or change Caddy's ports in docker-compose.yml</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Docker permission denied</td>
<td className="py-3 pr-4">Current user not in docker group</td>
<td className="py-3">Run <code>sudo usermod -aG docker $USER</code> and log out/in</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Caddy Admin API unreachable</td>
<td className="py-3 pr-4">Caddy not running or Admin API disabled</td>
<td className="py-3">Ensure Caddy is running with <code>admin :2019</code> in its config</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Technitium API token invalid</td>
<td className="py-3 pr-4">Token not set or expired</td>
<td className="py-3">Generate a new token in Technitium web console and update .env</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Dashboard shows 502 Bad Gateway</td>
<td className="py-3 pr-4">API server not responding</td>
<td className="py-3">Check <code>docker logs dashcaddy-api</code> for errors</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Out of memory during deployment</td>
<td className="py-3 pr-4">Insufficient RAM for container workloads</td>
<td className="py-3">Increase host RAM or reduce concurrent service deployments</td>
</tr>
<tr>
<td className="py-3 pr-4">Certificate trust errors in browser</td>
<td className="py-3 pr-4">DashCA root cert not installed on client</td>
<td className="py-3">Download root cert from DashCA page and install on client device</td>
</tr>
</tbody>
</table>
</div>
<h2>Post-install verification</h2>
<p>After the stack is up, verify each layer with these commands:</p>
<h3>1. Check container status</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`docker ps --filter "name=dashcaddy"
# Expected: dashcaddy-api, dashcaddy-dashboard, caddy, technitium all running`}</code></pre>
<h3>2. Verify API health</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`curl http://localhost:3001/healthz
# Expected: {"status":"ok","version":"1.0.0"}
curl http://localhost:3001/readyz
# Expected: {"status":"ready","checks":{"caddy":true,"technitium":true}}`}</code></pre>
<h3>3. Test Caddy Admin API</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`curl http://localhost:2019/config/
# Expected: JSON configuration object`}</code></pre>
<h3>4. Verify Technitium DNS</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`curl http://localhost:5380/api/dns/zones/list?token=YOUR_TOKEN
# Expected: List of DNS zones`}</code></pre>
<h3>5. Check Prometheus metrics</h3>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`curl http://localhost:3001/metrics
# Expected: Prometheus-formatted metrics output`}</code></pre>
<h3>6. Access the dashboard</h3>
<p>Open your browser and navigate to <code>http://localhost:3000</code> (or your configured domain). You should see the DashCaddy dashboard login screen.</p>
<h2>Next steps</h2>
<p>
Once install checks pass, head to the <a href="/docs/first-service">Deploy Your First Service</a> guide to
Once install checks pass, head to the <a href="/docs/first-service" className="text-brand-400 hover:text-brand-300 underline">Deploy Your First Service</a> guide to
bring your first application online.
</p>
<p>
If you need to understand the architecture in more depth, see the <a href="/docs/overview" className="text-brand-400 hover:text-brand-300 underline">Product Overview</a>.
</p>
</DocsLayout>
<Footer />
</div>
+245 -38
View File
@@ -10,81 +10,288 @@ export default function DocsIntegrationsPage() {
title="Infrastructure Integrations"
intro="DashCaddy is most valuable when its supporting integrations are healthy. This guide explains each layer it expects to work with, what it does, and how the pieces fit together into a single control plane."
>
<h2>Docker</h2>
<p>
Docker (and Docker Compose) is the runtime foundation for deployment workflows, container lifecycle actions,
service discovery, and template-based launches. DashCaddy talks to the Docker daemon to start, stop, restart,
inspect, and adopt containers, and to deploy the 76+ one-click application templates. Optional Docker Swarm
support (Premium) extends the same model across multiple nodes.
DashCaddy is not a monolith. It is an orchestration layer that drives several independent infrastructure
components a container runtime, a reverse proxy, a DNS server, a certificate authority, a private network,
a metrics pipeline, and an AI surface. Each integration is swappable, observable, and independently debuggable.
When you understand what each layer is responsible for, you can pinpoint failures in minutes instead of guessing.
</p>
<p>
This guide walks every integration in depth: what it does, how DashCaddy talks to it, the configuration it
expects, and a code example where relevant. Read it end-to-end once, then come back to specific sections when
something goes wrong. For a quick diagnostic flow, see the <a href="/docs/troubleshooting">Troubleshooting</a> guide.
</p>
<h2>Caddy reverse proxy &amp; HTTPS</h2>
<h2>Docker container runtime</h2>
<p>
Caddy is the reverse proxy and automatic HTTPS layer. DashCaddy communicates with the <strong>Caddy Admin API</strong>
to create, update, and remove routes, and to trigger certificate issuance. Caddy&apos;s built-in internal CA
auto-generates and renews certificates for every published service.
Docker (and Docker Compose) is the runtime foundation for every deployment workflow, container lifecycle action,
service discovery sweep, and template-based launch. DashCaddy communicates with the Docker daemon over the
Unix socket (<code>/var/run/docker.sock</code>) to start, stop, restart, inspect, and adopt containers, and to
deploy the <strong>76+ one-click application templates</strong> from the catalog.
</p>
<p>
The daemon connection is established at startup. If the socket is missing or permissioned for a different user,
DashCaddy&apos;s <code>/readyz</code> probe will fail immediately a fast signal that the runtime layer is broken.
During the <strong>Smart Defaults Wizard</strong>, DashCaddy probes the socket, reports the Docker version, and
suggests socket paths if the default is not found.
</p>
<p>
Optional <strong>Docker Swarm</strong> support (Premium) extends the same model across multiple nodes. When
Swarm mode is enabled, DashCaddy switches from single-container operations to service-level operations, managing
placement, replicas, and rolling updates across the cluster. See <a href="/docs/premium">Premium Features</a>.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Verify the Docker socket DashCaddy will use
docker version
ls -l /var/run/docker.sock
# The DashCaddy container needs the socket mounted:
docker run -d \\
-v /var/run/docker.sock:/var/run/docker.sock \\
-p 3000:3000 \\
ghcr.io/dashcaddy/dashcaddy:latest`}</code></pre>
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg">
<p className="text-surface-300">
<strong className="text-brand-400">Note:</strong> Mounting the Docker socket grants full container control.
In production, run DashCaddy behind Tailscale or a firewall so the dashboard is not exposed to the public
internet.
</p>
</blockquote>
<h2>Caddy reverse proxy &amp; automatic HTTPS</h2>
<p>
Caddy is the reverse proxy and automatic HTTPS layer. Every service you publish through DashCaddy gets a Caddy
route that terminates TLS and proxies traffic to the upstream container. DashCaddy communicates with the
<strong> Caddy Admin API</strong> (default <code>localhost:2019</code>) to create, update, and remove routes,
and to trigger certificate issuance on demand.
</p>
<p>
Caddy&apos;s built-in internal CA auto-generates and renews certificates for every published service. For
public domains, Caddy can also use ACME (Let&apos;s Encrypt / ZeroSSL) automatically. The choice between
internal and public CA is made per-service at publish time, so you can mix internet-facing and lab services
on the same host without conflict.
</p>
<h3>Caddyfile-as-Code</h3>
<p>
Instead of hand-editing Caddyfiles, DashCaddy exposes a <strong>visual Caddyfile-as-Code builder</strong>. You
describe the desired route hostname, upstream, TLS options, headers, redirects and DashCaddy generates the
valid Caddy configuration and applies it atomically through the Admin API. Configuration is versioned and
reviewable, so changes are auditable and reversible.
describe the desired route hostname, upstream, TLS options, headers, redirects, compression and DashCaddy
generates the valid Caddy configuration and applies it atomically through the Admin API. Configuration is
versioned and reviewable, so every change is auditable and reversible.
</p>
<p>
The generated config is rendered in the service&apos;s <strong>Caddyfile-as-Code view</strong>, so you can
inspect exactly what Caddy will receive before it is applied. If a route misbehaves, compare the rendered config
against your expectation. Invalid configs are rejected before they reach Caddy, preventing the proxy from
reloading into a broken state.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Example generated Caddyfile (internal CA, lab hostname)
media.lab {
tls internal
<h2>Technitium DNS</h2>
encode zstd gzip
reverse_proxy localhost:8096 {
header_up X-Forwarded-Host {host}
header_up X-Real-IP {remote_host}
}
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options nosniff
}
}`}</code></pre>
<h2>Technitium DNS DNS automation</h2>
<p>
Technitium DNS is the DNS automation target for record creation and removal. When you deploy or adopt a service,
DashCaddy creates the corresponding A/CNAME record through the Technitium API so the new hostname resolves
immediately. Removing a service cleans up the record automatically.
DashCaddy creates the corresponding A or CNAME record through the Technitium REST API so the new hostname
resolves immediately. Removing a service cleans up the record automatically no orphaned DNS entries.
</p>
<p>
DashCaddy needs three pieces of information to drive Technitium: the server URL, an API token with write access
to the target zone, and the zone name itself. All three are configured during the Smart Defaults Wizard or
later under <strong>Settings DNS</strong>. A common failure mode is a token with the wrong scope it can
read records but not create them which fails silently. Always verify the token can write to the zone you
intend to use.
</p>
<p>
Internal zones (e.g. <code>.lab</code>) only resolve if the client uses Technitium as its resolver. Public
resolvers like 8.8.8.8 will not know about them. For remote clients, either point their DNS at Technitium
directly or use <strong>Tailscale</strong> with a MagicDNS / split-DNS setup.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Create a record directly via the Technitium API (debugging)
curl -X POST "http://technitium-host:5380/api/zones/records/add" \\
-d "token=***" \\
-d "zone=lab" \\
-d "domain=media.lab" \\
-d "type=A" \\
-d "ipAddress=192.168.1.50"
# Verify the record resolves through Technitium
dig @technitium-host media.lab +short`}</code></pre>
<h2>DashCA internal certificate authority</h2>
<p>
DashCA is the certificate distribution system that makes internal HTTPS practical. Caddy&apos;s internal CA
issues certificates automatically; DashCA provides the distribution page where you download the root
certificate and install it as a trusted CA across your devices. Once trusted, every internal service is served
over valid HTTPS with no browser warnings.
issues certificates automatically for <code>.lab</code> and other private hostnames; DashCA provides the
distribution page where you download the root certificate and install it as a trusted CA across your devices.
Once trusted, every internal service is served over valid HTTPS with no browser warnings.
</p>
<p>
The root certificate must be installed on <strong>each client device</strong> that will access internal
services not just the server. A macOS laptop, a Windows desktop, and an Android phone each need the cert
installed separately. The DashCA page includes per-platform instructions (macOS Keychain, Windows certmgr,
Linux <code>update-ca-certificates</code>, and mobile profiles) to make this straightforward.
</p>
<p>
After installing the root CA, restart your browser or clear its certificate cache. Chrome and Firefox maintain
separate trust stores on some platforms; Firefox may need the import done from within its own settings.
</p>
<h2>Tailscale private access</h2>
<p>
DashCaddy fits naturally into private access patterns with <strong>Tailscale</strong>. Services can be published
only on a Tailnet, keeping them off the public internet while still benefiting from DashCaddy&apos;s DNS, proxy,
and TLS automation. This is ideal for home labs and internal team tools.
and TLS automation. This is ideal for home labs, internal team tools, and any service that should never be
internet-facing.
</p>
<p>
The typical setup runs Tailscale on the DashCaddy host, advertises the host on the Tailnet, and optionally
enables MagicDNS so Tailnet hostnames resolve without a separate DNS server. Combine with Technitium split-DNS
for the most seamless experience: Technitium handles <code>.lab</code> zones for Tailnet clients, while public
domains resolve normally.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# Install and authenticate Tailscale on the DashCaddy host
curl -fsSL https://tailscale.com/install.sh | sh
tailscale up --advertise-routes=192.168.1.0/24 --accept-routes
<h2>Prometheus &amp; Grafana metrics</h2>
# Verify the host is on the Tailnet
tailscale status
tailscale ip
# From another Tailnet device, reach the service directly
curl -k https://dashcaddy-host.tailnet-name.ts.net/media.lab`}</code></pre>
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg">
<p className="text-surface-300">
<strong className="text-brand-400">Tip:</strong> If you publish services only on the Tailnet, set Caddy to
bind to the Tailscale interface IP rather than <code>0.0.0.0</code>. This guarantees the service is
unreachable from the LAN even if the firewall is misconfigured.
</p>
</blockquote>
<h2>Prometheus &amp; Grafana metrics &amp; observability</h2>
<p>
DashCaddy exports metrics in Prometheus format at <code>/metrics</code>, including service health, container
status, request counts, and system indicators. Point your Prometheus scraper at the endpoint and build
Grafana dashboards on top for long-term observability and alerting.
status, request counts, certificate expiry, and system resource indicators. Point your Prometheus scraper at
the endpoint and build Grafana dashboards on top for long-term observability, capacity planning, and alerting.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# prometheus.yml scrape config
<p>
The metrics endpoint is unauthenticated by default for internal scraping. If your Prometheus instance is on a
different host or network, place it behind the same Tailscale Tailnet or restrict access with a reverse-proxy
basic-auth rule in Caddy.
</p>
<pre className="mt-4 overflow-x-auto rounded-lg border border-surface-700/50 bg-surface-950/80 p-4 text-sm"><code>{`# prometheus.yml — scrape DashCaddy
scrape_configs:
- job_name: 'dashcaddy'
metrics_path: /metrics
static_configs:
- targets: ['dashcaddy-host:3000']`}</code></pre>
<h2>MCP &amp; AI assistants</h2>
- targets: ['dashcaddy-host:3000']
# Optional: increase scrape frequency for faster alerting
scrape_interval: 15s
scrape_timeout: 10s`}</code></pre>
<p>
The built-in <strong>MCP Server</strong> exposes DashCaddy operations to AI assistants and external automation.
Combined with the <strong>AI Intent Router</strong>, you can issue natural-language commands
(&ldquo;restart the media server&rdquo;, &ldquo;deploy the postgres template&rdquo;) and have DashCaddy execute
the real infrastructure action. See the <a href="/docs/api">API and Automation</a> guide for details.
Useful PromQL starters once data is flowing: <code>dashcaddy_service_health == 0</code> (unhealthy services),
<code> rate(dashcaddy_http_requests_total[5m])</code> (request throughput), and
<code>dashcaddy_cert_expiry_days &lt; 14</code> (certificates expiring soon).
</p>
<h2>MCP Server &amp; AI assistants</h2>
<p>
The built-in <strong>MCP (Model Context Protocol) Server</strong> exposes DashCaddy operations to AI assistants
and external automation. Combined with the <strong>AI Intent Router</strong>, you can issue natural-language
commands &ldquo;restart the media server&rdquo;, &ldquo;deploy the postgres template&rdquo;, &ldquo;is the
database healthy?&rdquo; and have DashCaddy execute the real infrastructure action through the standard MCP
tool interface.
</p>
<p>
This turns DashCaddy into an AI-operable control plane: the same operations available in the dashboard are
available as MCP tools, so an assistant like Claude or GPT can inspect and manage your infrastructure directly.
Full setup instructions, the tool catalog, and intent examples are in the <a href="/docs/api">API and Automation</a> guide.
</p>
<h2>How the layers fit together</h2>
<ul>
<li><strong>Deploy / Adopt</strong> Docker runs the container.</li>
<li><strong>Publish</strong> Caddy creates the reverse-proxy route and TLS cert.</li>
<li><strong>Resolve</strong> Technitium DNS creates the hostname record.</li>
<li><strong>Trust</strong> DashCA distributes the root CA for internal HTTPS.</li>
<li><strong>Observe</strong> health checks + Prometheus + WebSocket live updates.</li>
<li><strong>Secure</strong> Security Center aggregates events; audit logging records every change.</li>
</ul>
<p>
The table below maps each integration to the layer it provides and the DashCaddy feature that consumes it.
When a service fails, locate the row whose symptom matches, then debug that integration directly.
</p>
<table>
<thead>
<tr>
<th>Layer</th>
<th>Integration</th>
<th>DashCaddy feature that uses it</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Runtime</strong></td>
<td>Docker / Docker Compose</td>
<td>Deploy, adopt, lifecycle, templates, service discovery</td>
</tr>
<tr>
<td><strong>Proxy</strong></td>
<td>Caddy (Admin API)</td>
<td>Reverse proxy routes, Caddyfile-as-Code, auto HTTPS</td>
</tr>
<tr>
<td><strong>DNS</strong></td>
<td>Technitium DNS</td>
<td>Automatic A/CNAME record creation &amp; cleanup</td>
</tr>
<tr>
<td><strong>Trust</strong></td>
<td>DashCA (internal CA)</td>
<td>Root certificate distribution for internal HTTPS</td>
</tr>
<tr>
<td><strong>Access</strong></td>
<td>Tailscale</td>
<td>Private networking, Tailnet-only publishing</td>
</tr>
<tr>
<td><strong>Observe</strong></td>
<td>Prometheus / Grafana</td>
<td>Metrics export, alerting, long-term dashboards</td>
</tr>
<tr>
<td><strong>Automate</strong></td>
<td>MCP Server + AI Intent Router</td>
<td>Natural-language ops, AI assistant tool surface</td>
</tr>
<tr>
<td><strong>Secure</strong></td>
<td>Security Center + audit log</td>
<td>Event aggregation, change auditing, RBAC</td>
</tr>
</tbody>
</table>
<h2>Operational flow: deploy to observe</h2>
<p>
When everything is wired correctly, a single service publish triggers the full chain automatically:
</p>
<ol>
<li><strong>Deploy / Adopt</strong> Docker runs the container (or adopts an existing one).</li>
<li><strong>Publish</strong> Caddy creates the reverse-proxy route and requests a TLS certificate.</li>
<li><strong>Resolve</strong> Technitium DNS creates the hostname record so the domain resolves.</li>
<li><strong>Trust</strong> DashCA distributes the root CA so clients accept the internal cert.</li>
<li><strong>Observe</strong> health checks, Prometheus metrics, and WebSocket live updates report state.</li>
<li><strong>Secure</strong> Security Center aggregates events; audit logging records every change.</li>
</ol>
<p>
Each step is independently observable. If a service is unreachable, walk the chain in order the first broken
step is your failure. For the full diagnostic procedure, see <a href="/docs/troubleshooting">Troubleshooting</a>.
</p>
</DocsLayout>
<Footer />
</div>
+250 -49
View File
@@ -10,6 +10,13 @@ export default function DocsOverviewPage() {
title="Product Overview"
intro="DashCaddy is a self-hosted control plane for deploying, exposing, and managing Docker applications — with automatic DNS, reverse proxy, internal HTTPS, real-time monitoring, AI-driven operations, and centralized fleet visibility."
>
<h2>What you'll learn</h2>
<blockquote className="border-l-4 border-brand-500/50 bg-brand-500/5 p-4 rounded-r-lg">
<p className="text-surface-300">
<strong className="text-brand-400">What you'll learn:</strong> This page covers the full DashCaddy architecture, design philosophy, component breakdown, and how it compares to manual self-hosting. By the end, you'll understand why DashCaddy exists, what problems it solves, and how its layers work together as a unified platform.
</p>
</blockquote>
<h2>What DashCaddy is</h2>
<p>
DashCaddy brings together the layers that self-hosters usually wire by hand — Docker deployment,
@@ -25,59 +32,253 @@ export default function DocsOverviewPage() {
<h2>Platform architecture</h2>
<p>
DashCaddy is a production-grade platform built on a layered stack:
DashCaddy is a production-grade platform built on eight distinct layers, each responsible for a
specific concern. Together they form a complete self-hosting stack that replaces dozens of manual
configuration steps with a single declarative action.
</p>
<ul>
<li><strong>Application layer</strong> a React dashboard for operators, plus a REST API and WebSocket channel for real-time updates.</li>
<li><strong>Orchestration layer</strong> a Node.js/Express engine that drives deployments, service lifecycle, DNS, reverse proxy, and certificates.</li>
<li><strong>Runtime layer</strong> Docker and Docker Compose for container workloads, with optional Docker Swarm and multi-host fleet support.</li>
<li><strong>Edge layer</strong> Caddy as the reverse proxy and automatic HTTPS termination, managed through its Admin API.</li>
<li><strong>Name resolution layer</strong> Technitium DNS for programmatic record creation and removal.</li>
<li><strong>Trust layer</strong> Caddy&apos;s internal CA and the optional DashCA certificate authority for trusted internal HTTPS.</li>
<li><strong>Observability layer</strong> real-time health checks, Prometheus metrics export, and structured audit logging.</li>
<li><strong>Intelligence layer</strong> an AI Intent Router for natural-language operations and an MCP Server for AI assistant integration.</li>
</ul>
<h2>Core product components</h2>
<ul>
<li><strong>Dashboard</strong> the main operator interface for service visibility, deployment, fleet management, and operational controls.</li>
<li><strong>DashCaddy API</strong> the orchestration engine under <code>/api/v1/</code> for deployments, DNS, reverse proxy, certificates, monitoring, and operational tooling.</li>
<li><strong>Template Library</strong> 76+ one-click Docker application templates covering the most popular self-hosted apps.</li>
<li><strong>Service Discovery</strong> auto-detection of existing containers on the host with one-click adoption into a managed service.</li>
<li><strong>Caddyfile-as-Code</strong> a visual reverse-proxy builder that generates and applies Caddy configuration without manual edits.</li>
<li><strong>DashCA</strong> the internal certificate authority distribution surface for trusted internal HTTPS across devices.</li>
<li><strong>Security Center</strong> a multi-source event pipeline aggregating logs and signals for threat detection and audit.</li>
<li><strong>AI Intent Router</strong> turn natural-language commands into real infrastructure actions.</li>
<li><strong>MCP Server</strong> expose DashCaddy operations to AI assistants and external automation.</li>
<li><strong>Licensing</strong> Premium feature gating tied to external validation and deactivation flows.</li>
</ul>
<h2>Who DashCaddy is for</h2>
<ul>
<li><strong>Home lab operators</strong> who want one place to deploy apps, publish them cleanly, and trust internal HTTPS.</li>
<li><strong>Self-hosters</strong> tired of hand-wiring Docker, Caddy, DNS, and certificates for every new service.</li>
<li><strong>Small teams and businesses</strong> that need multi-user access, RBAC, SSO, and audit trails.</li>
<li><strong>Platform administrators</strong> managing fleets of services across one host or many, with monitoring and backup at the core.</li>
</ul>
<h2>What makes it production-grade</h2>
<ul>
<li><strong>76+ vetted templates</strong> for one-click deployment of popular self-hosted software.</li>
<li><strong>Real-time monitoring</strong> with WebSocket live dashboard updates and Prometheus metrics export.</li>
<li><strong>Multi-user security</strong> TOTP 2FA, email magic-link login, admin invites, RBAC, encrypted credential vault, and audit logging.</li>
<li><strong>Security Center</strong> a multi-source event pipeline for centralized security visibility.</li>
<li><strong>Backup &amp; disaster recovery</strong> one-click backup/restore with SHA-256 checksums for full-system recovery.</li>
<li><strong>Internationalization</strong> 5 supported languages out of the box.</li>
<li><strong>Developer platform</strong> a JavaScript SDK with 39 methods and full TypeScript types, structured error codes (80 codes), and a plugin/extension system.</li>
<li><strong>AI-native</strong> natural-language operations via the Intent Router and AI assistant integration via MCP.</li>
</ul>
<h2>Ownership and licensing</h2>
<h3>1. Application Layer</h3>
<p>
DashCaddy is proprietary software and intellectual property of <strong>samiahmed7777</strong>. Public-facing
documentation and branding reflect that commercial/proprietary positioning rather than an open-source default.
The core platform is fully useful without a license; Premium unlocks a focused set of advanced orchestration features.
The Application Layer is what operators interact with directly. It is a React-based dashboard that
provides real-time visibility into every service, container, and infrastructure component managed by
DashCaddy. Beyond the visual interface, this layer exposes a REST API under <code>/api/v1/</code> and
a WebSocket channel for live updates. Every action available in the UI — deploying a service, editing
a Caddy route, reviewing audit logs — is available through the API, making the dashboard a thin client
over a fully programmable control plane. The application layer also handles authentication, role-based
access control, TOTP two-factor enrollment, and multi-user admin invitations.
</p>
<h3>2. Orchestration Layer</h3>
<p>
The Orchestration Layer is the Node.js/Express engine at the heart of DashCaddy. It receives deployment
requests, coordinates Docker container lifecycle, drives Caddy reverse proxy configuration through the
Admin API, manages Technitium DNS records programmatically, and handles certificate issuance and renewal.
This layer is responsible for ensuring that every deployment is atomic — either all layers succeed or the
operation rolls back cleanly. It maintains the authoritative service state store, tracks health checks,
and publishes events over WebSocket for the dashboard. The orchestration engine also powers the Smart
Defaults Wizard, Service Discovery, and the Caddyfile-as-Code builder.
</p>
<h3>3. Runtime Layer</h3>
<p>
The Runtime Layer is Docker and Docker Compose — the container workloads that actually run your services.
DashCaddy manages container creation, network attachment, volume mounts, environment variable injection,
and lifecycle operations (start, stop, restart, remove). For advanced deployments, the platform supports
Docker Swarm for multi-host orchestration and Fleet Management for coordinating services across multiple
servers. Every container managed by DashCaddy is tracked in the service state store, enabling features
like Service Discovery (adopting existing containers) and Disaster Recovery (full-system backup and restore
with SHA-256 checksum verification).
</p>
<h3>4. Edge Layer</h3>
<p>
The Edge Layer is Caddy — the reverse proxy that terminates HTTPS connections and routes traffic to your
services. DashCaddy manages Caddy entirely through its Admin API, never requiring manual edits to a
Caddyfile. The Caddyfile-as-Code builder generates configuration declaratively, and the orchestration
layer applies changes atomically. Caddy handles automatic TLS certificate issuance and renewal using its
built-in ACME client for public domains or its internal CA for private networks. The Edge Layer also
provides load balancing, header manipulation, request logging, and rate limiting — all configurable
through the DashCaddy dashboard without touching Caddy's native configuration syntax.
</p>
<h3>5. Name Resolution Layer</h3>
<p>
The Name Resolution Layer is Technitium DNS a self-hosted authoritative DNS server that DashCaddy
controls programmatically. When you deploy a service with hostname <code>plex.local</code>, the
orchestration layer creates an A record pointing to your host's IP address automatically. When you
remove the service, the record is cleaned up. This eliminates the manual DNS management that plagues
most self-hosting setups. Technitium DNS also supports zone transfers, forwarding, and custom record
types for advanced networking scenarios. The integration is optional — if you don't configure DNS,
DashCaddy skips this layer and your services still deploy with direct IP access.
</p>
<h3>6. Trust Layer</h3>
<p>
The Trust Layer handles certificate authority management and internal HTTPS distribution. Caddy's built-in
CA issues certificates automatically for every service, but those certificates are only trusted if the
client device trusts the issuing CA. DashCaddy solves this with DashCA — an internal certificate authority
distribution surface. The Smart Defaults Wizard initializes DashCA on first launch and offers the root
certificate for download. Once installed on client devices (browsers, phones, IoT devices), every service
managed by DashCaddy presents a trusted HTTPS connection without certificate warnings. This layer also
handles certificate renewal tracking and expiration alerts.
</p>
<h3>7. Observability Layer</h3>
<p>
The Observability Layer provides real-time health monitoring, structured audit logging, and metrics export.
Every service managed by DashCaddy has a health check that runs continuously, with status updates pushed
to the dashboard over WebSocket. The layer exports Prometheus-compatible metrics at <code>/metrics</code>,
enabling integration with Grafana, VictoriaMetrics, or any Prometheus-compatible monitoring stack. Audit
logs capture every administrative action — who deployed what, when, and from which IP — providing the
accountability required for multi-user environments. The Security Center aggregates logs from multiple
sources (Caddy access logs, container stdout, authentication events) into a unified event pipeline for
threat detection and forensic analysis.
</p>
<h3>8. Intelligence Layer</h3>
<p>
The Intelligence Layer makes DashCaddy AI-native. The AI Intent Router accepts natural-language commands
like "deploy Plex on port 32400" or "show me all unhealthy services" and translates them into API calls.
The MCP (Model Context Protocol) Server exposes DashCaddy operations to external AI assistants — Claude,
ChatGPT, or any MCP-compatible client can deploy services, check health, or modify configuration through
the protocol. This layer also powers the Plugin system, allowing third-party extensions to hook into
DashCaddy's event stream and extend functionality without modifying core code.
</p>
<h2>Design philosophy</h2>
<p>
DashCaddy is built on three principles that guide every architectural decision:
</p>
<ul>
<li>
<strong>Atomic operations:</strong> Deploying a service should succeed or fail as a single transaction.
You should never end up with a container running but no DNS record, or a Caddy route pointing to a
container that doesn't exist. The orchestration layer coordinates all layers and rolls back on failure.
</li>
<li>
<strong>Declarative configuration:</strong> You describe what you want (hostname, port, image), and
DashCaddy figures out the implementation details (Caddy route, DNS record, certificate). The
Caddyfile-as-Code builder generates configuration from your intent, not the other way around.
</li>
<li>
<strong>Progressive disclosure:</strong> The Smart Defaults Wizard gets you running in minutes with
sensible defaults. Advanced users can customize every layer — Caddy headers, DNS record types,
container resource limits — but complexity is optional, not mandatory.
</li>
</ul>
<h2>Comparison: Manual vs. DashCaddy Free vs. DashCaddy Premium</h2>
<div className="overflow-x-auto">
<table className="w-full text-left text-sm">
<thead>
<tr className="border-b border-surface-700">
<th className="py-3 pr-4 font-semibold text-surface-200">Capability</th>
<th className="py-3 pr-4 font-semibold text-surface-200">Manual Setup</th>
<th className="py-3 pr-4 font-semibold text-surface-200">DashCaddy Free</th>
<th className="py-3 font-semibold text-surface-200">DashCaddy Premium</th>
</tr>
</thead>
<tbody className="text-surface-300">
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Docker deployment</td>
<td className="py-3 pr-4">Manual compose files</td>
<td className="py-3 pr-4">76+ one-click templates</td>
<td className="py-3">Templates + Recipes</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Reverse proxy</td>
<td className="py-3 pr-4">Hand-edit Caddyfile</td>
<td className="py-3 pr-4">Caddyfile-as-Code builder</td>
<td className="py-3">Same + fleet-wide routes</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">DNS automation</td>
<td className="py-3 pr-4">Manual record creation</td>
<td className="py-3 pr-4">Technitium integration</td>
<td className="py-3">Same + multi-zone</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">TLS certificates</td>
<td className="py-3 pr-4">Let's Encrypt / manual</td>
<td className="py-3 pr-4">Automatic via Caddy + DashCA</td>
<td className="py-3">Same</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Monitoring</td>
<td className="py-3 pr-4">Custom scripts</td>
<td className="py-3 pr-4">Real-time health + Prometheus</td>
<td className="py-3">Same + fleet dashboard</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Multi-user access</td>
<td className="py-3 pr-4">None</td>
<td className="py-3 pr-4">TOTP 2FA + RBAC</td>
<td className="py-3">SSO (OIDC/SAML)</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Backup &amp; recovery</td>
<td className="py-3 pr-4">Manual snapshots</td>
<td className="py-3 pr-4">One-click backup/restore</td>
<td className="py-3">Same + scheduled</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">AI operations</td>
<td className="py-3 pr-4">None</td>
<td className="py-3 pr-4">Intent Router + MCP Server</td>
<td className="py-3">Same</td>
</tr>
<tr className="border-b border-surface-800">
<td className="py-3 pr-4">Multi-host orchestration</td>
<td className="py-3 pr-4">Manual Swarm/K8s</td>
<td className="py-3 pr-4">Single host</td>
<td className="py-3">Swarm + Fleet Management</td>
</tr>
<tr>
<td className="py-3 pr-4">Pricing</td>
<td className="py-3 pr-4">Time + complexity</td>
<td className="py-3 pr-4">Free forever</td>
<td className="py-3">$20$99 one-time</td>
</tr>
</tbody>
</table>
</div>
<h2>Real-world scenarios</h2>
<h3>Home lab operator</h3>
<p>
You run Plex, Nextcloud, Home Assistant, and a dozen other services on a single NUC. With DashCaddy,
you deploy each from a template, and every service gets a clean subdomain (<code>plex.local</code>,
<code>nextcloud.local</code>) with trusted HTTPS. Service Discovery adopts containers you already
had running, so you don't need to redeploy anything. The dashboard gives you one place to see health,
restart services, and review logs.
</p>
<h3>Small business internal tools</h3>
<p>
Your team needs Gitea, Grafana, and a wiki behind HTTPS with role-based access. DashCaddy Free handles
deployment, DNS, and certificates. TOTP 2FA and multi-user admin ensure only authorized team members
can modify infrastructure. Audit logs track who deployed what and when.
</p>
<h3>Multi-site fleet management</h3>
<p>
You manage DashCaddy instances across three offices. Premium's Fleet Management gives you a single
dashboard to monitor all hosts, deploy services to specific sites, and enforce configuration standards.
Swarm support lets you scale a service across multiple nodes within a site.
</p>
<h2>Premium licensing</h2>
<p>
DashCaddy Premium is a one-time purchase (not a subscription) that unlocks advanced orchestration
features. Pricing tiers:
</p>
<ul>
<li><strong>$20</strong> 30-day license</li>
<li><strong>$50</strong> 90-day license</li>
<li><strong>$70</strong> 180-day license</li>
<li><strong>$99</strong> 365-day license</li>
</ul>
<p>
Premium features include SSO (OIDC/SAML), Recipes (multi-service deployment blueprints), Docker Swarm
orchestration, and Fleet Management for multi-host coordination. The core platform is fully functional
without a license; Premium is for teams that need enterprise-grade access control and multi-site
visibility.
</p>
<h2>Next steps</h2>
<ul>
<li>
<a href="/docs/installation" className="text-brand-400 hover:text-brand-300 underline">
Installation Guide
</a> get DashCaddy running on your host with the guided installer or manual setup.
</li>
<li>
<a href="/docs/first-service" className="text-brand-400 hover:text-brand-300 underline">
Deploy Your First Service
</a> walk through deploying Plex (or any template) end-to-end.
</li>
</ul>
</DocsLayout>
<Footer />
</div>
+2 -3
View File
@@ -51,9 +51,8 @@ export default function Footer() {
<div className="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
{/* Brand Section */}
<div>
<Link href="/" className="flex items-center gap-2 font-bold text-lg text-brand-400 hover:text-brand-300 transition-colors mb-4">
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={28} height={28} className="rounded" />
<span>DashCaddy</span>
<Link href="/" className="flex items-center transition-opacity hover:opacity-80 mb-4">
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={36} height={36} className="rounded" />
</Link>
<p className="text-surface-400 text-sm leading-relaxed mb-4">
Self-hosted Docker dashboard with automatic SSL, DNS, and reverse proxy. Making self-hosting beautiful and effortless.
+2 -3
View File
@@ -19,9 +19,8 @@ export default function Navbar() {
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="flex h-16 items-center justify-between">
{/* Logo */}
<Link href="/" className="flex items-center gap-2 font-bold text-xl text-brand-400 hover:text-brand-300 transition-colors">
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={32} height={32} className="rounded-lg" priority />
<span>DashCaddy</span>
<Link href="/" className="flex items-center transition-opacity hover:opacity-80">
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={40} height={40} className="rounded-lg" priority />
</Link>
{/* Desktop Navigation */}