Secure Private Domains with Caddy + Tailscale

Imagine you want to access secret.example.com, but only you — or a few trusted people — should be able to reach it.
Traditional methods like IP allowlists or blocklists quickly become unreliable:

In 2025, IP filtering is simply not enough.


Why Tailscale Solves This

Caddy can serve your site directly over the Tailscale network interface, meaning the service is only reachable through your private 100.x.x.x Tailscale IP.

You gain:

To begin, point your DNS A / AAAA record to the Tailscale IP of your server.


Why DNS-01 Is Required

HTTP-01 and TLS-ALPN-01 challenges won’t work because the service is not publicly reachable.
The ACME server simply cannot connect.

DNS-01 solves this by verifying domain ownership through DNS API calls instead of network access.

If you use Cloudflare, the caddy-cloudflare build makes this process seamless:

https://github.com/CaddyBuilds/caddy-cloudflare


Step 1 — Add Cloudflare API Token to Docker Compose

Your compose.yaml should include:

1environment:
2  - CLOUDFLARE_API_TOKEN=your_cloudflare_api_token

The token must have:
Zone → DNS → Edit


Step 2 — Configure Caddy to Use Cloudflare DNS

Add this to the global block of your Caddyfile:

1{
2  # Use Cloudflare for all ACME DNS challenges
3  acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
4}

This tells Caddy to always use Cloudflare’s API for certificate validation.


Done — Your Private HTTPS Domain

You can now visit:

https://secret.example.com

The site is:

No public exposure.
No complicated firewall rules.
No unstable IP allowlists.

Just clean, modern, private infrastructure.


#caddy   #tailscale   #cloudflare   #dns-01   #self-hosting   #security