Introduction
Not every developer in the modern era knows or needs to configure a webserver itself. And even if you do, you might not want to spend hours setting up a huge, complex webserver like Apache or Nginx. That’s where Caddy comes in.
What is Caddy?
Officially, Caddy is a “powerful, extensible platform to serve your sites, services, and apps, written in Go”.
Personally, I like to think of it as a cool, modern webserver that’s easy to set up and use. It is especially great for small projects, personal websites, and APIs (it does not mean it can’t handle bigger projects). I fell in love with it when I just needed something to serve my static files and reverse-proxy to my backend services. Indeed, I could have used Nginx or Apache, but I really wanted to try something else, probably something “lighter”. I was also looking at lighttpd, but I tried Caddy. And I liked it. By the way, the most known feature of Caddy is its automatic HTTPS setup using Let’s Encrypt certificates.
Caddyfile
The configuration of Caddy is done via a Caddyfile
.
Official documentation is available here.
It also supports JSON
configuration and looks like it is a preferred way according to the documentation.
You can also utilise REST API to configure Caddy.
However, you will see most examples in the Caddyfile
format (which internally is converted to JSON).
My opinion is following:
- JSON is verbose but most people are familiar with it
- Caddyfile is more classic way to configure a webserver
- REST API is great for automation and integration with other tools
While I think that some common config language like YAML
or TOML
would be a better choice (maybe I am wrong and having +1 specific format is better), I am fine with Caddyfile
.
JSON seems to be more powerful and flexible, but I am not sure if I need that flexibility for my personal projects.
Too much words about configuration, let’s see an example:
# The most basic Caddyfile
localhost
respond "Hello, world!"
Probably this is the simplest Caddyfile
you can have.
It listens on localhost
and responds with Hello, world!
to every request.
This is a great way to test if Caddy is working.
But you can do much more with Caddy.
Assume you want to serve a static website.
You can do it with a single line in Caddyfile
:
# Serve static files
localhost # or your domain
root * /path/to/your/static/files
This will serve your static files from /path/to/your/static/files
directory.
And if you have few domains and want to serve different content for each of them, you can do it like this:
# Serve different content for different domains
domain1.com {
root * /path/to/domain1/files
}
domain2.com {
root * /path/to/domain2/files
}
Note that you need to have {}
blocks if you want to configure multiple sites.
Official:
Only the first line can be the address(es) of the site, and then all the rest of the file has to be directives for that site.
Reverse Proxy
One of the most common use cases for me is to use Caddy as a reverse proxy. I found it very easy to set up. Here is an example of how you can set up a reverse proxy to your backend service:
# Reverse proxy to backend service
localhost {
reverse_proxy localhost:8080
}
This will forward all requests to localhost:8080
to your backend service.
And indeed, you can additionally serve static files or do anything else in the same Caddyfile
:
localhost {
# Serve static files
handle_path /static/* {
root * /app/staticfiles/
file_server
}
# Serve media files
handle_path /media/* {
root * /app/media/
file_server
}
# Proxy all other requests to Gunicorn
reverse_proxy /* app:8000
# Enable gzip compression
encode gzip
}
Automatic HTTPS
Caddy is known for its automatic HTTPS setup.
And it does it by default.
You don’t need to do anything to get your site served over HTTPS
.
Just make sure your domain is pointing to your server and Caddy will take care of the rest.
You can also configure it to use your own certificates or disable HTTPS
if you want.
Note that even on localhost
Caddy will serve your site over HTTPS
.
So if this is not what you want, you need to explicitly point Caddy to use HTTP
:
# Explicitly use HTTP
http://localhost {
reverse_proxy /* app:8000
encode gzip # Enable gzip compression
}
Yon can use your own certificates like this:
# Use your own certificates
yourdomain.com {
tls /path/to/your/cert.pem /path/to/your/key.pem
reverse_proxy localhost:8080
}
Other Features
Caddy has a lot of other features. There is too much to describe in a single post.
For example, you can use templates
in your Caddyfile
to generate dynamic content.
You can also use plugins
to extend Caddy’s functionality.
Logs, matchers, rate limiting, and many other features are available.
You can use Caddy in so many ways, and it can be as complex as you need it to be. What is good is that ou can start simple. And defaults are just good.
Conclusion
Give Caddy a try.