Step-by-Step Guide: Building a Custom Caddy Web Server with DuckDns for Auto SSL | Ubuntu 22.0 TLS

Step-by-Step Guide: Building a Custom Caddy Web Server with DuckDns for Auto SSL | Ubuntu 22.0 TLS

How to Build a Custom Caddy Web Server with DuckDns on Ubuntu 22.04 TLS

In this article I will focus on building a custom caddy web server to support DuckDns. This caddy web server setup will allow you to serve multiple websites using a DuckDns url including an auto generated SSL certificate using let's encrypt acting as DuckDns SSL integration.

💡
At the end of the article, you will find a bash script to build caddy DuckDns on ubuntu 22.04 TLS

Building custom caddy version

To build a caddy version locally supporting DuckDns, two dependencies are required. You need to install go version 1.20.1 and xcaddy.

This setup was tested on Ubuntu 22.04 TLS but it should work with any Linux distribution with slight modifications of the variables and the package manager commands if needed.

Install go 1.20.1

We are going to manually install a specific version of go . You can try any other versions or install it from the package tool of your operating system but you may run into compilation issues when trying to build caddy.

This can be downloaded from the official go website:

All releases - The Go Programming Language

As I am installing go on Ubuntu 22.04 TLS amd64, I will use the amd64 architecture. You can get yours using the following command:

uname -m

Now we can use wget to download the file and save it to the /tmp location using:

wget https://go.dev/dl/go1.20.1.linux-amd64.tar.gz -O /tmp/go1.20.1.linux-amd64.tar.gz

The next step is to just extract the downloaded file. As we downloaded the go source files manually, we will extract them in the optional location which is the /opt using:

sudo tar -C /opt -xzf /tmp/go1.20.1.linux-amd64.tar.gz

This will add the go binary to /opt/go/bin/

This path is not in the loaded paths location by default , we will create a soft link to /usr/local/bin directory to be able to execute go without using the full path. This can be done by executing:

sudo ln -s /opt/go/bin/go /usr/local/bin/

To check the paths loaded during the shell login we can use:

echo $PATH

Finally logout then login and you should be able to execute the go command.

Verify by checking the version:

go version
#go version go1.20.1 linux/amd64
Automated docker rootless setup
Docker rootless provides a safe and accessible environment to harness the full potential of Docker.

Install xcaddy using apt

This can be installed using the package tool but first we have to add the key and the source list of xcaddy to the sources list. As I am using debian, I will use apt to install xcaddy.

First add the required key and source list

curl -1sLf "https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key" | sudo gpg --dearmor -o /usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg
curl -1sLf "https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt" | sudo tee /etc/apt/sources.list.d/caddy-xcaddy.list

Then update the packages index files which contain information's about available packages and their versions:

sudo apt update
sudo apt install xcaddy

Build caddy DuckDns

As we installed all requirements, we are ready to build the DuckDns version of caddy. This can be done with a single command:

xcaddy build  --with github.com/caddy-dns/duckdns

This command will save the binary to the same location where the command is executed. To add the binary to the PATH , we can just move it using:

sudo mv caddy /usr/local/bin/

Finally, we can verify that caddy is installed correctly by checking the version:

caddy version

Putting everything together

All steps can be executed using a single bash script.

Create a file called e.g caddy-duckdns-build.sh and add the following:

#!/bin/bash

#THIS SCRIPT WILL INSTALL GO, XCADDY AND BUILD CADDY DUCKDNS
#PLEASE NOTE THAT YOU HAVE TO MODIFY THE VARIABLES TO MEET YOUR SYSTEM REQUIREMENTS

#THIS SHOULD RUN AS ROOT
if [ $(id -u) -ne 0 ];then
    echo "[-] Script must run as root"
    exit
fi

#VARIABLES
TEMP_INSTALL_LOCATION="/tmp/caddy"
GO_VERSION="1.20.1"
GO_INSTALL_LOCATION="/opt"

XCADDY_KEY_URL="https://dl.cloudsmith.io/public/caddy/xcaddy/gpg.key"
XCADDY_KEY_FILE="/usr/share/keyrings/caddy-xcaddy-archive-keyring.gpg"
XCADDY_SOURCE_URL="https://dl.cloudsmith.io/public/caddy/xcaddy/debian.deb.txt"
XCADDY_SOURCE_FILE="/etc/apt/sources.list.d/caddy-xcaddy.list"

ARCHITECTURE="amd64"
#RELEASE="jammy"
mkdir $TEMP_INSTALL_LOCATION

#INSTALL GO
if ! which go;then
        echo "[+] Downloading [ go ]"
        if ! wget https://go.dev/dl/go${GO_VERSION}.linux-${ARCHITECTURE}.tar.gz -O $TEMP_INSTALL_LOCATION/go${GO_VERSION}.linux-${ARCHITECTURE}.tar.gz;then
                echo "[-] Failed to download [ go ]"
                exit 1;
        fi
        if ! tar -C $GO_INSTALL_LOCATION -xzf $TEMP_INSTALL_LOCATION/go${GO_VERSION}.linux-${ARCHITECTURE}.tar.gz;then
                echo "[ go ] Extraction failed";
                exit 2;
        fi
        ln -s $GO_INSTALL_LOCATION/go/bin/go /usr/local/sbin/
        go version
else
        echo "[ go ] already installed"
        go version
fi

#INSTALL XCADDY
if [ ! -f $XCADDY_KEY_FILE ];then
        echo "[+] Downloading xcaddy key"
        if ! curl -1sLf "$XCADDY_KEY_URL" | gpg --dearmor -o "$XCADDY_KEY_FILE";then
                echo "[-] Failed to do download [ xcaddy ] key"
                exit 3
        fi
else
        echo "[+] Caddy key found"
fi
if [ ! -f $XCADDY_SOURCE_FILE ];then
        echo "[+] Adding xcaddy source file"
        if ! curl -1sLf "$XCADDY_SOURCE_URL" | tee "$XCADDY_SOURCE_FILE";then
                echo "[-] Failed to do download [ xcaddy ] source file"
                exit 4
        fi
else
        echo "[+] Caddy source found"
fi

#UPDATE THE REPO
echo "[+] Updating repositories"
if ! apt update;then echo "[-] Update failed, please rectify the problem";exit 5;fi

#INSTALL XCADDY
if ! which xcaddy >/dev/null;then
        echo "[+] Installing xcaddy"
        if ! apt install -y xcaddy;then
                echo "[-] Failed to install xcaddy"
                exit 6
        fi
else
        echo "[+] xcaddy already installed"
fi

#BUILD CADDY
if ! which caddy >/dev/null;then
        echo "[+] Build caddy"
        if ! xcaddy build  --with github.com/caddy-dns/duckdns;then
                echo "[-] Failed to build caddy"
                exit 6;
        else
                echo "[+] Caddy built successfully"
                mv caddy /usr/local/sbin/
                caddy version
        fi
else
        echo "[+] xcaddy already installed"
        caddy version
fi

rm -rf $TEMP_INSTALL_LOCATION

In the next article , I will be talking about configuring caddy as reverse proxy, request a real let's encrypt certificate and install caddy as a service.

Automatic HTTPS with caddy as reverse proxy
Caddy is a web server and reverse proxy known for its simplicity and powerful features. With automatic HTTPS, easy configuration, and extensive capabilities, Caddy makes it easy to secure and route traffic to the back-end servers.

Something not working for you ? Feel free to drop a comment!

buy me a coffe