Root-Server Tutorial


Caddy Server Setup - The easiest way to provide secure HTTPS connections

Caddy is a web server that is very easy to set up and maintain. It uses Let's Encrypt certificates almost without configuration or additional programs!


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: {

   reverse_proxy localhost:8080


We'll go into detail about the Caddy server configuration later.

An equivalent nginx server config might look like this and it requires additional tools like Certbot:
server {
    listen 80;

    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/;
    ssl_certificate_key /etc/letsencrypt/live/;

An equivalent Apache2 server config might look like this and would require a tool like Certbot as well:
<VirtualHost *:80>

    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    DocumentRoot /var/www/html

    <Directory /var/www/html>
        Options FollowSymLinks
        AllowOverride All
        Require all granted

    Alias /.well-known/acme-challenge/ /var/www/html/.well-known/acme-challenge/


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:

  • A server (e.g. VPS) running a recent version of Ubuntu with access via SSH
    • The server needs a public ipv4 or ipv6 address. netcup VPS / RS servers always have ipv4 and ipv6 addresses.
    • The tutorial might also be applicable to other Linux distributions, especially the Caddyfile part.
    • This tutorial was tested with Ubuntu 22.04.
  • A domain name or a subdomain where you have control over the DNS settings
  • Optional: If you want to create a reverse proxy using Caddy, you need a service running on your server that you want to expose to the outside world.

For this tutorial we will use the domain as an example. If necessary, you should replace this with your own domain name or subdomain, e.g. in the configuration examples.

Step 1 - Setting up the DNS records

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.

Step 1.1 - Getting the IP addresses of your server

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
echo -n -e "\nipv6 address:  " && curl -6

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.

Step 1.2 - Setting up the DNS records

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 > > DNS.

Then add the following entries to the DNS records:

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.

Step 1.3 - Checking the DNS records

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

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.

Step 2 - Installing Caddy

Step 2.1 - Adding the Caddy repository

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:

  • Download and install the repository signing key, so that the packages can be verified:
    • Enter your password when prompted (applies also to the following commands)
curl -1sLf '' | sudo tee /usr/share/keyrings/caddy.asc
  • Set up the repository:
echo "deb [signed-by=/usr/share/keyrings/caddy.asc] any-version main" | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list
  • Update the package cache, so that the packages from the new repository are available:
sudo apt update

Step 2.2 - Installing Caddy

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!

Step 3 - Configuring Caddy

The configuration file of Caddy, the Caddyfile, is located at /etc/caddy/Caddyfile.

Step 3.1 - Checking the default configuration and emptying Caddyfile

To view the file, use the following command:

sudo cat /etc/caddy/Caddyfile
Your Caddyfile should look similar to this:
## 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.

        ## 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:

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

Step 3.2 - Adding the first configuration

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. 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.

Step 3.2.1 - Your first entry: deploying static html files

The first entry will deploy static html files. For this, we will use the file_server directive.

Note: If you've set up a firewall you need to allow incoming connections on port 80 and 443 for Caddy to work.

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 with your own domain or subdomain where you configured the DNS records in step 1.2. {

   root * /usr/share/caddy



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 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.

Step 3.2.2 - Optional: Using Caddy as a reverse proxy

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: {

   reverse_proxy localhost:8080


Make sure that you don't have any other entries for 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.


Contributor's Certificate of Origin

By making a contribution to this project, I certify that:

  1. 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

  2. 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

  3. The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.

  4. 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.

Published 29/09/2023 by Anton Mrosek

Submit your tutorial

Get 60€ netcup vouchers for every published tutorial.