Cloudflare Setup

3 min read

Cloudflare in front of a teploy app is entirely optional and set up on Cloudflare's side — teploy has no Cloudflare API integration. Your app works without it: SSL is handled automatically by Caddy via Let's Encrypt, and traffic goes straight to your server.

Why add Cloudflare?

  • Global CDN — cache static assets at Cloudflare's edge
  • DDoS protection — traffic filtering in front of your server
  • Web Application Firewall — block common attacks before they reach Caddy
  • Analytics — traffic insights at the edge

Set it up

This is configured entirely in Cloudflare's dashboard, not teploy's:

  1. Add your domain to Cloudflare and update your nameservers
  2. In Cloudflare DNS, point your A record at your server's IP and enable the proxy (orange cloud)
  3. In Cloudflare's SSL/TLS settings, choose a mode (see below)

teploy doesn't need to know Cloudflare is there — Caddy still serves the app the same way. The only teploy-side consideration is DNS validation: with the proxy enabled, your domain's A record resolves to a Cloudflare IP, not your server's, so teploy deploy's DNS check will fail unless you pass --skip-dns-check.

SSL modes

Mode Description
Full (Strict) Cloudflare verifies your origin certificate — recommended
Full Encrypts to origin, accepts self-signed
Flexible Only encrypts browser to Cloudflare, plaintext to your server — avoid this

With the proxy enabled, Caddy can no longer complete an HTTP-01 ACME challenge (Cloudflare, not your server, answers on port 80/443 from the public internet), so automatic Let's Encrypt HTTPS won't work for a proxied domain. Two options:

  • Full (Strict), recommended: generate a Cloudflare Origin Certificate (Cloudflare's dashboard → SSL/TLS → Origin Server), then reference it from teploy.yml:
    tls:
      cert: ./certs/cloudflare-origin.pem
      key: ./certs/cloudflare-origin-key.pem
    teploy uploads these to the server on every deploy and Caddy terminates TLS with them instead of attempting ACME.
  • Cloudflare Tunnel: if you're using cloudflared instead of a proxied A record, set ingress: external in teploy.yml — teploy skips Caddy routing entirely and your app is reachable at its Docker network alias, which the tunnel points to.

Without Cloudflare

If you don't put anything in front of your server:

  • SSL is handled by Let's Encrypt (automatic, via Caddy)
  • Traffic goes directly to your server
  • No edge CDN caching
  • DDoS protection is whatever your VPS provider offers at the network level

For most apps this is fine. Add Cloudflare later if you need CDN or edge-level filtering.