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.
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:
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
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.
Something not working for you ? Feel free to drop a comment!