Caddy - a new generation of scalable WebServer written in Go

This article was last updated on: February 7, 2024 pm

When I used Netmaker a few days ago, I found that it replaced Nginx with Caddy, and after using it, I found that it was really simple and easy to use, so I amway.

Caddy is a powerful, extensible platform, written in Go, that serves your sites, services, and applications. If you’re new to Caddy, the way you serve the web will change.


Most people use Caddy as a web server or proxy, but at its core, Caddy is a server of servers. PassNecessary modules, which can assume the role of any long-running process!

Configuration is dynamic and passable Caddy’s API Export. Although no configuration files are required, you can still use them; Most people’s favorite way to configure Caddy is to use it Caddyfile。 The format of the configuration document takes many forms through the configuration adapter, but Caddy’s native configuration language is JSON

Caddy is compiled for all major platforms and has no runtime dependencies.

Beginner’s Guide

We recommend that everyone take a look at ours regardless of experienceGetting Started Guide。 It will provide you with a well-rounded view of your new web server, which will be invaluable for you to continue learning. This tutorial will explore the basics of working with Caddy and help you become familiar with it at a higher level.


  • Run the daemon
  • Try the API
  • Give Caddy a configuration
  • Test the configuration
  • Make a Caddyfile
  • Using the config adapter
  • Start with an initial configuration
  • Compare JSON and Caddyfile
  • Compare APIs and configuration files
  • Runs in the background
  • Zero-downtime configuration overload


  • Installed caddy and curl(Installing Caddy can be referred to.)Over here

To start Caddy as a daemon, use run Subcommands:

caddy run

By default, Caddy’s configuration (“config”) is empty. We can access it using another terminalManagement API to verify this:

curl localhost:2019/config/

ℹ️ Information

Address aboveNoYour website, localhost: 2019, is used to control Caddy’s management endpoints and is restricted to native access by default.

We can make Caddy useful by giving it a configuration. This can be done in a variety of ways, but we will use it in the next section curl toward /load The endpoint makes a POST request.

Your first configuration

In order to prepare our request, we need to make a configuration.

Save it to a JSON file (eg caddy.JSON) :

"apps": {
"http": {
"servers": {
"example": {
"listen": [":2015"],
"routes": [
"handle": [{
"handler": "static_response",
"body": "Hello, world!"

Then upload:

curl localhost:2019/load \
-H "Content-Type: application/json" \
-d @caddy.json

We can verify that Caddy is applying our new configuration to another GET request with the following command:

curl localhost:2019/config/

Then test the new configuration:

$curl localhost:2015
Hello, world!

If you see Hello, world! Congratulations, it worked! It’s always a good idea to ensure that your configuration works as expected, especially before deploying to production.

Your first Caddyfile

Another way to configure Caddy is to use Caddyfile. The configuration we wrote in JSON above can be simply expressed as:


respond "Hello, world!"

Save it to a file named Caddyfile (no extension) in the working directory file.

If Caddy is already running, (Ctrl + c) stop it and run:

caddy adapt

Or you store the Caddyfile somewhere else, or give it a different name:

caddy adapt --config /path/to/Caddyfile

You’ll see the JSON output! What’s going on here?

We just useConfigure the adapterConvert a Caddyfile to Caddy’s native JSON structure.

While we can get this output and make another API request, we can skip all these steps because caddy Commands can do these things for us. If there is a file called a Caddyfile in the working directory and no other configuration is specified, Caddy loads the Caddyfile, adapts it for us, and runs it immediately.

Now that there is a Caddyfile in the current folder, let’s run caddy again:

caddy run

Or if your Caddyfile is somewhere else:

caddy run --config /path/to/Caddyfile

(If you are calling something else that doesn’t start with “Caddyfile,” you’ll need to specify it.) --adapter caddyfile)

As you can see, there are several ways to start Caddy with the initial configuration:

  • The working directory is a file named Caddyfile
  • --config flag (optional, with--adapter flag)
  • --resume flag (if the configuration was previously loaded)

JSON vs. Caddyfile

Now you know, Caddyfile just converted to JSON for you.

Caddyfile looks simpler than JSON, but should you use it all the time? There are pros and cons to each method. The answer depends on your needs and use case.

JSON Caddyfile
Full Caddy functionality The most common Caddy features
Easy to generate Easy to make by hand
Easy to program Difficult to automate
Very expressive Moderate expression
Allow configuration traversal You cannot convert
Partial configuration changes Only the entire configuration can be modified
You can export Unable to export
Compatible with all API endpoints Compatible with some API endpoints
Auto-generated documentation The document is handwritten
Everywhere Niche
More efficient More calculations
A bit boring Pretty interesting
Learn more:JSON structure Learn more:Caddyfile documentation

You will need to decide which one is best for your use case.

Note that JSON and Caddyfile (as wellAny other supported configuration adapters) can be with Caddy’s API Used together. However, if you use JSON, you get the full functionality and API features of Caddy. If you use a configuration adapter, the only way to use the API to load or change the configuration is to do so /load endpoint

API vs. Configuration File

ℹ️ Information

In fact, even the configuration file goes through Caddy’s API endpoint, and the command just wraps those API calls for you.

You also need to decide whether your workflow is API-based or CLI-based. (You can use both APIs and profiles on the same server, but we don’t recommend it: it’s best to have a source of truth.) )

API Configuration files
Use HTTP requests to modify the configuration Use shell commands to modify the configuration
Easy to scale up Difficult to scale
Difficult to do by hand Easy to operate by hand
Really interesting Also interesting
Learn more:API tutorials Learn more:Caddyfile tutorial

ℹ️ Information

Manually managing server configuration using the API is entirely possible with the appropriate tools, such as: any REST client application

Or the choice of configuration file workflow is orthogonal to the use of configuration adapters: you can use JSON, but store it in a file, and use the command line interface; Instead, you can also use Caddyfile and the API.

But most people will use a combination of json + API or Caddyfile + CLI.

As you can see, Caddy is great for a wide variety of use cases and deployments!


Because Caddy is a server, it can run indefinitely. This means in execution caddy run After that, the terminal does not unblock until the process terminates (usually using Ctrl + c).

though caddy run It is the most common and usually recommended (especially when performing system services!), and you can also choose to use it caddy start Start Caddy and let it run in the background:

caddy start

This will allow you to use your terminal again, which is very handy in some interactive headless environments.

Then you have to stop the process yourself because Ctrl + c won’t stop for you:

caddy stop

Or use the API’s/stop endpoint

Reload the configuration

Your server can perform zero-downtime configuration overloads/changes.

Load or change all of the configurations API endpointsAll perfect and with no downtime.

However, when using the command line, it might be easy to use Ctrl + C to stop the server and then restart the server to get the new configuration. Don’t do this: Stopping and starting the server is orthogonal to configuration changes and will cause downtime.

Instead, use the caddy reload command to gracefully modify the configuration:

caddy reload

This is really just using the API under the hood. It will load and, if necessary, adjust the configuration file to JSON, and then gracefully replace the active configuration without downtime.

If there are any errors while loading the new configuration, Caddy rolls back to the last working configuration.

ℹ️ Information

Technically, the new configuration is started before the old configuration is stopped, so in a very short time, both configurations are running! If the new configuration fails, it aborts an error, while the old configuration does not stop at all

Caddy common features

  1. Static file access
  2. Reverse proxy
  3. HTTPS

Static file access

Command line mode

In the terminal, switch to the root of the site and run:

caddy file-server

If you get a permission error, it probably means that your operating system does not allow you to bind to a low port---- So use a high port instead:

caddy file-server --listen :2015

Then open it in your browser (or localhost:2015Check out your website!

Use this if you don’t have an index file, but you want to display a list of files --browse Options:

caddy file-server --browse

You can use another folder as the site root:

caddy file-server --root ~/mysite

Caddyfile way

In the root of the site, create a file named Caddyfile file, which contains the following:





file_server browse



root * /home/me/mysite

Correspond to the above commands.

Reverse proxy

This tutorial assumes that you have a run in on the back-end HTTP service.

Command line mode

Very straightforward, can be directly understood:

caddy reverse-proxy --to

If you don’t have permission to bind to a low port, you can proxy from a high port:

caddy reverse-proxy --from :2016 --to

Caddyfile way

Direct on-configuration:



caddy run Just run

Changing the address of the proxy is easy:



When changing the Caddyfile, make sure that:reload Caddy (or stop and restart it).

useReverse proxy directivesto do a lot of things.


This guide will show you how to use it right awayFully self-managed HTTPS Get up and running.

ℹ️ Information

By default, Caddy uses HTTPS for all sites, as long as it is provided in the configurationhost name。 This tutorial assumes that you want to get a public trusted site (i.e. not “localhost”) over HTTPS, so we’ll use a public domain name and an external port


  • Basic understanding of DNS
  • Registered public domain name
  • External access to ports 80 and 443
  • Installed caddy and curl

In this tutorial, you will with your actual domain name.

Set the A/AAAA record for the domain name to point to the server. You can do this by logging into your DNS provider and managing your domain name.

Verify the correct record with an authoritative lookup before continuing. Replace it with your domain name, if you are using IPv6, put type=A to be replaced with type=AAAA:

curl "" \
-H "accept: application/dns-json"

ℹ️ prompt

All this assumes that you bought the domain name on Cloudflare.
If not, the steps are a bit more complicated.
See this How the domain name is requested for a certificate on DNSPod

Also make sure that your server is reachable from the public interface on ports 80 and 443.

ℹ️ prompt

If you’re on your home or other restricted network, you might need to forward ports or adjust firewall settings

All we need to do is start configuring Caddy with your domain name. There are several ways to do this.


This is the most common way to get HTTPS.

Create a file named Caddyfile (no extension) where the first line is your domain name, for example:


respond "Hello, privacy!"

Then run from the same directory:

caddy run

You will see that Caddy provides a TLS certificate and serves your site over HTTPS. This is possible because your website contains a domain name at its address in a Caddyfile.

file-server command

caddy file-server --domain


reverse-proxy command

caddy reverse-proxy --from --to localhost:9000


What attracted me to Caddy:

  1. Automatic request for renewal of certificates
  2. Caddyfile for simple commands
  3. Written in Go, Caddy is compiled for all major platforms and has no runtime dependencies.



Caddy - a new generation of scalable WebServer written in Go
Posted on
December 13, 2021
Licensed under