Having to manage SSL certificates is a chore no developer wants to deal with. It can be a hassle to remember to renew them, to set them up, to upload the right files to the right folder.
In this tutorial I want to show you how to serve your web application over HTTPS without creating certificates manually. Instead weâre going to use caddy - open source web server with automatic HTTPS written in Go.
I recently stumbled upon caddy when I was automating the process of loading a VM with the source code of a web app, then exposing the app on a public address over HTTPS.
Ideally, I envisioned the steps to be more or less 1) run the vm, 2) tweak a few DNS settings, 3) copy the source and 4) run the app. Thanks to caddy I managed to preserve that sequence without dealing with certificates myself.
How does caddy work?
Serving a website with caddy can be summarized in 3 steps:
- Create the Caddyfile
- Configure your web server in Caddyfile (for example saying âmake iamawesome.com serve those filesâ)
- Run
caddy start
Thatâs it, https://iamawesome.com will be accessible shortly after â From here on caddy will also handle renewing the ceretificate!
How is the certificate created exactly?
Obtaining a publicly-trusted SSL certificate requries a validation process which boils down to up to three challenges that caddy will perform:
If the selected challenges are sorted out correctly caddy will proceed with creating the certificate.
Under the hood Caddy uses the well-known Letâs encrypt Certificate Authority to actually issue the certificate for your website.
Prerequisites
- some command line experience
brew install caddy
- ruby 2.6.3, node 12.4.0 + yarn
Run your static website with caddy
Running a web server to serve a static website on localhost is as easy as:
caddy file-server --domain localhost
given that youâre in the root directory of your site (where your index.html resides) and the default port 80 is available.
â ď¸ caddy commands may require sudo permissions to spin the web server.
Alternatively, to indicate root folder you can:
caddy file-server --root /path/to/your/website
You can also specify another port to bind on:
caddy file-server --listen :8085
Letâs create a âhello worldâ static website and serve it on https://app.localhost:8085:
mkdir mywebsite && cd mywebsite
echo 'Hello world!' > index.html
caddy file-server --domain app.localhost --listen :8085
Congrats! Open https://app.localhost:8085 and see your website served over HTTPS đ
Configuring the web server in command line in this case is an alternative to creating a Caddyfile. To run it on the same address using a Caddyfile, the file should contain:
app.localhost:8085
root * /path/to/your/mywebsite
file_server
then run caddy in the folder of your Caddyfile:
caddy start
Run your dynamic web app with caddy
In the spirit of the previous Docker tutorials (Part 1 & Part 2) letâs use a Todos app that consists of a Vue.js single page app and a Rails app in api mode. Go ahead and clone the Todos from here.
Install libraries for both parts & set the databse:
cd todos-api && bundle install && rails db:setup
cd ../todos-app && yarn install
Build Vue.js app:
yarn build
Run rails api (in another terminal):
cd ../todos-api && rails s
Now if we wanted to serve only the Rails api over https we can simply make use of caddyâs reverse proxy mode:
caddy reverse-proxy --from api.localhost --to 127.0.0.1:3000
given that weâve run Rails server on port 3000
Letâs serve the front-end part on app.localhost and the back-end on api.localhost. Hereâs the content of the Caddyfile:
api.localhost {
reverse_proxy * localhost:3000
}
app.localhost {
root * /full/path/to/todos-app/dist
file_server
try_files {path} ./index.html
}
Here with try_files directive we set ./index.html as a default for all missing files. That might also be suitable for an error page like 404.html or similar. Make sure to repalce /full/path/to/todos-app/dist with the full path to the todos-app/dist folder on your machine.
Again run caddy start
, then open https://app.localhost and start adding todos securely đ
Now if Rails api was namespaced with /api/ we could serve the whole Todos app (Vue.js & Rails apps) on the same domain like myapp.localhost. Then the Caddyfile will look a bit different:
myapp.localhost {
reverse_proxy /api/* localhost:3000
root * /full/path/to/todos-app/dist
file_server
}
â ď¸ In all of the examples we used localhost as the main domain address. In those cases caddy will use its internal certificate authority to create the certificates (self-signed). However, when using caddy in production instead of myapp.localhost youâll use your real domain like awesometodos.com, then caddy will use its default CA - Letâs encrypt
Certificate issue limits
Letâs Encrypt is the default CA of caddy as we have already mentioned, hence caddy depends on Letâs Encrypt rate limits:
- 50 certificates per week (1 certificate for 1 registered domain)
- 100 subdomain names per certificate (in case you want to combine many subdomains in 1 certificate)
- 5 renewals per certificate per week
- 5 validation failures per hostname per hour
Those are the limits the youâre likely to run into. There are a couple more that youâre unlikely to touch, however you can find all the data on the official Letâs Encrypt rate limits page if you want to be on the safe side.
I personally got stung by the last one - 5 validation failures per hour. As I described above part of the setup that I was adding caddy to involved configuring some DNS settings. While tinkering with those settings, then waiting for them to persist and running caddy at the same time I started getting âtoo many failed authorizations recentlyâ. So I had to wait for an hour to spin the web server again and test my setup. Luckily my caddy configuration was relatively simple and I didnât see that error again.
I highly recommend using Letâs encrypt staging environment while developing locally and testing your caddy setup, especially if itâs a complex one. The staging environment has much bigger rate limits and so itâs easier to debug connectivity problems and others.
I hope that article was helpful and caddy will come in handy to you at some point đ¤
Comments