Get Started
โ† All Posts

Automating SSL for Millions of Domains with Caddy

How our Rust control plane uses Caddy to instantly provision custom domain certificates for our managed tenants.

Automating SSL for Millions of Domains with Caddy

When a customer upgrades to the MarkReply Managed Cloud, they expect to serve their comment widget from their own subdomain (e.g., comments.their-startup.com).

Managing SSL certificates for thousands of custom, tenant-owned domains is one of the hardest infrastructure challenges in a multi-tenant SaaS. Here is how we solved it without ever restarting our web server.

๐Ÿ“œ The Old Way: Nginx and Reloads

Historically, issuing a custom domain certificate required a fragile, multi-step pipeline:

  1. The tenant points their DNS to your server.
  2. A worker queue triggers Certbot to complete an ACME challenge.
  3. The server generates a new Nginx configuration file.
  4. The server forcefully reloads Nginx to apply the new certificate.

If a configuration is malformed, the reload fails, and routing breaks. If you have hundreds of signups an hour, constantly reloading the proxy creates dropped connections and latency spikes.

โšก The MarkReply Way: Caddy On-Demand TLS

We bypassed this entirely by placing Caddy in front of our Rust Axum backend.

Caddy has a remarkable feature called On-Demand TLS. Instead of pre-fetching certificates when a user registers, Caddy waits until the very first time a browser attempts to visit comments.their-startup.com.

During the TLS handshake, Caddy pauses the connection and asks our Rust control plane a single question: โ€œIs this domain authorized?โ€

// Caddy asks our Rust API
GET /api/internal/verify-domain?domain=comments.their-startup.com

Our Axum backend instantly checks our SQLite database to verify if the tenant is on an active billing plan. If we return 200 OK, Caddy automatically:

  1. Generates an SSL certificate via Letโ€™s Encrypt.
  2. Serves the certificate to the browser.
  3. Caches it securely for all future requests.

โœ‹ Zero-Touch Provisioning

The entire process takes roughly 2 seconds for the very first visitor, and milliseconds for everyone else.

By combining Caddyโ€™s dynamic proxying with our high-performance Rust control plane, we achieved true zero-touch provisioning. Customers can upgrade their plan, update their DNS, and immediately start securely serving commentsโ€”no manual intervention or server reloads required.