← All Guides
intermediate

Wildcard SSL Certificates for Your Homelab (Let's Encrypt + Cloudflare)

Get a single wildcard SSL certificate that covers every subdomain in your homelab. No more per-service certificates, no more HTTPS warnings.

Budget Homelab ·
networkingssl-certificatescloudflarenginx-proxy-manager

Every time you add a new service to your homelab, you need an SSL certificate for it. If you’re requesting individual certificates per subdomain, that means a separate Let’s Encrypt request for mealie.yourdomain.com, paperless.yourdomain.com, jellyfin.yourdomain.com, and every other service you run.

A wildcard certificate covers all of them at once. One certificate, *.yourdomain.com, is valid for every subdomain. Add ten new services and you don’t touch SSL again. It’s also required if your services are internal-only (no public HTTP route), since wildcard certs use DNS challenge instead of HTTP challenge.

This guide covers requesting a wildcard certificate through Nginx Proxy Manager using Let’s Encrypt and Cloudflare DNS. If you’re using a different DNS provider, the steps are similar but the API token setup will differ.

Before you start: You need NPM running and a domain on Cloudflare. If NPM isn’t set up yet, see the Nginx Proxy Manager setup guide.

Why wildcard certificates

Individual per-subdomain certs work fine, but they have real downsides:

Get a Cloudflare API token

The DNS challenge works by having your DNS provider temporarily create a TXT record to prove you control the domain. Cloudflare’s API handles this automatically.

In the Cloudflare dashboard:

  1. Go to My Profile → API Tokens
  2. Click Create Token
  3. Use the Edit zone DNS template
  4. Under Zone Resources, select Specific zone and choose your domain
  5. Create the token and copy it — you won’t see it again

This token has permission to create and delete DNS records on that specific zone. It can’t touch anything else.

Request the wildcard certificate in NPM

In NPM, go to SSL Certificates → Add SSL Certificate.

Fill in the form:

Domain Names: Add two entries:

The second entry covers the bare domain. Without it, yourdomain.com (without a subdomain) won’t be covered by the certificate.

Email address: Your Let’s Encrypt account email — used for expiry notifications.

Use a DNS Challenge: Enable this toggle. Without DNS challenge, wildcard certificates aren’t possible through Let’s Encrypt.

DNS Provider: Select Cloudflare from the dropdown.

A text field will appear for credentials. Enter your API token in this format:

dns_cloudflare_api_token = your-token-here

Click Save. NPM will:

  1. Contact Let’s Encrypt
  2. Get a challenge TXT record to create
  3. Create the record via Cloudflare’s API
  4. Wait for DNS propagation
  5. Let’s Encrypt verifies the record
  6. Certificate issues

This usually takes 30–90 seconds. If it times out, it’s almost always DNS propagation — wait two minutes and try again.

Assign the wildcard cert to proxy hosts

Once the certificate exists, assign it to proxy hosts instead of requesting individual certs.

For each proxy host in NPM:

  1. Go to Hosts → Proxy Hosts
  2. Edit a host
  3. Click the SSL tab
  4. Under SSL Certificate, select your wildcard cert from the dropdown
  5. Enable Force SSL and HTTP/2 Support
  6. Save

Do this for every proxy host. From this point forward, any new subdomain you create in NPM can use the same wildcard cert — just select it from the dropdown.

Set up automatic renewal

Let’s Encrypt certificates expire every 90 days. NPM handles renewal automatically — it monitors certificate expiry and renews before they expire.

No manual action needed. The Cloudflare API token stays stored in NPM and gets used again at renewal time. Make sure the token doesn’t expire — the default Cloudflare API tokens don’t expire unless you set them to.

If renewal fails (usually because the API token was deleted or expired), NPM will show the certificate as invalid and you’ll get HTTPS warnings on all services at once. Check the NPM logs when that happens:

docker logs nginx-proxy-manager 2>&1 | grep -i "cert\|ssl\|error" | tail -20

Using the certificate for internal-only services

One of the main reasons to use DNS challenge and wildcard certs is internal services. A service only reachable on your local network (or via Tailscale) can’t respond to HTTP challenge — there’s no public route for Let’s Encrypt to verify. DNS challenge doesn’t care.

The setup is identical. Create a proxy host for mealie.yourdomain.com, point it to the internal IP:port, assign the wildcard cert, enable Force SSL. Let’s Encrypt never needs to reach the service — only the DNS record matters for validation.

My entire homelab runs this way: every service has HTTPS, zero ports are forwarded, and everything is accessible via Tailscale with valid certificates.

For the remote access side of this, see the Tailscale homelab setup guide and subnet routing guide.

Wildcard + subdomain certificates together

You can mix wildcard and individual certificates in NPM. If you have a service that needs a certificate for a domain that isn’t a subdomain of your main domain (say, a second domain you own), request that separately as an individual cert.

Wildcard certs are domain-specific — *.yourdomain.com doesn’t cover *.otherdomain.com. Each domain needs its own wildcard cert if you want coverage.

Troubleshooting

Certificate request fails immediately

Usually an API token issue. Double-check the token was entered correctly in the dns_cloudflare_api_token = <token> format. Paste it fresh — don’t retype.

Challenge TXT record visible in DNS but Let’s Encrypt still fails

Sometimes Let’s Encrypt queries a specific DNS server that hasn’t picked up the new record yet. Wait two minutes and retry. If it keeps failing, check whether Cloudflare’s DNS propagation is showing the TXT record:

dig TXT _acme-challenge.yourdomain.com @1.1.1.1

The record should appear there. If it doesn’t, the API token may not have write permissions on that zone.

NPM shows the cert as expired and won’t auto-renew

Check whether the Cloudflare token is still valid. Go to Cloudflare → My Profile → API Tokens and verify the token is active. If it was deleted, create a new one and update the credential in NPM by editing the SSL certificate.

Wildcard doesn’t cover a two-level subdomain

*.yourdomain.com covers service.yourdomain.com but not service.subdomain.yourdomain.com. Two-level wildcards (*.subdomain.yourdomain.com) require a separate certificate. In practice, homelab setups are flat — all services are at the first subdomain level — so this rarely matters.


A wildcard certificate is a one-time setup that eliminates SSL friction for every service you add afterward. It’s worth doing early so it’s already in place when you’re adding your tenth service and you can’t remember the per-cert workflow anyway.

For the full homelab reverse proxy setup, see Nginx Proxy Manager setup and the Authelia SSO guide for authentication on top of HTTPS.