Skip to content

Provision TLS for a Custom Domain

When to Run This Runbook

Run this runbook every time an agency's custom domain transitions to verified status. Until TLS provisioning is automated (see v2 roadmap in the feature doc), the platform operator must manually register each verified domain in Dokploy so that Traefik can obtain a Let's Encrypt certificate and serve the domain over HTTPS.

Symptoms that indicate this runbook is needed:

  • An agency admin reports that their custom domain shows as "Active" in the dashboard but is unreachable or shows a TLS warning in the browser.
  • A new verified record appears in identity.agency_custom_domains that has no Dokploy domain entry yet.

Prerequisites

Before running this runbook, confirm:

  1. Domain is verified in the database. Run the following query against the identity schema:

    sql
    SELECT id, agency_id, hostname, status, verified_at
    FROM identity.agency_custom_domains
    WHERE hostname = '<hostname>'
      AND status = 'verified';

    If the query returns no rows, the domain is not yet verified. The agency admin must complete DNS verification first (see Agency Custom Domains — End-to-End Flow).

  2. CNAME record points to proxy.daramex.org. Confirm from a DNS lookup tool or terminal:

    bash
    dig CNAME <hostname> +short
    # Expected output: proxy.daramex.org.

    If the CNAME is missing or points elsewhere, ask the agency admin to add/correct their DNS records and wait for propagation before proceeding. Dokploy will fail to obtain a Let's Encrypt cert if the domain does not route to the server.

  3. Dokploy access. You must have operator-level access to the Dokploy UI.


Step 1 — Log in to Dokploy

  1. Navigate to the Dokploy admin UI (internal URL — see infra ops docs).
  2. Sign in with your operator credentials.

Step 2 — Open the Panel Service

  1. From the Dokploy dashboard, click Applications.
  2. Locate the service that serves the DaraMex panel (typically named daramex-panel or similar — confirm with the infra team if unsure).
  3. Click on the service to open its detail view.

Step 3 — Add the Custom Domain

  1. Click the Domains tab inside the service detail view.

  2. Click Add Domain.

  3. Fill in the fields:

    FieldValue
    Domain<hostname> (e.g. booking.kfc.com)
    HTTPSEnabled (checkbox checked)
    CertificateLet's Encrypt (select from dropdown)
    PortMatch the panel service port (typically 3000)
  4. Click Save (or Add depending on Dokploy version).

Traefik will automatically initiate a Let's Encrypt ACME challenge. Certificate issuance typically completes within 30–90 seconds, assuming the CNAME is already propagated.


Step 4 — Verify the Certificate

Allow 60–90 seconds for cert issuance, then verify:

bash
# Check that the domain returns HTTP 200 and the cert is valid
curl -I https://<hostname>

# Check cert details
echo | openssl s_client -connect <hostname>:443 -servername <hostname> 2>/dev/null \
  | openssl x509 -noout -dates -subject

Expected output:

  • HTTP/2 200 (or redirect to the app route) in the curl response.
  • subject=CN = <hostname> in the cert output.
  • notAfter is approximately 90 days from today (Let's Encrypt cert validity).

Failure Modes

DNS not pointing yet / propagation lag

Symptom: Cert issuance fails; Traefik logs show acme: error: 403 :: urn:ietf:params:acme:error:unauthorized or NXDOMAIN.

Resolution:

  1. Confirm the CNAME is set correctly with dig CNAME <hostname> +short.
  2. If the CNAME resolves correctly but issuance still fails, wait for propagation (up to 48 hours for high-TTL zones) and retry by removing and re-adding the domain in Dokploy.
  3. If the CNAME is not set, ask the agency admin to add it and wait for propagation.

Let's Encrypt rate limit exceeded

Symptom: Cert issuance fails with urn:ietf:params:acme:error:rateLimited in Traefik logs. Let's Encrypt enforces 5 certificates per registered domain per week (and account-level limits).

Resolution options:

  1. Wait 7 days. The rate limit window resets automatically.
  2. Use Let's Encrypt staging to test certificate issuance without consuming production quota (configure Traefik with the LE staging CA URL; staging certs are not trusted by browsers, so this is only for operator testing).
  3. If the same domain is being re-issued frequently (e.g. after repeated Dokploy domain removes/re-adds), avoid unnecessary changes to the domain entry.

Reference: Let's Encrypt Rate Limits


Certificate not renewing automatically

Symptom: notAfter date is within 30 days (Traefik should auto-renew before then) or the cert has already expired.

Resolution:

  1. Check Traefik logs for renewal errors:

    bash
    # On the Dokploy server or via Dokploy log viewer:
    docker logs <traefik-container-name> 2>&1 | grep -i "acme\|certificate\|renew"
  2. Common causes:

    • The CNAME was removed or changed by the agency admin after initial provisioning → re-point the CNAME and wait for Traefik to retry renewal.
    • ACME account key issue → may require recreating the Traefik ACME storage file (consult infra team).
    • Let's Encrypt rate limit hit during renewal → wait and monitor.
  3. If the cert cannot be renewed automatically and is expired, the domain will show a TLS error to end-users. Escalate to the infra team.


Agency removes domain from dashboard but cert is still active in Dokploy

Symptom: The agency_custom_domains record is in removed status, but Dokploy still shows the domain and Traefik still serves traffic from it.

Resolution:

  1. Open the Domains tab for the service in Dokploy.
  2. Find the domain entry for the removed hostname.
  3. Click Remove (or the trash icon).
  4. Traefik will stop routing traffic for that hostname.

The Redis key agency:host:<hostname> is invalidated automatically by the API on domain removal, so the tenant resolution returns 404 immediately. The Dokploy cleanup is a secondary step to free the Let's Encrypt quota and stop serving the (now-invalid) TLS cert.


Rollback

If you need to remove a domain from Dokploy (e.g. the agency removed it from the dashboard or a configuration error occurred):

  1. Open the Domains tab for the panel service in Dokploy.
  2. Find the domain row for the hostname.
  3. Click Remove.
  4. Traefik stops routing and certificate renewal for that hostname.

Removing the domain from Dokploy has no effect on the agency_custom_domains record in the database — those are managed exclusively through the API. Removing from Dokploy only stops TLS termination and routing at the infrastructure layer.