This tutorial explains how to install and configure the Caddy web server. It also shows how to deploy static files using Caddy and how to run a reverse proxy that, for example, exposes services running on Docker to the outside world.
Due to its configuration file format, Caddy is easy to use and configure. A simple configuration file for a reverse proxy featuring automatic HTTPS might look like this:
my-cool-domain.de {
reverse_proxy localhost:8080
}
We'll go into detail about the Caddy server configuration later.
server {
listen 80;
server_name my-cool-domain.de www.my-cool-domain.de;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location ~ /.well-known/acme-challenge {
allow all;
}
location = /.well-known/acme-challenge/ {
return 404;
}
listen [::]:443 ssl ipv6only=on;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/my-cool-domain.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my-cool-domain.de/privkey.pem;
}
<VirtualHost *:80>
ServerName my-cool-domain.de
ServerAlias www.my-cool-domain.de
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
DocumentRoot /var/www/html
<Directory /var/www/html>
Options FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/
</VirtualHost>
By comparison, the Caddy configuration is much simpler and easier to understand. Caddy also takes care of obtaining and using a Let's Encrypt certificate without any configuration!
So let's get started on how to set up Caddy on your own server.
For this tutorial you need the following:
Caddyfile
part.For this tutorial we will use the domain my-cool-domain.de
as an example. If necessary, you should replace this with your own domain name
or subdomain, e.g. in the configuration examples.
For using your domain with your server, you must set up the DNS records to properly point to the public ipv4 and/or ipv6 address of your server. If both are set, the client will choose whether to connect via ipv4 or ipv6.
First, we need to find out the public ipv4 and ipv6 addresses of your server. You can do this with the following command:
echo -n -e "\n\nipv4 address: " && curl -4 ifconfig.co
echo -n -e "\nipv6 address: " && curl -6 ifconfig.co
Keep a note of your server's ipv4 and ipv6 addresses. We will need them in the next step.
If you're seeing something like: ipv6 address: curl: (7) Couldn't connect to server
, then your server might not have
an ipv6 address. In this case you can use the ipv4 address only, and it will just work fine.
Your DNS records can be changed by your DNS provider. If you haven't changed the default settings, this is most likely the
place where you bought your domain.
If you purchased your domain at netcup, you can change the DNS records in the Customer Control Panel. There you need to
select Domains
> my-cool-domain.de
> DNS
.
Then add the following entries to the DNS records:
Type | Host | Value |
---|---|---|
A | @ | ipv4 address of your server |
AAAA | @ | ipv6 address of your server |
If you're missing either ipv4 or ipv6, you can omit the corresponding entry.
In principle, it can take up to 24 hours for the DNS records to be updated. However, it usually takes only a few minutes. To check whether the DNS records have been updated, use the following command:
dig +short my-cool-domain.de
If you see the ipv4 and/or ipv6 address of your server, the DNS records have been updated and you can continue with the next step.
As Caddy is not available in the default Ubuntu repositories, we'll start by adding the Caddy repository. To do so, carry out the following steps:
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo tee /usr/share/keyrings/caddy.asc
echo "deb [signed-by=/usr/share/keyrings/caddy.asc] https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main" | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
Now that the repository has been added, we can install Caddy with the following command:
sudo apt install caddy
Congratulations! You have successfully installed Caddy on your server!
The configuration file of Caddy, the Caddyfile
, is located at /etc/caddy/Caddyfile
.
Caddyfile
To view the file, use the following command:
sudo cat /etc/caddy/Caddyfile
## The Caddyfile is an easy way to configure your Caddy web server.
#
## Unless the file starts with a global options block, the first
## uncommented line is always the address of your site.
#
## To use your own domain name (with automatic HTTPS), first make
## sure your domain's A/AAAA DNS records are properly pointed to
## this machine's public IP, then replace ":80" below with your
## domain name.
:80 {
## Set this path to your site's directory.
root * /usr/share/caddy
## Enable the static file server.
file_server
## Another common task is to set up a reverse proxy:
## reverse_proxy localhost:8080
## Or serve a PHP site through php-fpm:
## php_fastcgi localhost:9000
}
## Refer to the Caddy docs for more information:
## https://caddyserver.com/docs/caddyfile
To configure Caddy, the easiest way is to start with a blank Caddyfile
and add the configuration step by step.
To delete the default contents of the Caddyfile
, use the following command:
sudo truncate -s 0 /etc/caddy/Caddyfile
If you wish, you can verify that the Caddyfile
is indeed empty by checking the contents again:
sudo cat /etc/caddy/Caddyfile
Now we can add our first configuration to the Caddyfile
. We will start with a simple configuration to display the
static html page that came with the caddy installation.
To open and edit the Caddyfile
, use the following command:
sudo nano /etc/caddy/Caddyfile
To save the file, press CTRL + S
. To exit the editor, press CTRL + X
. Make sure to always save your
changes.
In the following steps only parts of the Caddyfile
will be shown. Different configurations can in principle
simply be placed one below the other. However, you have to make sure that there is only one entry for one
name (e.g. my-cool-domain.de
). This is important for domains as well as subdomains! If you have multiple entries for a
name, Caddy will fail to start because it is not clear which entry should be used for the name.
The first entry will deploy static html files. For this, we will use the file_server
directive.
For example, you can add the following lines to the Caddyfile
.
The file_server
will deploy files from the directory specified in the root
directive. The root
directive must be specified before the
file_server
directive.
Remember to replace my-cool-domain.de
with your own
domain or subdomain where you configured the DNS records in step 1.2.
my-cool-domain.de {
root * /usr/share/caddy
file_server
}
To activate your changes, you need to let Caddy reload the configuration using the following command:
sudo systemctl reload caddy
To check if Caddy is running and for viewing some debugging output, e.g. if there is an error in your Caddyfile
, use the following command:
sudo systemctl status caddy
Now you can open your domain in your browser and you should see the default Caddy page at your domain/subdomain. Just enter https://my-cool-domain.de in your browser and you should see the default Caddy page. If this doesn't work right away, wait a minute because Caddy needs to request and set up the TLS certificate. If you pay close attention and depending on the browser, you'll see a padlock icon in the address bar indicating that the connection is encrypted using https. In the background Caddy has requested a TLS certificate from Let's Encrypt and configured it for your domain.
If you have a service running on your server that you want to expose to the outside world, you can use Caddy as a reverse proxy.
For this purpose, you can use the reverse_proxy
directive. The reverse_proxy
directive will forward all requests to
the specified address.
If you have a webservice running on port 8080 on your server, you can use the following configuration to expose it to the outside world:
my-cool-domain.de {
reverse_proxy localhost:8080
}
Make sure that you don't have any other entries for my-cool-domain.de
in your Caddyfile
or Caddy will fail to start.
To activate your changes, you need to let Caddy reload the configuration using the following command:
sudo systemctl reload caddy
In this tutorial you've learned how to set up the server with two basic configurations. However, with Caddy many other options are available, and even the configurations shown can be extended.
This information is available in the caddy documentation.
If you like, you can try out other directives from the documentation, just as we tried out the other configurations in this tutorial.
Just add the directives to the Caddyfile
and reload Caddy with sudo systemctl reload caddy
.
I find working with Caddy and the Caddyfile
very easy and intuitive. I hope you feel the same way!
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
By making a contribution to this project, I certify that:
The contribution was created in whole or in part by me and I have the right to submit it under the license indicated in the file; or
The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same license (unless I am permitted to submit under a different license), as indicated in the file; or
The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
I understand and agree that this project and the contribution are public and that a record of the contribution ( including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the license(s) involved.