In silence I feel full; With speech I sense emptiness.

Use Caddy as reverse proxy server with free HTTPS certificate


Because of the data loss caused by the previous server OS image replacement, my blog service was stopped for several months, and in the middle of it, my father had a stroke, and I took care of it in my hometown for more than 4 months, so I haven't had time to take care of my personal blog. Today finally fixed it back.

In the middle of this I did a lot of updates, Ruby version updated from 1.9 to 2.7, and Rails also updated from 3.2 to 5.2; In addition, the manual deployment process has been changed to automatic deployment. Another new thing I tried is that I used Caddy instead of Nginx as a reverse proxy server, and used it to get HTTPS certificates directly, which is very convenient.

Previously, I used Nginx as a reverse proxy + acem.sh as a certificate issuer, but this time I used Caddy to do both of their original functions:

  1. Nginx
    1. To listen to port 80/443 and forward the service to the corresponding app service (Rails, in this case)
    2. I started the rails server on multiple ports, so nginx also did the load balancing
    3. To redirect the HTTP request HTTPS
    4. To render static files like JS/CSS directly
  2. acem.sh
    1. To Issue https certificate
    2. To renew certificate after it expires (need to work together with cron)

And if you use Caddy, then the above functions can be done by it all at once. Here are the advantages of using Caddy:

  1. No need to manage and configure HTTPS certificate by myself
  2. No need to configure HTTP to HTTPS redirect
  3. The load balancing policy is very simple to configure, and I feel that its default configuration is also good

It is simply a lazy man's gospel, basically, nothing need to write on their own, the following is the entire content of my configuration file:

hegwin.me {
    root * /var/www/blog/current/public/
    route {
        file_server /assets*
        reverse_proxy :4000 :4001 :4002

Installation and Usage

In my early blog server, the operating system was Ubuntu 12.04. For Ruby and Postgres, I install them by downloading the source code and compiling by myself. Nowadays, I don't want to do this, so I almost always use apt to install it, and caddy can be installed directly by apt.

The official installation documentation has a guide for Ubuntu. But I met some unexpected results. The official installation steps for Ubuntu are as follows:

$ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
$ sudo apt update
$ sudo apt install caddy

There is nothing wrong with this step, and the execution of caddy version also returns normally, except that there is only caddy-api.service in systemctl but not caddy.service, and using caddy start will not read /etc/caddy/ Caddyfile.

So I found this blog: Build Aria2+Caddy2 download site with RaspberryPi , followed by some steps as follows:

$ wget https://github.com/caddyserver/dist/blob/master/init/caddy.service # download caddy.service
$ sudo mv caddy.service /etc/systemd/system/caddy.service

And then you can use systemctl to control Caddy normally, such as systemctl status caddy; I personally still recommend this operation, you can avoid some troubles, such as the permission problem of port 443.

After that, you can configure the Caddyfile as follows

sudo touch /etc/caddy/Caddyfile
sudo vim /etc/caddy/Caddyfile

For Rails app, if you don't use webpacker, the configuration is as follows:

hegwin.me {
    root * /var/www/blog/current/public/
    route {
        file_server /assets*
         # If you use puma or unicorn you can directly use unix domain socket;
         # I'm using thin so I configured ports here
        reverse_proxy :4000 :4001 :4002 

If you're using webpacker, replace the file_server line with file_server /packs*.

Save and refresh:

systemctl reload caddy

Oh yeah, and remember to turn off Apache or Nginx, they may already be using port 80/443. I remember that Ubuntu 12.04 has Apache enabled by default, so you have to turn off Apache before switching to Nginx. I'm using Ubuntu 22.04 now, and I'm very happy that it doesn't specify a default HTTP server, whether it's Apache or Nginx.

< Back