Auto SSL for User-Added Custom Domains

Project Context: I'm building a SaaS platform where users can create their own websites and add their custom domains. Think of it like Shopify's custom domain feature - users should be able to point their domains to our service and get SSL automatically.

Current Stack:

  • Traefik v3.1
  • Next.js application
  • Hosted on VPS using Coolify
  • Namecheap DNS with Let's Encrypt

The Problem: While my Traefik setup works perfectly with hardcoded domains, I can't get it to automatically generate SSL certificates for dynamically added domains. Users should be able to:

  1. Add their custom domains
  2. Point their DNS to our service
  3. Get SSL automatically without manual intervention

Current Configuration:

# Certificate Resolver Setup
certificatesresolvers:
  letsencrypt:
    acme:
      email: info@my-domain.com
      storage: /acme.json
      dnschallenge:
        provider: namecheap
        delaybeforecheck: 30

# Router for Custom Domains
custom-domains-secure:
  rule: 'HostRegexp(`{customdomain:.+}`) && !Host(`coolify.my-domain.com`, `my-domain.com`)'
  service: nextjs-app
  entryPoints:
    - websecure
  tls:
    certResolver: letsencrypt
  priority: 1000

What Works: SSL works perfectly when domains are hardcoded like this:

tls:
  certResolver: letsencrypt
  domains:
    - main: example.com
    - sans: '*.example.com'

What I Need: A way to make Traefik automatically:

  1. Detect new domains when users add them
  2. Generate SSL certificates without manual config changes
  3. Handle multiple custom domains pointing to the same service

Questions:

  1. Is there a proper way to handle dynamic SSL certification in Traefik v3.1?
  2. Should I be using a different approach altogether?

Any help would be greatly appreciated! This is a crucial feature for my SaaS platform to allow users to use their own domains seamlessly.

For Traefik to create an individual LetsEncrypt TLS cert, you need to create a router with the domain name.

Traefik loads dynamic config via providers, so you need to add the new router (or updated rule) to a dynamic config file, to container labels, a http service, redis or whatever providers are available (doc). Traefik will then pull config updates.

From a few posts on the forum (example), there seems to be a REST provider to actively push config updates to Traefik, but it is undocumented, a leftover from v1, so not really recommended.

1 Like

Note that Traefik LetsEncrypt will usually test the domain first, if it points to itself. Therefore it will do DNS domain lookup. If the domain points to the wrong IP, it will generate an error. The issue is that DNS is cached, so it might take 10 min to 24 hours until an IP update by customer is recognized.

The alternative to Traefik LetsEncrypt is to use an external tool like certbot or go-acme to create the TLS certs. Those you can trigger by code and check results. You could create a separate dynamic config TLS (file) for every domain, and inline the certs (example). But don’t forget about the cert renew after 2 months.

tls:
  options:
    default:
      minVersion: VersionTLS12
  certificates:
    # CERT FILE /etc/letsencrypt/live/example.com
    - certFile: |-
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
      keyFile: |-
        -----BEGIN PRIVATE KEY-----
        ...
      -----END PRIVATE KEY-----
    # CERT FILE /etc/letsencrypt/live/www.example.com
    - certFile: |-
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
      keyFile: |-
        -----BEGIN PRIVATE KEY-----
        ...
      -----END PRIVATE KEY-----   
1 Like

Thanks for the insights. i appreciate it :wink: