<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://smitssjors.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://smitssjors.github.io/" rel="alternate" type="text/html" /><updated>2026-01-06T22:09:44+00:00</updated><id>https://smitssjors.github.io/feed.xml</id><title type="html">Sjors Smits</title><subtitle>My personal blog. All opinions are mine.</subtitle><entry><title type="html">Simple Custom User Domains</title><link href="https://smitssjors.github.io/2024/10/24/simple-custom-user-domains.html" rel="alternate" type="text/html" title="Simple Custom User Domains" /><published>2024-10-24T00:00:00+00:00</published><updated>2024-10-24T00:00:00+00:00</updated><id>https://smitssjors.github.io/2024/10/24/simple-custom-user-domains</id><content type="html" xml:base="https://smitssjors.github.io/2024/10/24/simple-custom-user-domains.html"><![CDATA[<p>Let’s say you have a website builder and you’re hosting a user’s site at
<code class="language-plaintext highlighter-rouge">user1.yoursite.com</code>. The goal is to allow users to use their own domain so
that, for example, <code class="language-plaintext highlighter-rouge">user1.com</code> points to <code class="language-plaintext highlighter-rouge">user1.yoursite.com</code>.</p>

<h2 id="dns-records">DNS Records</h2>

<p>If a user wants to set up a subdomain (like <code class="language-plaintext highlighter-rouge">www.user1.com</code>), you can simply
instruct them to add a <code class="language-plaintext highlighter-rouge">CNAME</code> record that points <code class="language-plaintext highlighter-rouge">www.user1.com</code> to
<code class="language-plaintext highlighter-rouge">user1.yoursite.com</code> in their DNS settings. However, for root domains (e.g.,
<code class="language-plaintext highlighter-rouge">user1.com</code>), the correct record type depends on their DNS provider. This could
be an <code class="language-plaintext highlighter-rouge">ANAME</code>, <code class="language-plaintext highlighter-rouge">ALIAS</code>, or even a <code class="language-plaintext highlighter-rouge">CNAME</code> record.</p>

<p>If you have a stable IP address, you can also guide the user to add an <code class="language-plaintext highlighter-rouge">A</code>
record.</p>

<h2 id="tls-certificates">TLS Certificates</h2>

<p>At this point, you might wonder if that’s all you need to do, but the short
answer is no. If your site is served over HTTPS (which it should be), users will
encounter a TLS error. This happens because your TLS certificate only covers
<code class="language-plaintext highlighter-rouge">*.yoursite.com</code>, but the request is coming from <code class="language-plaintext highlighter-rouge">user1.com</code>. You’ll need to
obtain a new TLS certificate for your user’s domain.</p>

<p>This can present some challenges. For instance, if you’re using a hosting
platform like Vercel that manages TLS, you may not have the option to add
certificates for custom domains. Or, if you’re using a proxy/CDN service like
Cloudflare that terminates TLS, you’ll need to either disable it or use one of
their services designed for this purpose (such as
<a href="https://www.cloudflare.com/saas">Cloudflare for SaaS</a>).</p>

<p>While managing and renewing certificates might seem daunting, fortunately,
there’s an easier solution.</p>

<h2 id="caddy-on-demand-tls">Caddy On-Demand TLS</h2>

<p><a href="https://caddyserver.com">Caddy</a> is an open-source web server built in Go, known
for its automatic HTTPS capabilities. One of its standout features is the
ability to dynamically issue certificates on demand. When a request comes in,
Caddy will automatically attempt to obtain a certificate for the requested
domain. However, since this can be risky, it’s important to configure Caddy to
ask your application whether it should issue a certificate for a particular
domain.</p>

<p>Here’s an example Caddyfile configuration. The global <code class="language-plaintext highlighter-rouge">on_demand_tls.ask</code> option
ensures that Caddy makes a request to
<code class="language-plaintext highlighter-rouge">http://localhost:5555/check?domain=example.com</code> to validate the domain. The
<code class="language-plaintext highlighter-rouge">tls.on_demand</code> option enables On-Demand TLS for the specified site.</p>

<pre><code class="language-caddyfile">{
    on_demand_tls {
        ask      http://localhost:5555/check
    }
}

https:// {
    tls {
        on_demand
    }
    reverse_proxy localhost:9000
}
</code></pre>

<p>For more details, check the Caddy documentation:</p>

<ul>
  <li><a href="https://caddyserver.com/docs/automatic-https#on-demand-tls">Automatic HTTPS - On-Demand TLS</a></li>
  <li><a href="https://caddyserver.com/docs/caddyfile/options#on-demand-tls">Caddyfile Options - On-Demand TLS</a></li>
  <li><a href="https://caddy.community/t/serving-tens-of-thousands-of-domains-over-https-with-caddy/11179">Serving Many Domains with Caddy</a></li>
</ul>]]></content><author><name></name></author><summary type="html"><![CDATA[Let’s say you have a website builder and you’re hosting a user’s site at user1.yoursite.com. The goal is to allow users to use their own domain so that, for example, user1.com points to user1.yoursite.com.]]></summary></entry></feed>