Caddy is a great web server built with Go and can be used for a multitude of things. Here at Vizalo we use it on nearly all of our servers that power our network.
This guide explains how to set up Caddy as a reverse proxy that routes traffic to different backend services based on URL paths. This is useful when you have multiple services running on different ports and want to expose them under a single domain.
Basic Setup
Create aCaddyfile
in your project directory:
example.com { handle /api/* { reverse_proxy localhost:3000 } handle /admin/* { reverse_proxy localhost:8080 } handle /* { reverse_proxy localhost:5000 }}
This configuration will:
- Send
/api/*
requests to a service running on port 3000 - Send
/admin/*
requests to a service running on port 8080 - Send all other requests to port 5000
A More Complete Example
Here's a more practical example that includes common settings you might need:
example.com { # API Service handle /api/* { reverse_proxy localhost:3000 { header_up Host {upstream_hostport} header_up X-Real-IP {remote_host} header_up X-Forwarded-For {remote_host} } } # Admin Dashboard handle /admin/* { reverse_proxy localhost:8080 { # Health checks health_uri /health health_interval 30s # Timeout settings timeout 30s } } # Frontend App handle /* { reverse_proxy localhost:5000 { # Load balancing lb_policy round_robin lb_try_duration 30s } # Enable compression encode gzip } # Global options log { output file /var/log/caddy/access.log format json }}
Running Multiple Backend Services
For testing, you might run these simple backend services:
# API Service (Node.js/Express)node api.js# Runs on :3000# Admin Dashboard (Go)go run admin.go# Runs on :8080# Frontend (React)npm start# Runs on :5000
Verifying the Setup
Test your configuration:
# Test API endpointcurl example.com/api/users# Test admin endpointcurl example.com/admin/dashboard# Test frontendcurl example.com
Common Patterns
Stripping Path Prefixes
If your backend service doesn't expect the/api
prefix:
handle /api/* { uri strip_prefix /api reverse_proxy localhost:3000}
Adding Headers
Add authentication headers or API keys:
handle /api/* { reverse_proxy localhost:3000 { header_up X-API-Key {env.API_KEY} }}
That's it. The beauty of Caddy is that it handles HTTPS certificates automatically and has sensible defaults for most settings. Most of the "extra" configurations shown above are only needed for specific use cases.
Top comments(1)

- Email
- LocationBrisbane, Australia
- WorkSoftware Developer at ABC News Digital
- Joined
Thanks for this. Just pointing out that if you use this config and then try to go to/api
(without the trailing slash) it will be handled by the end /* fallback. Seems like you can fix this by doinghandle /api*
or by doing a redirect:
handle /art { redir * /art/ }
For further actions, you may consider blocking this person and/orreporting abuse