diff --git a/src/app/docs/first-service/page.tsx b/src/app/docs/first-service/page.tsx index 29a3c60..dfff950 100644 --- a/src/app/docs/first-service/page.tsx +++ b/src/app/docs/first-service/page.tsx @@ -10,16 +10,27 @@ export default function DocsFirstServicePage() { title="Deploy Your First Service" intro="This is where DashCaddy becomes real: take an app from a template, an existing container, or a raw target port to a DNS-backed, reverse-proxied, HTTPS-enabled service visible in one dashboard — in a few clicks." > +

Prerequisites

+
+

+ Before you begin: Complete the Installation Guide first. You need a running DashCaddy instance with the dashboard accessible, the API responding on /healthz, and Caddy's Admin API reachable. Technitium DNS is recommended but optional — services will still deploy without it using direct IP access. +

+
+

What DashCaddy handles for you

When you deploy a service, DashCaddy automates the full infrastructure chain:

+

+ 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. +

Three ways to add a service

@@ -29,69 +40,340 @@ export default function DocsFirstServicePage() { databases, note apps, automation tools, and more. Each template bundles sane defaults for ports, volumes, environment variables, and the recommended subdomain.

-
    -
  1. Open the dashboard and choose New Service → From Template.
  2. -
  3. Browse or search the 76+ templates.
  4. -
  5. Select an app and confirm the service name, hostname, and any required secrets.
  6. -
  7. Click Deploy. DashCaddy pulls the image, starts the container, and wires DNS + Caddy + TLS automatically.
  8. -

2. Use Service Discovery to auto-detect existing containers

- Already running Docker containers? DashCaddy's Service Discovery scans the host and lists + Already running Docker containers? DashCaddy's Service Discovery scans the host and lists every running container, marking any that are not yet managed.

-
    -
  1. Open Service Discovery from the sidebar.
  2. -
  3. Review the list of detected containers.
  4. -
  5. For each one you want to manage, click Adopt.
  6. -
  7. Provide a hostname/subdomain. DashCaddy generates the Caddy route, DNS record, and certificate.
  8. -

3. Define a service manually

- For custom images or apps not in the template library, define the service by hand: -

-
    -
  1. Choose New Service → Custom.
  2. -
  3. Provide the container image or the host:port backend target.
  4. -
  5. Set the hostname/subdomain DashCaddy should publish.
  6. -
  7. Optionally add environment variables, volumes, and port mappings.
  8. -
  9. Deploy — the same DNS + Caddy + TLS wiring applies.
  10. -
- -

How Docker + Caddy + DNS wire together

-

- The magic is that the three layers are coordinated as a single transaction rather than three manual steps: -

-
    -
  1. Docker starts (or adopts) the container and exposes the backend port.
  2. -
  3. DashCaddy 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.
  4. -
  5. Caddy automatically requests and renews a TLS certificate for the hostname via its internal CA (or DashCA).
  6. -
  7. Technitium DNS creates the A/CNAME record pointing the hostname at the host.
  8. -
  9. The service appears Healthy on the dashboard once the health check passes.
  10. -
-

- If any layer is not configured (for example, no DNS integration), DashCaddy simply skips that step and - the service still deploys with whatever layers are available. + For custom images or apps not in the template library, define the service by hand with full control + over image, ports, volumes, and environment variables.

-

If the service is internal-only

+

Step-by-step: Deploy Plex

- 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.

+ +

Step 1: Open the template library

+

+ From the dashboard sidebar, click New Service → From Template. The template library + opens with a searchable grid of 76+ applications. +

+ +

Step 2: Find Plex

+

+ Type "Plex" in the search bar, or browse the "Media" category. Click the Plex template card to + open its configuration form. +

+ +

Step 3: Configure the service

+

The form is pre-filled with sensible defaults. Review and adjust:

-

If the service does not come up correctly

+

Step 4: Deploy

- Debug in order, layer by layer: backend container, backend port reachability, reverse-proxy route, DNS - resolution, TLS trust, then dashboard/API state. See the Troubleshooting - guide for the full checklist. + Click Deploy. DashCaddy now executes the full deployment chain:

+
    +
  1. Pulls the linuxserver/plex:latest Docker image
  2. +
  3. Creates and starts the container with your configured volumes and environment
  4. +
  5. Creates a service record in the DashCaddy state store
  6. +
  7. Generates a Caddy route mapping plex.locallocalhost:32400
  8. +
  9. Applies the route through the Caddy Admin API
  10. +
  11. Requests a TLS certificate for plex.local via DashCA
  12. +
  13. Creates an A record in Technitium DNS pointing plex.local to your host IP
  14. +
  15. Starts health checks and reports status on the dashboard
  16. +
+ +

Step 5: Verify

+

+ Within 30 seconds, the service card on the dashboard should show Healthy with a green + status indicator. Click the service to see its detail page, which shows: +

+ + +

Service Discovery: Adopt existing containers

+

+ If you already have Docker containers running that you want DashCaddy to manage, use Service Discovery + instead of redeploying from scratch. +

+ +

How it works

+

+ 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. +

+ +

Adopt a container

+
    +
  1. Open Service Discovery from the sidebar
  2. +
  3. Review the list of detected containers
  4. +
  5. For each one you want to manage, click Adopt
  6. +
  7. Provide a hostname/subdomain (e.g., grafana.local)
  8. +
  9. Specify which port to expose (if the container exposes multiple)
  10. +
  11. Click Adopt & Configure
  12. +
+

+ 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. +

+ +

Behind the scenes: The deployment chain

+

+ Understanding what happens during a deployment helps you troubleshoot when things go wrong. Here's + the full chain, layer by layer: +

+ +

1. Docker: Container creation

+

+ The orchestration layer calls the Docker API to create a container from the specified image. It attaches + the container to the dashcaddy-net bridge network, mounts the configured volumes, and injects + environment variables. The container starts in the background and begins listening on its configured port. +

+ +

2. DashCaddy: Service record

+

+ A service record is written to the DashCaddy state store (a SQLite database in ./data/services.db). + 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. +

+ +

3. Caddy: Reverse proxy route

+

+ The Caddyfile-as-Code builder generates a route configuration: +

+
{`plex.local {
+    reverse_proxy localhost:32400
+    encode gzip
+    header / {
+        Strict-Transport-Security "max-age=31536000;"
+    }
+}`}
+

+ This configuration is applied atomically through the Caddy Admin API (POST /load). Caddy + reloads its configuration without downtime and begins routing traffic for plex.local to + localhost:32400. +

+ +

4. DNS: Record creation

+

+ If Technitium DNS is configured, the orchestration layer calls the Technitium API to create an A record: +

+
{`POST /api/zones/records/create
+{
+  "zone": "local",
+  "type": "A",
+  "name": "plex",
+  "ipAddress": "192.168.1.100"
+}`}
+

+ The DNS record propagates immediately (Technitium is authoritative for the local zone). + Clients on your network can now resolve plex.local to your host's IP address. +

+ +

5. TLS: Certificate issuance

+

+ Caddy's built-in ACME client detects the new hostname and requests a certificate. For internal domains + like plex.local, 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 + plex.local. +

+

+ 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. +

+ +

6. Health: Continuous monitoring

+

+ 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 Unhealthy on the dashboard and an event is logged. +

+

+ Health status updates are pushed to the dashboard over WebSocket, so you see status changes in real-time + without refreshing the page. +

+ +

Configuration reference

+

+ When deploying a service, these are the configuration fields available in the deployment form: +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldRequiredDescription
Service NameYesInternal identifier (lowercase, no spaces)
HostnameYesSubdomain for the service (e.g., plex.local)
Container ImageYesDocker image (e.g., linuxserver/plex:latest)
Backend PortYesPort the container listens on internally
VolumesNoHost:container path mappings for persistent storage
Environment VariablesNoKey-value pairs injected into the container
NetworkNoDocker network to attach (default: dashcaddy-net)
Restart PolicyNoContainer restart behavior (default: unless-stopped)
Health Check PathNoHTTP path for health checks (default: /)
+
+ +

Common scenarios

+ +

Deploy an internal-only service

+

+ For services that should stay on the local network (not exposed to the internet), use a .local + or .internal TLD. Ensure client devices trust the DashCA root certificate (download it from + the DashCA page in the dashboard). The service will be accessible at https://servicename.local + with a trusted HTTPS connection, but only from devices on your network that have the root cert installed. +

+ +

Deploy a service with custom environment variables

+

+ 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: +

+ + +

Deploy multiple services on the same host

+

+ DashCaddy handles multiple services on the same host automatically. Each service gets a unique subdomain, + and Caddy routes traffic based on the Host header. You can run Plex on plex.local, + Nextcloud on nextcloud.local, and Grafana on grafana.local — all on the same + host, all on port 443, with no port conflicts. +

+ +

Adopt a service that's already running

+

+ If you have a container running outside of DashCaddy (e.g., started manually with docker run), + 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. +

+ +

Verification checklist

+

After deploying a service, verify each layer:

+
    +
  1. + Container status: The service card on the dashboard shows Running with + a green status indicator +
  2. +
  3. + Backend port: curl http://localhost:32400 returns a response from the + application +
  4. +
  5. + Caddy route: curl http://localhost:2019/config/ shows a route for your + hostname +
  6. +
  7. + DNS resolution: ping plex.local resolves to your host's IP address +
  8. +
  9. + TLS certificate: curl -v https://plex.local shows a valid certificate + (no warnings if DashCA root is installed) +
  10. +
  11. + Health check: The dashboard shows Healthy and the health check + history graph shows consistent success +
  12. +
+ +

Troubleshooting

+

If the service does not come up correctly, debug in order, layer by layer:

+
    +
  1. Container: Check docker logs <container_name> for startup errors
  2. +
  3. Backend port: Verify the container is listening on the expected port
  4. +
  5. Caddy route: Confirm the route exists in the Caddy Admin API
  6. +
  7. DNS resolution: Check that the DNS record was created in Technitium
  8. +
  9. TLS trust: Verify the DashCA root certificate is installed on the client device
  10. +
  11. Dashboard state: Check the service detail page for error messages or failed health checks
  12. +
+

+ See the Troubleshooting Guide for + the full checklist and common error patterns. +

+ +

Next steps

+