Caddy Web Server on Ubuntu 16.04

caddy web server


Across our many tutorials we have looked at hundreds of different technologies. In almost every article, we’ve based our work on Apache or NGINX based servers.
However, there is a new web server which is gaining popularity due to its overall simplicity… welcome to the world of Caddy web server! This web server is entirely written in Go, and was first released in 2015. Caddy configuration is based on Caddyfile, and, as we will see in an example, these files are incredibly easy to write and manage.

What’s really got us excited, however, is the fact that it integrates Let’s Encrypt by default and without any manual configuration!

Caddy Features

  • Automatic HTTPS on by default, via Let’s Encrypt
  • HTTP/2 by default
  • Static files in the current working directory
  • All server types, directives, DNS providers, and other features are just plugins
  • Can be used like a library in other Go programs
  • Configurable to run system commands at startup and shutdown
  • Caddy is a single executable file with no dependencies at all except from the kernel

Impressive right? And this is not even an exhaustive list of the features available!

Now that you’re excited. Let’s take a look at how to install and use Caddy web browser on an Ubuntu 16.04 server.

Install Caddy Web Server

Caddy provides an installation script which downloads and installs Caddy binaries. As anticipated in the introduction, this web server has no dependencies.

Execute the following command:

$ curl | bash

During the installation, the script will prompt for your password in order to gain administrative privileges.

The output will be:

 % Total % Received % Xferd Average Speed Time Time Time Current
 Dload Upload Total Spent Left Speed
100 5593 100 5593 0 0 3696 0 0:00:01 0:00:01 --:--:-- 3696
Downloading Caddy for linux/amd64...
Download verification OK
Putting caddy in /usr/local/bin (may require password)
[sudo] password for gmolica: 
Caddy 0.10.6
Successfully installed

Once the script has completed it’s work, Caddy binaries will be installed and ready to use, and, as we can see, caddy is on the /usr/local/bin/ directory.

What’s important to note is that the installation process will not create any system-wide configuration, so, this part is up to you. Luckily, the process is simple.

Configure Caddy

By default, Caddy will use the cthe directory it is being executed from as the root of the site, so, if you execute it from $HOME, it will use this as its root. This means, of course, that with Caddy it’s really easy to work on sites locally.

To execute:

$ caddy

The terminal will show the following message:

Activating privacy features... done.
WARNING: File descriptor limit 1024 is too low for production servers. 
At least 8192 is recommended. Fix with "ulimit -n 8192".

Right now, we can ignore the WARNING and note that Caddy runs on localhost, on port 2015.

Going with a web browser to http://your_server_IP:2015 could redirect to a 404 Not Found error page. This is due to the fact that the directory Caddy is using as its root does not contain a web site. Before moving on, create the required directories:

Creating Required Directories

First of all, create a directory that will contain the main Caddyfile:

# mkdir /etc/caddy

Change its owner to the root user and its group to www-data:

# chown -R root:www-data /etc/caddy

Create a second directory, where Caddy will store the SSL certificates and private keys:

# mkdir /etc/ssl/caddy

Change its owner to www-data:

# chown -R www-data /etc/ssl/caddy

Change the permissions, as follows:

# chmod 0770 /etc/ssl/caddy

Next, create the directory that will contain the site, /var/www:

# mkdir /var/www

This directory will be owned by www-data:

# chown www-data:www-data /var/www

Download the Caddy Unit File

By default, Caddy will not install itself as a systemd service, but the project provides an official unit file. Download it with the following command:

# curl -s -o /etc/systemd/system/caddy.service

Looking at this file we will note the following lines:

; Letsencrypt-issued certificates will be written to this directory.

; Always set "-root" to something safe in case it gets forgotten in the Caddyfile.
ExecStart=/usr/local/bin/caddy -log stdout -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp

This is why we set up those directories in the previous steps.

Create an empty Caddyfile:

# sudo touch /etc/caddy/Caddyfile

Execute the following commands to enable Caddy to run on boot:

# systemctl daemon-reload
# systemctl enable caddy

Check its status:

# systemctl status caddy
â caddy.service - Caddy HTTP/2 web server
 Loaded: loaded (/etc/systemd/system/caddy.service; enabled; vendor preset: en
 Active: inactive (dead)

Allow HTTP and HTTPS Connections

Through ufw, allow both HTTP and HTTPS connections so  that Caddy will be able to correctly serve users:

# ufw allow http
# ufw allow https

Testing Caddy

Last step is to test Caddy to be sure that everything has been done correctly.

Edit Caddyfile

Previously, we created an empty Caddyfile. Now, it’s time to populate it. Open with a text editor:

# $EDITOR /etc/caddy/Caddyfile

In that file, paste the content: {
 root /var/www
 tls [email protected]

Note: the tls line contains the email address that will be used by Caddy to obtain SSL certificates from Let’s Encrypt.

Save and close.

Start Caddy:

# systemctl start caddy

Create a Web Page

Create a web page for testing Caddy:

$ echo '<h1>Website using Caddy</h1>' | sudo tee /var/www/index.html

Use the same root that you set up in the Caddyfile.

Now, with a web browser, just go to, and you will see our test page!


We have seen how to install and use Caddy. Note how easy it can be to create Caddyfile to customize the server behaviour! Also keep in mind that the ease of use becomes even more evident in more complex environments.