Skip to content

Caddy on Windows: automatic TLS with one binary

Verified 1 min read

Use Caddy on Windows for a small site or reverse proxy, with automatic public TLS, internal TLS for a lab, and a Caddyfile you can validate.

Tested onStandard / Datacenter · Build 26100.33650 · x64
E1
Build
26100.33650
Edition
Standard / Datacenter
Architecture
x64
Support
Documentation (E1)
Evidence
E1Official documentation
Verified
2026-10-29
Page type
Task

Caddy is a single Windows binary with automatic HTTPS for public DNS names. It is a good fit for:

  • a small internal/public site with a real domain;
  • a reverse proxy in front of Node/Python;
  • a lab where you want TLS without manually issuing certificates.

It is not a drop-in IIS replacement for Windows authentication, IIS modules or ASP.NET-specific features.

Download the Windows amd64 zip, extract to C:\caddy, and put caddy.exe on PATH or use the full path.

Terminal window
C:\caddy\caddy.exe version
C:\caddy\caddy.exe validate --config C:\caddy\Caddyfile
C:\caddy\caddy.exe run --config C:\caddy\Caddyfile

caddy run stays in the foreground. caddy start backgrounds it; caddy reload applies a new config; caddy stop stops it.

lab.example.com {
root * C:/sites/lab
file_server
}

With a public DNS record and ports 80/443 reachable, Caddy obtains and renews a certificate automatically. It uses HTTP-01 or TLS-ALPN; no manual CSR.

For a lab name that does not resolve publicly:

lab.local {
tls internal
root * C:/sites/lab
file_server
}

tls internal uses Caddy’s local CA; clients must trust it (caddy trust on the server, or import the root CA on the client). It is not a public certificate.

app.example.com {
reverse_proxy 127.0.0.1:3000
}

Caddy sets X-Forwarded-For, X-Forwarded-Proto and Host by default. For WebSocket, reverse_proxy handles the upgrade without a separate map.

Headers:

app.example.com {
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options "nosniff"
-Server
}
reverse_proxy 127.0.0.1:3000
}

Caddy does not need a service to run, but production should use one. Wrap caddy.exe run --config C:\caddy\Caddyfile with WinSW/NSSM:

  • working directory C:\caddy;
  • account with read on the binary/config/site and write on Caddy’s data dir;
  • restart on failure;
  • firewall 80/443 only from the intended network.

Do not run two process managers (service + scheduled task) against the same config/ports.

Terminal window
C:\caddy\caddy.exe validate --config C:\caddy\Caddyfile
curl.exe -I https://lab.example.com/
curl.exe -I --resolve lab.example.com:443:127.0.0.1 https://lab.example.com/ -k

Check the certificate issuer/SAN, redirect from HTTP, and X-Forwarded-* at the app.

E1. Caddy was not installed in this lab. The Caddyfile examples are the starting point; test certificate issuance and service wrapping on Server 2025 before claiming E2.

Sources