Technology, Tutorial

GETTING RELIABLE SSL CERTS FOR FREE WITH DUCKDNS

What is this?

You’ve discovered the powerful and free tool of DuckDNS (They take donations by the way if you scroll to bottom of page). Now you tried one attempt or another of getting SSL certificates working so you can use it, perhaps, as a home test lab server, but you have endless problems getting the certs working via lets encrypt usual ways. In my case, I was using a DuckDNS version of a container which, after many startups, finally did get the certs automatically, but the wait and pain wasn’t worth it. I decided to make them manually and it turned out that the process was actually pretty easy. That’s what this is

Setup a Directory and Acme Software on Your Server in Which the Commands Will Run

The ssl certificate creation software (Acme) has a script we need to setup and run on the server. Let’s do that:

  1. Create A Directory (use whatever name you want) in a tidy place you like In Which to Do Acme Stuff

mkdir DUCK_ACME

  1. Go into the DUCK_ACME directory

cd DUCK_ACME

  1. Get the Acme Stuff

wget https://github.com/acmesh-official/acme.sh/archive/master.tar.gz

  1. Unpack the Acme Stuff

tar -zxvf master.tar.gz

  1. Slide into the Acme Stuff Directory

cd acme.sh-master/

Run the Scripts

It’s time to actually do stuff now:

  1. Run the script but first changing the ‘your-email` email to yours (and seems to need sudo) and also updated the /path/to/ part to the full path of the directory you just created above in Step 1:

sudo ./acme.sh --install --home path/to/acme.sh --accountemail "your-email@example.com"

  1. Get your DuckDNS token ready.
    Best way I found to do this is: 1) log into duck dns, go to ‘install’ and 2) Go to bottom and select your domain
    and then 3) select ‘linux netcat cron’ (because it neatly extracts the token onto its own line in the example terminal script)
  2. Export the environment variable to the operating system (including the double quotes). If you don’t know what this means or does, go study it or accept that ‘it just does something cool that makes it work”.

export DuckDNS_Token="your-duckdns-token"

Note: after running command there is no confirmation message, just blank terminal line… So “no news is good news” as they say…

  1. Register an zerossl account (seems to be required, whatever it is) making sure to use the full path spelled out like this:
    full/path/to/acme.sh-master/acme.sh --register-account -m your-email@example.com --server zerossl
  2. Manually issue certificate, replacing ‘yourdomain’ with your duckdns subdomain:

./acme.sh --issue --dns dns_duckdns -d yourdomain.duckdns.org --ecc

Note 1: make sure you are running this inside the acme.sh-master directory or, again, that the full path is there
Note 2: This tool shows you the full status of what’s going on and seems to not proceed until things are actually propagated and such. It has countdown clocks in your terminal so you can be aware of progress too. Just wait out the process. As a reference for you, the final message that indicates things happened successfully, is the following (when it arrives):

“And the full-chain cert is in: /home/dellmin/.acme.sh/yourdomain.duckdns.org_ecc/fullchain.cert”

Create a Certificate Directory and Point the Acme Tool’s finalized certs to the Caddy Directory where the certs should be stored.

This section is specifically for Caddy and more specifically for a containerized environment. It may not be perfectly applicable to your setup, so adjust accordingly.

In my example, my Caddy container is located here:

~/.n8n/caddy/
and it has all these sub-directories in it:

/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/sub.myotherdomain.net/

Inside that acme-v02.api.letsencrypt.org-directory directory there is an old domain I successfully ran with Caddy. As such, I will manually create a similarly formatted directory in the acme-v02.api.letsencrypt.org-directory called mydomain.duckdns.org and then I will issue the certificates into that, with this command, path. You update to match your paths.

You may have to find where your system is storing your certificates and update accordingly. This is just my example setup.

Create the Certificate Directory and Issue Certificates

  1. Make directory to host your new SSL certs:

mkdir ~/.n8n/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mydomain.duckdns.org

  1. Issue the certificates to the directory you made

Because this next command has to be run as one chunky command, I am going to use a text editor to make sure it is written correctly before copying/pasting into the command line. You can trust yourself but I don’t trust myself… here is my pre-paste work using my paths which you can copy to a text editor and adjust for yourself before pasting:

./acme.sh --install-cert -d yourdomain.duckdns.org \
--fullchainpath ~/.n8n/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mydomain.duckdns.org/fullchain.pem \
--keypath ~/.n8n/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mydomain.duckdns.org/privkey.pem \
--capath ~/.n8n/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mydomain.duckdns.org/chain.pem   

You can see how huge that is so doing it in a text editor off to the side is probably wise but do what you like.

Note 1: Make sure those backslashes remain at the end of the lines where they are and make sure there is not a backslash at the end of chain.pem. Triple check your paths. Triple check your directories and domain names.

Note 2: Make sure you are still in the acme.sh-master/ (where the .sh script is) directory before you paste. Then copy/paste (…and hope!)

If all worked properly you should see the three installations of the three .pem files with the log report “Installing full chain to: …”

  1. Disable Automatic SSL stuff from the Caddy image

Understand this: when Caddy is started it will try to get new SSL certs if it doesn’t have them. We have to tell Caddy to stop doing that and to use the ones we just wasted our day making. Understand this, too: If you are using containers (like me) in the Caddyfile, it will look for the container paths not the path on your host machine we referenced above. This is likely mostly taken care of in your container startup configs (ie. compose file) but just make sure that the path you list for this next part is does not include the host paths, but only the path from the mount point on the host onwards. This confused me so let me be more clear:

Above we installed the certs on the host machine and into the container with a path like this:

~/.n8n/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mydomain.duckdns.org/

In my setup, the ‘data’ directory is, for lack of a more technical lingo ‘The start of the container”. So, in my Caddyfile, I will omit the ~/.n8n/caddy part at the front and leave it from the shared/startpoint like this:

/caddy/certificates/acme-v02.api.letsencrypt.org-directory/mydomain.duckdns.org/

Now, here is the config we need in our Caddyfile. Change out the yourDomain part and adjust your Caddy file for your own needs. I like to (like above) map it all out in a text editor first and then past when I’m confident of my paths, files, etc:

yourDomain.duckdns.org {
    tls {
        tls /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourDomain.duckdns.org/gcw.duckdns.org.crt /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/yourDomain.duckdns.org/gcw.duckdns.org.key
    }   
  1. Test

Fire up your caddy / duckdns setup on the server.
Try to reach it from outside the network.

For a bonus check, after Caddy is running (because 443 must be exposed and usually happens only after Caddy is running) from a non-server computer outside of its access, run this command to see how the outside world sees the SSL certs. Replace the domain with your newly-issued domain:

echo | openssl s_client -connect yourdomain.duckdns.org:443 -servername yourdomain.duckdns.org 2>/dev/null | openssl x509 -noout -dates -subject

Dealing With Multiple DuckDNS domains on same Network and Same Server

I won’t confuse the blog more by doing this, but just wanted to let you know that I was ultimately able to run multiple duckDNS services on the same machine. I wanted to only let you know that I originally tried doing it with two caddy containers running with two services. Things didn’t go well. My ultimate solution was this, roughly, for your reference:

  • One network that everything will ultimately share in my containered network called ‘proxy_net’
  • One caddy container which joins ‘proxy_net’ network, and which has one Caddyfile handling the duckDNS domains and certificates, forwarding everything to the appropriate services.
  • Pod 1 (example nextcloud with mariadb) running which then also join ‘proxy_net’ and their own internal network
  • Pod 2 (example n8n with postgres) running which they join ‘proxy_net’ and their own internal network

In this setup you have multiple pods / container setups. We will separate out Caddy as its own container and keeping its own configs with itself instead of with the pods. If you are going to jump into podman and containers then I will now present my basic multi-pod setup that worked for me so you can try too. Naw. Actually, I’ll make that a second blog. You can find that MANUALLY CREATING A CONTAINER NETWORK WITH PODMAN


Tagged , , , , , ,

Leave a Reply

Your email address will not be published. Required fields are marked *