Nginx to Caddy Converter

Paste an nginx server block and convert it to a clean Caddyfile.

Client-side only — nothing leaves your browser

example.com, www.example.com {
	root * /var/www/example
	encode gzip
	header X-Frame-Options SAMEORIGIN
	header Strict-Transport-Security max-age=31536000
	tls /etc/ssl/example.com.crt /etc/ssl/example.com.key
	handle /* {
		try_files {path} {path}/ =404
		file_server
	}
	handle /api/ {
		reverse_proxy 127.0.0.1:3000
	}
	handle /old {
		redir https://example.com/new
	}
	handle /admin {
		# basicauth requires hashed credentials — generate with: caddy hash-password
		basicauth {
			# Convert /etc/nginx/.htpasswd entries to: <user> <bcrypt-hash>
			# user JDJhJDE0...
		}
	}
}

Manual review needed

  • auth_basic for "/admin" was scaffolded — generate hashes with "caddy hash-password".

What this converter does

This tool parses a single nginx server block and rewrites it as the equivalent Caddyfile. It maps the most common directives — server_name, listen, root, location, proxy_pass, try_files, return 301, TLS certificates, gzip, headers, and basic auth. Anything it cannot translate is flagged in a notes panel so you can fix it by hand. Conversion happens entirely in your browser — your config never leaves the page.

Nginx to Caddyfile directive mapping

NginxCaddyfileNotes
server_name example.comexample.com (site address)Multiple names → comma-separated
listen 80; listen 443 ssl(no directive)Caddy auto-enables HTTPS for domains
root /var/www/siteroot * /var/www/siteCaddy needs a matcher (use *)
index index.htmlfile_serverfile_server serves index files automatically
location / { try_files $uri =404 }handle /* { try_files {path} =404; file_server }{path} replaces $uri
proxy_pass http://127.0.0.1:3000reverse_proxy 127.0.0.1:3000Strip http:// — Caddy infers it
proxy_set_header X-Real-IP $remote_addr(omitted)reverse_proxy sets X-Forwarded-* automatically
return 301 https://example.com$request_uriredir https://example.com{uri}Use redir for permanent redirects
ssl_certificate /path/cert.crttls /path/cert.crt /path/key.keyCombine cert + key on one line
add_header X-Frame-Options SAMEORIGINheader X-Frame-Options SAMEORIGINCaddy header replaces by default
gzip onencode gzipUse 'encode gzip zstd' for both
auth_basic / auth_basic_user_filebasicauth { user <bcrypt-hash> }Generate hash with caddy hash-password
client_max_body_size 50Mrequest_body { max_size 50MB }Caddy uses MB/GB suffixes

Nginx variables → Caddy placeholders

Caddy uses {placeholder} braces instead of nginx $variable syntax. This converter rewrites the most common ones inside proxy_set_header values automatically:

NginxCaddy
$host{host}
$http_host{host}
$remote_addr{remote_host}
$proxy_add_x_forwarded_for{remote_host}
$scheme{scheme}
$request_uri{uri}
$uri{path}
$args / $query_string{query}

Why migrate from Nginx to Caddy?

  • Automatic HTTPS. Caddy provisions and renews Let's Encrypt or ZeroSSL certificates with zero configuration. No certbot, no cron jobs, no renewal scripts.
  • Simpler config. A typical Caddyfile is roughly 40-60% shorter than the equivalent nginx config because sensible defaults (HTTPS redirect, security headers, HTTP/2, HTTP/3 via QUIC) are on by default.
  • First-class HTTP/3. Caddy enables HTTP/3 (QUIC) by default; nginx requires a build flag and manual tuning.
  • Live config reload. Caddy can reload via API without dropping connections — handy for dynamic environments.
  • Single static binary. Caddy ships as one Go binary with no runtime dependencies, which simplifies containers and edge deployments.

What this tool can't convert

Some nginx features have no direct Caddyfile equivalent or require a custom Caddy module. The converter will flag these in the notes panel:

  • Complex regex locations (~ / ~*) — Caddy uses named matchers
  • if blocks (nginx's if is evil) — refactor with @matcher blocks
  • map directives — use Caddy map handler
  • FastCGI / PHP-FPM (fastcgi_pass) — use php_fastcgi
  • Stream (TCP/UDP) blocks — Caddy needs the layer4 module
  • Rate limiting and WAF rules — require third-party Caddy modules
  • Upstream load-balancing pools — express as space-separated upstreams in reverse_proxy

Frequently Asked Questions

Is Caddy similar to Nginx?
Yes — Caddy and Nginx are both production-grade HTTP servers and reverse proxies, and they fill the same role in a stack. The big differences are philosophy and defaults: Nginx is a battle-tested C server with a configuration language built around contexts and directives, while Caddy is a Go binary that ships with automatic HTTPS, HTTP/3, and a much shorter config format (the Caddyfile). Both can serve static files, terminate TLS, reverse-proxy applications, do basic auth, compress responses, and handle thousands of concurrent connections.
What is the difference between Nginx and Caddy?
The biggest practical difference is that Caddy provisions and renews TLS certificates automatically — you write a domain name in your Caddyfile and HTTPS just works. Nginx requires you to install certbot (or another ACME client), generate certs, and wire up renewal. Caddy also enables HTTP/2 and HTTP/3 by default, while Nginx needs explicit configuration and (for HTTP/3) a custom build. Nginx wins on raw throughput for static workloads and has a much larger ecosystem of modules, third-party tutorials, and battle-tested production deployments.
Is Caddy faster than Nginx?
For most reverse-proxy and dynamic workloads they perform within a few percent of each other — the network and the upstream app are usually the bottleneck. Nginx tends to win benchmarks for serving static files and very high concurrent connection counts because it&apos;s written in C and has had two decades of micro-optimization. Caddy uses more memory than Nginx (Go runtime + garbage collector) but is fast enough that the productivity gains from automatic HTTPS and a simpler config almost always outweigh the difference. If you need to squeeze out the last 5% of static-file throughput, stay on Nginx; otherwise Caddy is more than fast enough.
Where should I put my Caddyfile?
By default Caddy looks for a file named exactly Caddyfile (no extension) in the current working directory when you run caddy run or caddy start. On Linux installs from the official package, the canonical location is /etc/caddy/Caddyfile, and the systemd service loads it automatically. In Docker, mount your Caddyfile to /etc/caddy/Caddyfile inside the official caddy image. You can also point to a different path explicitly with caddy run --config /path/to/Caddyfile.
How do I reload Caddy after editing the Caddyfile?
Run caddy reload from the directory containing your Caddyfile, or caddy reload --config /etc/caddy/Caddyfile if it lives elsewhere. This validates the new config and applies it with zero downtime — existing connections keep their old config until they finish. On systemd-based Linux installs you can also run systemctl reload caddy. If the new config is invalid, the reload fails and Caddy keeps running the previous config, so you never accidentally take the site down with a typo.

Related Tools

Need to manage SSH connections?

SSH Workbench lets you connect, browse files, and manage servers visually.

Try SSH Workbench Free