DashCaddy Documentation

Deploy Your First Service

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:

  • Container deployment (from template) or adoption of an existing container
  • Service record creation in the DashCaddy state store
  • DNS record creation through Technitium DNS (when configured)
  • Caddy reverse-proxy route configuration via the Admin API
  • Automatic TLS certificate issuance through Caddy's internal CA / DashCA
  • Real-time health tracking and WebSocket status updates on the dashboard

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

1. Pick from 77 one-click templates

The template library covers the most popular self-hosted applications — media servers, dashboards, databases, note apps, automation tools, and more. Each template bundles sane defaults for ports, volumes, environment variables, and the recommended subdomain.

2. Use Service Discovery to auto-detect existing containers

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

3. Define a service manually

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.

Step-by-step: Deploy Plex

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

  • Service name: plex (used for internal identification)
  • Hostname: plex.local (the subdomain DashCaddy will publish)
  • Container image: linuxserver/plex:latest
  • Port: 32400 (Plex's default web interface port)
  • Volumes: /opt/plex/config:/config and /mnt/media:/media
  • Environment variables: PUID=1000, PGID=1000, VERSION=docker

Step 4: Deploy

Click Deploy. DashCaddy now executes the full deployment chain:

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

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:

  • Container logs (live-streamed via WebSocket)
  • Resource usage (CPU, memory, network I/O)
  • Caddy route configuration
  • DNS record details
  • Certificate expiration date
  • Health check history

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. Review the list of detected containers
  3. For each one you want to manage, click Adopt
  4. Provide a hostname/subdomain (e.g., grafana.local)
  5. Specify which port to expose (if the container exposes multiple)
  6. Click Adopt & Configure

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 tolocalhost: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 toplex.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 .localor .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.localwith 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:

  • PUID=1000 / PGID=1000 — user/group ID for file permissions (LinuxServer images)
  • TZ=America/New_York — timezone for log timestamps
  • DB_PASSWORD=secret — database credentials for apps like Nextcloud

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. Backend port: curl http://localhost:32400 returns a response from the application
  3. Caddy route: curl http://localhost:2019/config/ shows a route for your hostname
  4. DNS resolution: ping plex.local resolves to your host's IP address
  5. TLS certificate: curl -v https://plex.local shows a valid certificate (no warnings if DashCA root is installed)
  6. Health check: The dashboard shows Healthy and the health check history graph shows consistent success

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. Backend port: Verify the container is listening on the expected port
  3. Caddy route: Confirm the route exists in the Caddy Admin API
  4. DNS resolution: Check that the DNS record was created in Technitium
  5. TLS trust: Verify the DashCA root certificate is installed on the client device
  6. Dashboard state: Check the service detail page for error messages or failed health checks

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

Next steps

  • Product Overview — understand the full architecture and design philosophy
  • Explore the Template Library to discover other applications you can deploy
  • Configure Service Discovery to adopt existing containers
  • Set up Prometheus metrics for external monitoring integration