fix: docs pages, navbar, footer updates from QA sprint
This commit is contained in:
@@ -10,16 +10,27 @@ export default function DocsFirstServicePage() {
|
|||||||
title="Deploy Your First Service"
|
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."
|
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>
|
<h2>What DashCaddy handles for you</h2>
|
||||||
<p>When you deploy a service, DashCaddy automates the full infrastructure chain:</p>
|
<p>When you deploy a service, DashCaddy automates the full infrastructure chain:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Container deployment (from template) or adoption of an existing container.</li>
|
<li>Container deployment (from template) or adoption of an existing container</li>
|
||||||
<li>Service record creation in the DashCaddy state store.</li>
|
<li>Service record creation in the DashCaddy state store</li>
|
||||||
<li>DNS record creation through Technitium DNS (when configured).</li>
|
<li>DNS record creation through Technitium DNS (when configured)</li>
|
||||||
<li>Caddy reverse-proxy route configuration via the Admin API.</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>Automatic TLS certificate issuance through Caddy's internal CA / DashCA</li>
|
||||||
<li>Real-time health tracking and WebSocket status updates on the dashboard.</li>
|
<li>Real-time health tracking and WebSocket status updates on the dashboard</li>
|
||||||
</ul>
|
</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>
|
<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,
|
databases, note apps, automation tools, and more. Each template bundles sane defaults for ports,
|
||||||
volumes, environment variables, and the recommended subdomain.
|
volumes, environment variables, and the recommended subdomain.
|
||||||
</p>
|
</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>
|
<h3>2. Use Service Discovery to auto-detect existing containers</h3>
|
||||||
<p>
|
<p>
|
||||||
Already running Docker containers? DashCaddy'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.
|
every running container, marking any that are not yet managed.
|
||||||
</p>
|
</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>
|
<h3>3. Define a service manually</h3>
|
||||||
<p>
|
<p>
|
||||||
For custom images or apps not in the template library, define the service by hand:
|
For custom images or apps not in the template library, define the service by hand with full control
|
||||||
</p>
|
over image, ports, volumes, and environment variables.
|
||||||
<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.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>If the service is internal-only</h2>
|
<h2>Step-by-step: Deploy Plex</h2>
|
||||||
<p>
|
<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>
|
</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>
|
<ul>
|
||||||
<li>The client device trusts the DashCA root certificate (download it from the DashCA page).</li>
|
<li><strong>Service name:</strong> <code>plex</code> (used for internal identification)</li>
|
||||||
<li>The internal domain resolves properly via Technitium DNS or a local resolver.</li>
|
<li><strong>Hostname:</strong> <code>plex.local</code> (the subdomain DashCaddy will publish)</li>
|
||||||
<li>The route is reachable on the network you intend to use.</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>
|
</ul>
|
||||||
|
|
||||||
<h2>If the service does not come up correctly</h2>
|
<h3>Step 4: Deploy</h3>
|
||||||
<p>
|
<p>
|
||||||
Debug in order, layer by layer: backend container, backend port reachability, reverse-proxy route, DNS
|
Click <strong>Deploy</strong>. DashCaddy now executes the full deployment chain:
|
||||||
resolution, TLS trust, then dashboard/API state. See the <a href="/docs/troubleshooting">Troubleshooting</a>
|
|
||||||
guide for the full checklist.
|
|
||||||
</p>
|
</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 & 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 <container_name></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>
|
</DocsLayout>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,90 +10,380 @@ export default function DocsInstallationPage() {
|
|||||||
title="Installation Guide"
|
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."
|
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>
|
<h2>System requirements</h2>
|
||||||
<p>Before installing, make sure the host has the following:</p>
|
<p>Before installing DashCaddy, verify that your host meets these minimum requirements:</p>
|
||||||
<ul>
|
<div className="overflow-x-auto">
|
||||||
<li><strong>Docker</strong> and <strong>Docker Compose</strong> — the runtime foundation for all DashCaddy services.</li>
|
<table className="w-full text-left text-sm">
|
||||||
<li><strong>Node.js 20+</strong> — required for the DashCaddy API server.</li>
|
<thead>
|
||||||
<li><strong>Caddy</strong> with Admin API access enabled — the reverse proxy and HTTPS layer.</li>
|
<tr className="border-b border-surface-700">
|
||||||
<li><strong>Technitium DNS</strong> — optional, but recommended for automatic DNS record management.</li>
|
<th className="py-3 pr-4 font-semibold text-surface-200">Component</th>
|
||||||
<li>A static host or stable IP if you plan to expose services beyond the local network.</li>
|
<th className="py-3 pr-4 font-semibold text-surface-200">Minimum</th>
|
||||||
</ul>
|
<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>
|
<h2>Quick start with start.sh</h2>
|
||||||
<p>
|
<p>
|
||||||
The fastest path to a running DashCaddy is the bundled <code>start.sh</code> script. It performs environment
|
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>
|
</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
|
<h3>Step 1: Clone the repository</h3>
|
||||||
chmod +x start.sh
|
<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
|
||||||
./start.sh`}</code></pre>
|
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>
|
<p>
|
||||||
The script is idempotent — re-running it will reconcile the stack rather than clobber an existing install.
|
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>
|
</p>
|
||||||
|
|
||||||
<h2>The guided installer</h2>
|
<h3>What start.sh does</h3>
|
||||||
<p>
|
<p>Under the hood, the script performs these steps:</p>
|
||||||
For users who prefer a walk-through, DashCaddy includes a dedicated installer that steps through:
|
|
||||||
</p>
|
|
||||||
<ol>
|
<ol>
|
||||||
<li><strong>Dependency checks</strong> — verifies Docker, Node.js, and Caddy are present and reachable.</li>
|
<li><strong>Dependency validation</strong> — checks for Docker, Docker Compose, Node.js, and Caddy</li>
|
||||||
<li><strong>Path selection</strong> — chooses where state, configs, and certificates are stored.</li>
|
<li><strong>Port availability check</strong> — verifies ports 80, 443, and 2019 (Caddy Admin API) are free</li>
|
||||||
<li><strong>Configuration generation</strong> — writes environment files and Caddy/DNS integration settings.</li>
|
<li><strong>Configuration generation</strong> — creates <code>.env</code> file with sensible defaults</li>
|
||||||
<li><strong>Container deployment</strong> — pulls images and starts the API, dashboard, and supporting services.</li>
|
<li><strong>Docker image pull</strong> — fetches the DashCaddy API and dashboard images</li>
|
||||||
<li><strong>First-launch validation</strong> — confirms the API responds and the dashboard loads.</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>
|
</ol>
|
||||||
|
|
||||||
<h2>First launch & the Smart Defaults Wizard</h2>
|
<h2>Docker Compose configuration</h2>
|
||||||
<p>
|
<p>
|
||||||
On first launch the dashboard opens to the <strong>Smart Defaults Wizard</strong>. It surveys your host and
|
If you prefer to inspect or customize the Docker Compose configuration before launching, here's the
|
||||||
pre-fills sensible choices so you can go from install to a working deployment in minutes:
|
default <code>docker-compose.yml</code> that <code>start.sh</code> generates:
|
||||||
</p>
|
</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>
|
<ul>
|
||||||
<li>Detects the Caddy Admin API endpoint and validates connectivity.</li>
|
<li><strong>Caddy detection</strong> — 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><strong>Technitium detection</strong> — 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><strong>Domain suggestion</strong> — 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><strong>DashCA initialization</strong> — initializes the internal certificate authority and offers the root certificate for download</li>
|
||||||
<li>Creates the initial admin account and offers TOTP 2FA enrollment.</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>
|
</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>
|
<h2>Manual setup</h2>
|
||||||
<p>
|
<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>
|
</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li>Clone the repository.</li>
|
<li>Clone the repository: <code>git clone https://github.com/samiahmed7777/dashcaddy.git</code></li>
|
||||||
<li>Install the API dependencies (<code>npm ci</code>).</li>
|
<li>Install the API dependencies: <code>cd dashcaddy && npm ci</code></li>
|
||||||
<li>Prepare Caddy and confirm the Admin API is reachable.</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.</li>
|
<li>Prepare Technitium DNS if you want automatic DNS changes (optional)</li>
|
||||||
<li>Configure environment variables and state paths.</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 via your process manager).</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.</li>
|
<li>Serve the dashboard through Caddy by adding a reverse proxy rule to your Caddyfile</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<h2>Post-install checks</h2>
|
<h2>Common installation issues</h2>
|
||||||
<p>After the stack is up, verify each layer:</p>
|
<p>If you encounter problems during installation, check this troubleshooting table:</p>
|
||||||
<ul>
|
<div className="overflow-x-auto">
|
||||||
<li>The dashboard loads in your browser.</li>
|
<table className="w-full text-left text-sm">
|
||||||
<li>The API responds — check <code>/healthz</code> and <code>/readyz</code>.</li>
|
<thead>
|
||||||
<li>The Caddy Admin API is reachable from the API server.</li>
|
<tr className="border-b border-surface-700">
|
||||||
<li>The service management UI loads and lists the host's containers.</li>
|
<th className="py-3 pr-4 font-semibold text-surface-200">Symptom</th>
|
||||||
<li>DNS and certificate integration report healthy (if configured).</li>
|
<th className="py-3 pr-4 font-semibold text-surface-200">Cause</th>
|
||||||
<li>Prometheus metrics are exposed at <code>/metrics</code> (if scraping is enabled).</li>
|
<th className="py-3 font-semibold text-surface-200">Solution</th>
|
||||||
</ul>
|
</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>
|
<h2>Next steps</h2>
|
||||||
<p>
|
<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.
|
bring your first application online.
|
||||||
</p>
|
</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>
|
</DocsLayout>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,81 +10,288 @@ export default function DocsIntegrationsPage() {
|
|||||||
title="Infrastructure Integrations"
|
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."
|
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>
|
<p>
|
||||||
Docker (and Docker Compose) is the runtime foundation for deployment workflows, container lifecycle actions,
|
DashCaddy is not a monolith. It is an orchestration layer that drives several independent infrastructure
|
||||||
service discovery, and template-based launches. DashCaddy talks to the Docker daemon to start, stop, restart,
|
components — a container runtime, a reverse proxy, a DNS server, a certificate authority, a private network,
|
||||||
inspect, and adopt containers, and to deploy the 76+ one-click application templates. Optional Docker Swarm
|
a metrics pipeline, and an AI surface. Each integration is swappable, observable, and independently debuggable.
|
||||||
support (Premium) extends the same model across multiple nodes.
|
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>
|
</p>
|
||||||
|
|
||||||
<h2>Caddy — reverse proxy & HTTPS</h2>
|
<h2>Docker — container runtime</h2>
|
||||||
<p>
|
<p>
|
||||||
Caddy is the reverse proxy and automatic HTTPS layer. DashCaddy communicates with the <strong>Caddy Admin API</strong>
|
Docker (and Docker Compose) is the runtime foundation for every deployment workflow, container lifecycle action,
|
||||||
to create, update, and remove routes, and to trigger certificate issuance. Caddy's built-in internal CA
|
service discovery sweep, and template-based launch. DashCaddy communicates with the Docker daemon over the
|
||||||
auto-generates and renews certificates for every published service.
|
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'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 & 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's built-in internal CA auto-generates and renews certificates for every published service. For
|
||||||
|
public domains, Caddy can also use ACME (Let'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>
|
</p>
|
||||||
|
|
||||||
<h3>Caddyfile-as-Code</h3>
|
<h3>Caddyfile-as-Code</h3>
|
||||||
<p>
|
<p>
|
||||||
Instead of hand-editing Caddyfiles, DashCaddy exposes a <strong>visual Caddyfile-as-Code builder</strong>. You
|
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
|
describe the desired route — hostname, upstream, TLS options, headers, redirects, compression — and DashCaddy
|
||||||
valid Caddy configuration and applies it atomically through the Admin API. Configuration is versioned and
|
generates the valid Caddy configuration and applies it atomically through the Admin API. Configuration is
|
||||||
reviewable, so changes are auditable and reversible.
|
versioned and reviewable, so every change is auditable and reversible.
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
The generated config is rendered in the service'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>
|
<p>
|
||||||
Technitium DNS is the DNS automation target for record creation and removal. When you deploy or adopt a service,
|
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
|
DashCaddy creates the corresponding A or CNAME record through the Technitium REST API so the new hostname
|
||||||
immediately. Removing a service cleans up the record automatically.
|
resolves immediately. Removing a service cleans up the record automatically — no orphaned DNS entries.
|
||||||
</p>
|
</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>
|
<h2>DashCA — internal certificate authority</h2>
|
||||||
<p>
|
<p>
|
||||||
DashCA is the certificate distribution system that makes internal HTTPS practical. Caddy's internal CA
|
DashCA is the certificate distribution system that makes internal HTTPS practical. Caddy's internal CA
|
||||||
issues certificates automatically; DashCA provides the distribution page where you download the root
|
issues certificates automatically for <code>.lab</code> and other private hostnames; DashCA provides the
|
||||||
certificate and install it as a trusted CA across your devices. Once trusted, every internal service is served
|
distribution page where you download the root certificate and install it as a trusted CA across your devices.
|
||||||
over valid HTTPS with no browser warnings.
|
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>
|
</p>
|
||||||
|
|
||||||
<h2>Tailscale — private access</h2>
|
<h2>Tailscale — private access</h2>
|
||||||
<p>
|
<p>
|
||||||
DashCaddy fits naturally into private access patterns with <strong>Tailscale</strong>. Services can be published
|
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's DNS, proxy,
|
only on a Tailnet, keeping them off the public internet while still benefiting from DashCaddy'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>
|
||||||
|
<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 & 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 & Grafana — metrics & observability</h2>
|
||||||
<p>
|
<p>
|
||||||
DashCaddy exports metrics in Prometheus format at <code>/metrics</code>, including service health, container
|
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
|
status, request counts, certificate expiry, and system resource indicators. Point your Prometheus scraper at
|
||||||
Grafana dashboards on top for long-term observability and alerting.
|
the endpoint and build Grafana dashboards on top for long-term observability, capacity planning, and alerting.
|
||||||
</p>
|
</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:
|
scrape_configs:
|
||||||
- job_name: 'dashcaddy'
|
- job_name: 'dashcaddy'
|
||||||
metrics_path: /metrics
|
metrics_path: /metrics
|
||||||
static_configs:
|
static_configs:
|
||||||
- targets: ['dashcaddy-host:3000']`}</code></pre>
|
- targets: ['dashcaddy-host:3000']
|
||||||
|
# Optional: increase scrape frequency for faster alerting
|
||||||
<h2>MCP & AI assistants</h2>
|
scrape_interval: 15s
|
||||||
|
scrape_timeout: 10s`}</code></pre>
|
||||||
<p>
|
<p>
|
||||||
The built-in <strong>MCP Server</strong> exposes DashCaddy operations to AI assistants and external automation.
|
Useful PromQL starters once data is flowing: <code>dashcaddy_service_health == 0</code> (unhealthy services),
|
||||||
Combined with the <strong>AI Intent Router</strong>, you can issue natural-language commands
|
<code> rate(dashcaddy_http_requests_total[5m])</code> (request throughput), and
|
||||||
(“restart the media server”, “deploy the postgres template”) and have DashCaddy execute
|
<code>dashcaddy_cert_expiry_days < 14</code> (certificates expiring soon).
|
||||||
the real infrastructure action. See the <a href="/docs/api">API and Automation</a> guide for details.
|
</p>
|
||||||
|
|
||||||
|
<h2>MCP Server & 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 — “restart the media server”, “deploy the postgres template”, “is the
|
||||||
|
database healthy?” — 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>
|
</p>
|
||||||
|
|
||||||
<h2>How the layers fit together</h2>
|
<h2>How the layers fit together</h2>
|
||||||
<ul>
|
<p>
|
||||||
<li><strong>Deploy / Adopt</strong> → Docker runs the container.</li>
|
The table below maps each integration to the layer it provides and the DashCaddy feature that consumes it.
|
||||||
<li><strong>Publish</strong> → Caddy creates the reverse-proxy route and TLS cert.</li>
|
When a service fails, locate the row whose symptom matches, then debug that integration directly.
|
||||||
<li><strong>Resolve</strong> → Technitium DNS creates the hostname record.</li>
|
</p>
|
||||||
<li><strong>Trust</strong> → DashCA distributes the root CA for internal HTTPS.</li>
|
<table>
|
||||||
<li><strong>Observe</strong> → health checks + Prometheus + WebSocket live updates.</li>
|
<thead>
|
||||||
<li><strong>Secure</strong> → Security Center aggregates events; audit logging records every change.</li>
|
<tr>
|
||||||
</ul>
|
<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 & 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>
|
</DocsLayout>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+250
-49
@@ -10,6 +10,13 @@ export default function DocsOverviewPage() {
|
|||||||
title="Product Overview"
|
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."
|
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>
|
<h2>What DashCaddy is</h2>
|
||||||
<p>
|
<p>
|
||||||
DashCaddy brings together the layers that self-hosters usually wire by hand — Docker deployment,
|
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>
|
<h2>Platform architecture</h2>
|
||||||
<p>
|
<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>
|
</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'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>
|
<h3>1. Application Layer</h3>
|
||||||
<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 & 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>
|
|
||||||
<p>
|
<p>
|
||||||
DashCaddy is proprietary software and intellectual property of <strong>samiahmed7777</strong>. Public-facing
|
The Application Layer is what operators interact with directly. It is a React-based dashboard that
|
||||||
documentation and branding reflect that commercial/proprietary positioning rather than an open-source default.
|
provides real-time visibility into every service, container, and infrastructure component managed by
|
||||||
The core platform is fully useful without a license; Premium unlocks a focused set of advanced orchestration features.
|
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>
|
</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 & 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>
|
</DocsLayout>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -51,9 +51,8 @@ export default function Footer() {
|
|||||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8">
|
||||||
{/* Brand Section */}
|
{/* Brand Section */}
|
||||||
<div>
|
<div>
|
||||||
<Link href="/" className="flex items-center gap-2 font-bold text-lg text-brand-400 hover:text-brand-300 transition-colors mb-4">
|
<Link href="/" className="flex items-center transition-opacity hover:opacity-80 mb-4">
|
||||||
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={28} height={28} className="rounded" />
|
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={36} height={36} className="rounded" />
|
||||||
<span>DashCaddy</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
<p className="text-surface-400 text-sm leading-relaxed mb-4">
|
<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.
|
Self-hosted Docker dashboard with automatic SSL, DNS, and reverse proxy. Making self-hosting beautiful and effortless.
|
||||||
|
|||||||
@@ -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="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||||
<div className="flex h-16 items-center justify-between">
|
<div className="flex h-16 items-center justify-between">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<Link href="/" className="flex items-center gap-2 font-bold text-xl text-brand-400 hover:text-brand-300 transition-colors">
|
<Link href="/" className="flex items-center transition-opacity hover:opacity-80">
|
||||||
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={32} height={32} className="rounded-lg" priority />
|
<Image src="/images/logo-dark.jpg" alt="DashCaddy" width={40} height={40} className="rounded-lg" priority />
|
||||||
<span>DashCaddy</span>
|
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
{/* Desktop Navigation */}
|
{/* Desktop Navigation */}
|
||||||
|
|||||||
Reference in New Issue
Block a user