Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

More than 430 friends have joined Er Ge’s programming community. If you also need a good learning environment, click the link to join our big family! This is a private group for Java learning guides + practical programming + LeetCode problem-solving, where you can ask Er Ge questions, get help in creating a learning plan, and work on practical projects together. Let’s go!

Hello everyone, I am Er Ge. Today I want to share an article by my good friend macrozheng. Nginx is a very popular web server with over 16K+ Stars on GitHub, and we often use it for static resource hosting or reverse proxying. Recently, I discovered a brand new web server called Caddy, which has surpassed Nginx with over 38K+ Stars. After trying Caddy, I found it to be much more elegant than Nginx, and it has powerful features, so I recommend it to everyone!

Introduction to Caddy

Caddy is a powerful and highly extensible web server, currently boasting over 38K+ Stars on GitHub. It is written in Go and can be used for static resource hosting and reverse proxying.

Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

Caddy has the following main features:

  • Compared to Nginx’s complex configuration, its unique Caddyfile configuration is very simple;
  • Dynamic configuration changes can be made through its provided Admin API;
  • It supports automated HTTPS configuration by default, automatically obtaining and configuring HTTPS certificates;
  • It can scale to thousands of sites;
  • It can run anywhere without additional dependencies;
  • Written in Go, it guarantees memory safety.

Installation

First, we will install Caddy directly on CentOS 8. Using the DNF tool is undoubtedly the simplest method, and the Docker installation method will be introduced later.

  • Use the following command to install Caddy via the DNF tool. After successful installation, Caddy will be registered as a system service;
dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
  • Use systemctl status caddy to check the status of Caddy. You will find that Caddy has been registered as a system service but is not yet started.
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

Usage

Next, let’s experience the basic usage of Caddy. These are common operations for web servers that you will definitely find useful!

Basic Usage

First, let’s start with a basic usage of Caddy, running it on port 2015 and returning Hello, world!.

  • Directly use the caddy command to output Caddy’s common commands. You can see how to use them from the descriptions, with the commonly used commands highlighted;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • Use the caddy start command to run the Caddy service in the background;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • Caddy uses a JSON format configuration file by default, but since writing JSON format configurations can be cumbersome, it also provides a simpler configuration format called Caddyfile. The following command can automatically convert Caddyfile to JSON configuration;
caddy adapter
  • We can first create a file named Caddyfile with the following content, then use caddy adapter to convert it to JSON configuration, and finally use caddy reload to apply the configuration. This configuration will listen on port 2015 and return Hello, world!;
:2015

respond "Hello, world!"
  • Then we can use the curl command to access localhost:2015, which will return the specified information;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • Of course, we can also use the Admin API provided by Caddy to view configuration information with the following command;
curl localhost:2019/config/
  • The current JSON configuration is as follows. If you were to use JSON configuration directly, you would need to write the following configuration, so using Caddyfile is indeed much more convenient!
{
 "apps": {
  "http": {
   "servers": {
    "srv0": {
     "listen": [":2015"],
     "routes": [{
      "handle": [{
       "body": "Hello, world!",
       "handler": "static_response"
      }]
     }]
    }
   }
  }
 }
}

Caddyfile Basic Syntax

  • The following example will use Caddyfile for configuration, and it is necessary to understand its syntax. The specific syntax rules for Caddyfile are as follows.
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • Here are the keywords in the above image, which will help in understanding.
Keyword Explanation Usage
Global options block Global server configuration Can be used to configure whether to enable HTTPS and Admin API, etc.
Snippet Reusable configuration snippets Once defined, they can be referenced using the import keyword.
Site Block Configuration for a single site Static proxy can be configured using file_server, and dynamic proxy can be configured using reverse_proxy.
Matcher definition Definition of matching By default, directives have a global effect, and this can specify the scope of influence.
Comment Comments Start with the # symbol.
Site address Website address Defaults to using HTTPS; if HTTP is needed, it must start with http://.
Directive Directives Directives give Caddy powerful functionality.

Reverse Proxy

A reverse proxy forwards requests made to your proxy server. It can forward to static resource paths or dynamic service interfaces. Below, we will discuss how to perform static and dynamic proxying using domain names as examples.

Static Proxy

A static proxy forwards requests to different static resource paths. Here, we will proxy requests to docs.macrozheng.com to my documentation project and requests to mall.macrozheng.com to the mall’s frontend project.

  • First, we modify the local host file:
192.168.3.106 docs.macrozheng.com
192.168.3.106 mall.macrozheng.com
  • Then we upload our documentation project and mall frontend project to Caddy’s HTML directory and extract them;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • Modify the Caddyfile with the following configuration, and after completing the modification, use the caddy reload command to refresh the configuration;
http://docs.macrozheng.com {
        root * /mydata/caddy/html/docs
        file_server browse
}

http://mall.macrozheng.com {
        root * /mydata/caddy/html/mall
        file_server browse
}
  • If your Caddyfile format is not quite correct, you will see a warning like the following. Simply use caddy fmt --overwrite to format and rewrite the configuration to resolve it;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • You can access the deployed documentation project via docs.macrozheng.com:
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • You can access the deployed frontend project via mall.macrozheng.com.
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

Dynamic Proxy

A dynamic proxy forwards requests from the proxy server to another service. Here, we will proxy requests to api.macrozheng.com to the API service in the demo environment.

  • First, we modify the local host file, adding the following rule:
192.168.3.106 api.macrozheng.com
  • Modify the Caddyfile with the following configuration, and after completing the modification, use the caddy reload command to refresh the configuration;
http://api.macrozheng.com {
        reverse_proxy http://admin-api.macrozheng.com
}
  • Then you can access the mall-admin API documentation page via api.macrozheng.com/swagger-ui.html.
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

File Compression

If our server has low bandwidth, the website access speed will be slow. In this case, we can enable Gzip compression in Caddy to improve website access speed. Here, we will demonstrate its speed-up effect using the mall frontend project as an example.

  • We need to modify the Caddyfile, using the encode directive to enable Gzip compression. After modifying, use the caddy reload command to refresh the configuration;
http://mall.macrozheng.com {
        root * /mydata/caddy/html/mall
        encode {
            gzip
        }
        file_server browse
}
  • There is a relatively large JS file that is 1.7M before compression;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • After compression, it is 544K, and the access speed has significantly improved;
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!
  • Additionally, we can check the response information. If there is a Content-Encoding: gzip response header, it indicates that Gzip compression has been enabled.
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

Address Rewriting

Sometimes, when our website changes its domain name, users may still be accessing the old domain. In this case, we can use Caddy’s address rewriting feature to redirect users to the new domain.

  • We need to modify the Caddyfile, using the redir directive to rewrite the address. After modifying, use the caddy reload command to refresh the configuration;
http://docs.macrozheng.com {
        redir http://www.macrozheng.com
}
  • At this point, accessing the old domain docs.macrozheng.com will directly redirect to www.macrozheng.com.

Directory Segmentation

Sometimes we need to use the same domain to access different frontend projects, and in this case, we need to distinguish the frontend projects by subdirectories.

  • For example, we need to access various frontend projects via the following paths;
www.macrozheng.com # Access documentation project
www.macrozheng.com/admin # Access backend project
www.macrozheng.com/app # Access mobile project
  • We need to modify the Caddyfile, using the route directive to define the routing, and after modifying, use the caddy reload command to refresh the configuration.
http://www.macrozheng.com {
        route /admin/* {
                uri strip_prefix /admin
                file_server {
                        root /mydata/caddy/html/admin
                }
        }
        route /app/* {
                uri strip_prefix /app
                file_server {
                        root /mydata/caddy/html/app
                }
        }
        file_server * {
                root /mydata/caddy/html/www
        }
}

HTTPS

Caddy automatically supports HTTPS without the need for manual certificate configuration. This is why we needed to use http:// at the beginning of the domain configuration. To use Caddy’s default HTTPS functionality, follow these steps.

  • First, we need to modify the DNS resolution of the domain, which can be set directly on the website where the domain was purchased. Here, we take docs.macrozheng.com as an example;
  • Then use the following command to verify that the DNS resolution record is correct. Note that the configured server’s 80 and 443 ports must be accessible from the external network;
curl "https://cloudflare-dns.com/dns-query?name=docs.macrozheng.com&type=A" \
  -H "accept: application/dns-json"
  • Modify the Caddyfile configuration file as follows;
docs.macrozheng.com {
        root * /mydata/caddy/html/docs
        file_server browse
}
  • Then use the caddy run command to start the Caddy server. Isn’t it very convenient!
caddy run

Docker Support

Caddy also supports installation and usage via Docker, which is basically the same as installing directly on CentOS.

  • First, use the following command to download the Caddy Docker image;
docker pull caddy
  • Then create a Caddyfile configuration file in the /mydata/caddy/ directory with the following content;
http://192.168.3.105:80

respond "Hello, world!"
  • After that, use the following command to start the Caddy service, where we mount the host’s Caddyfile configuration file, Caddy’s data directory, and website directory into the container;
docker run -p 80:80 -p 443:443 --name caddy \
    -v /mydata/caddy/Caddyfile:/etc/caddy/Caddyfile \
    -v /mydata/caddy/data:/data \
    -v /mydata/caddy/html:/usr/share/caddy \
    -d caddy
  • Then use docker exec to enter the Caddy container and execute commands;
docker exec -it caddy /bin/sh
  • Input Caddy commands to operate, and subsequent operations will be the same as if we installed it directly on CentOS.
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

Conclusion

Today, I experienced Caddy, and its powerful directive functionality allows us to achieve various features without excessive configuration, making it truly elegant to use! Especially its ability to automatically configure HTTPS is excellent! Caddy can achieve almost all the functionalities that Nginx can, so you can compare it with the Nginx usage tutorial I wrote earlier, and you will find how elegant it is to use Caddy!

References

Nothing keeps me anchored—except for my purpose. Even though there are roses, shade, and tranquil harbors by the shore, I am a boat without a tether.

Recommended Reading:

  • Is it too much to play Gobang in IDEA?
  • Successfully joined the company
  • Discrimination in outsourcing
  • Let’s cheer everyone up!
Beyond Nginx! The Next-Generation Web Server That Is Elegantly Designed!

Leave a Comment