Letsencrypt SSL Certs: Difference between revisions
Wikisailor (talk | contribs) |
Wikisailor (talk | contribs) |
||
| Line 144: | Line 144: | ||
Β nigel ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload apache2, /usr/bin/systemctl reload nginx | Β nigel ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload apache2, /usr/bin/systemctl reload nginx | ||
This will allow systemctl reload apache2 to be run without adding a password | This will allow systemctl reload apache2 to be run without adding a password | ||
===Automation Hook === | |||
To ensure the script runs every time a certificate is successfully renewed, use the reconfigure command on Raisin: | |||
sudo certbot reconfigure --cert-name seaoffate.net --deploy-hook /usr/local/bin/deploy-wildcard.sh | |||
===Docker Volume Mapping (For Blackberry & Quince)=== | |||
Since these nodes run on Docker, the certificates sitting on the host OS don't help the containers unless they are "mapped" in. | |||
Using Certs in Docker | |||
On Docker nodes like Quince, do not install Apache. Instead, map the certificates into your docker-compose.yml volumes: | |||
volumes: | |||
Β - /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro | |||
Β - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro | |||
Revision as of 15:45, 16 February 2026
Introduction
We chose to use Letsencrypt SSL certificates in addition to the Cloudflare origin certs because we occasionally need to serve SSL websites and services directly and while the cloudflare origin certs work well and are easy to setup, they are not publicly recognised. To set up the ACME LetsEncrypt service (specifically using acme.sh) on Raisin' with Cloudflare DNS, we will want to use a wildcard cert so that we don't have to keep on adding to a growing list of domain names
Installation
To set up the certbot Let's Encrypt service specifically using cert bot on the reverse proxy, Raisin, with Cloudflare DNS. Since we are using a wildcard, the DNS-01 challenge is the only way to go, and using the Cloudflare API makes it completely automated. The reason for choosing Raisin for the cert download is that it will nearly always need to be used on Raisin as it is the host that Pfsense directs all https traffic to.
Install certbot
This setup ensures we get our wildcard certificates without needing a webserver to be reachable from the internet, keeping our security tight.
ποΈ Phase 1: Clean Up & Core Install
Ubuntu 24.04 (Noble) likes its packages to be "clean." Mixing apt and snap is the most common way to break SSL renewals. To purge any old apt versions:
sudo apt-get remove certbot
Install the Snap core (the "engine" for snaps)
sudo snap install core; sudo snap refresh core
Create the Symlink: (This ensures when we type certbot, the system actually finds the snap version.)
sudo ln -s /snap/bin/certbot /usr/bin/certbot
πCloudflare API Token
To get the Cloudflare API Token, we need to head into the Cloudflare dashboard. Since we have both .net and .uk domains, we can actually handle them with a single command or separate ones depending on whether we want one "combined" certificate or two distinct ones. in our case we will get two separate keys
- Log in to your Cloudflare Dashboard.
- Click on the User Profile icon (top right) and select My Profile.
- Click API Tokens in the left sidebar.
- Click Create Token.
- Find the template "Edit zone DNS" and click Use template.
- Permissions: Ensure it says Zone - DNS - Edit (and optionally Zone - Zone - Read).
- Zone Resources: * If you want one token for both domains, select Include - All zones.
- If you want to be extra secure, select Include - Specific zone and add both seaoffate.net and seaoffate.uk.
- Click Continue to summary and then Create Token.
- Copy the token immediately! Cloudflare won't show it to you again.
π Phase 3: The Cloudflare Plugin & Secret
Since we want *.seaoffate.net and *.seaoffate.net Certbot needs to "talk" to Cloudflare to create a temporary TXT record. We have two choices here based on your cloudflare_net.ini and cloudflare_uk.ini setup. If we had wanted a single certificate that covers both domains (ideal for a single load balancer like Raisin), we could have used just one .ini file as long as the API token inside has permission for both zones. However, we prefer to keep them separate so we just ran the command twice and have two separate files. Certbot is smart enough to create two separate renewal profiles in /etc/letsencrypt/renewal/.
- To Authorize the plugin
sudo snap set certbot trust-plugin-with-root=ok
Install the Cloudflare DNS plugin
sudo snap install certbot-dns-cloudflare
Create the Credentials File It's best practice to keep this in the /etc/letsencrypt directory, note we also have a cert for the .uk
sudo mkdir -p /etc/letsencrypt/cloudflare sudo nano /etc/letsencrypt/cloudflare/cloudflare_net.ini
Add your API Token Note: Use a Token, not your Global Key. It only needs "Zone:DNS:Edit" permissions. we repeat this step to get the .uk key
dns_cloudflare_api_token = 0123456789abcdefyourtokenhere
Then the same for the .uk key
sudo nano /etc/letsencrypt/cloudflare/cloudflare_uk.ini
and copy the other key for the .uk domain
dns_cloudflare_api_token = 0123456789abcdefyourtokenhere
Lock down the files (Safety First!)
sudo chmod 600 /etc/letsencrypt/cloudflare/cloudflare_net.ini sudo chmod 600 /etc/letsencrypt/cloudflare/cloudflare_uk.ini
π Phase 4: Getting the First Certificate
Now we run the big command. This generates the cert and registers the Deploy Hook (so Nginx reloads itself every 60 days). We have chosen to keep the two separate files so we run the command twice. Certbot is smart enough to create two separate renewal profiles in /etc/letsencrypt/renewal/
sudo certbot certonly --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/cloudflare_net.ini \ --dns-cloudflare-propagation-seconds 60 \ --deploy-hook "systemctl reload nginx" \ --cert-name seaoffate.net \ -d seaoffate.net -d "*.seaoffate.net"
sudo certbot certonly --dns-cloudflare \ --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/cloudflare_uk.ini \ --dns-cloudflare-propagation-seconds 60 \ --deploy-hook "systemctl reload nginx" \ --cert-name seaoffate.uk \ -d seaoffate.uk -d "*.seaoffate.uk"
ποΈ Phase 4: Verification
Always verify your work before closing the terminal. To Test the Renewal process:
sudo certbot renew --dry-run
Verify the Systemd Timer:
systemctl list-timers | grep certbot
Now that Raisin will fetch a new SSL certificate every time it becomes due we can look at deploying it to other VMs in which case the local PCs will also be using the SSL cert and not give security warnings.
ποΈ The Architecture: Push Distribution
Since we now have Raisin acting as the central certificate hub, the most professional way to handle this is to have Raisin "push" the certificates to Plum, Fig, Blackberry, and Quince the moment they are renewed. This avoids having to remember to do it manually and ensures all our "Fruits" stay in sync with the latest wildcard SSL. We will use a Bash script combined with SSH keys and Certbot's deploy-hook.
Establish SSH Trust (Passwordless Login)
For Raisin to push files, it needs to log into the other servers without being prompted for a password. On Raisin, check for a root SSH key:
sudo ls /root/.ssh/id_rsa.pub # If it doesn't exist, create it: sudo ssh-keygen -t rsa -b 4096 -N ""
Copy the key to each destination server (repeat for all):
sudo ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] sudo ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] sudo ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected] sudo ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected]
ποΈ Final Prep: The "Destination" Folders. Before we run the script, we need to make sure the target directories exist on each "Fruit" and that nigel has the right permissions to drop files thereon each server run the following commands
sudo mkdir -p /etc/nginx/ssl/seaoffate.net sudo chown nigel:nigel /etc/nginx/ssl/seaoffate.net
Note: If a server doesn't have Nginx installed yet, the directory /etc/nginx might not exist. You can still create it manually.
π The "Fruit-Sync" Master Script
Now, back on Raisin, letβs create the script that will automate the distribution. Create the script file:
sudo nano /usr/local/bin/deploy-wildcard.sh
Paste this code (Optimized for your specific setup):
#!/bin/bash
# Raisin SSL Distribution Bot - February 2026
#
# 1. Reload local Nginx on Raisin
echo "Reloading local Nginx on Raisin..."
systemctl reload nginx
#
# 2. Destination Servers
SERVERS=("plum.seaoffate.local" "fig.seaoffate.local" "blackberry.seaoffate.local" "quince.seaoffate.local")
#
# 3. Source Cert Path
CERT_DIR="/etc/letsencrypt/live/seaoffate.net"
#
echo "--- Starting SSL Distribution: $(date) ---"
#
for SERVER in "${SERVERS[@]}"; do
echo "Deploying to $SERVER..."
#
# Ensure the destination directory exists (Nigel's Manual Step)
# We push the files regardless of whether a webserver is there yet
scp "$CERT_DIR/fullchain.pem" "nigel@$SERVER:/etc/nginx/ssl/seaoffate.net/fullchain.pem"
scp "$CERT_DIR/privkey.pem" "nigel@$SERVER:/etc/nginx/ssl/seaoffate.net/privkey.pem"
#
# SMART CHECK: Only reload Apache if it exists
ssh nigel@$SERVER "if systemctl is-active --quiet apache2; then sudo systemctl reload apache2 && echo 'Apache reloaded'; elif systemctl is-active --quiet nginx; then sudo systemctl reload nginx && echo 'Nginx reloaded'; else echo 'No webserver active - Files copied only'; fi"
if [ $? -eq 0 ]; then
echo "Successfully processed $SERVER."
else
echo "ERROR: Issue communicating with $SERVER."
fi
done
#
echo "--- SSL Distribution Complete ---"
The script reloads Apache when the cert is delivered but the sudo systemctl reload apache2 requires a password that the script cannot give so we must add the no password rule to the sodoers file. on each target system (Plum, Fig, Blackberry and Quince) we must open the visudo file with the command
sudo visudo
Scroll down to the bottom and add the following line at the very bottom
nigel ALL=(ALL) NOPASSWD: /usr/bin/systemctl reload apache2, /usr/bin/systemctl reload nginx
This will allow systemctl reload apache2 to be run without adding a password
Automation Hook
To ensure the script runs every time a certificate is successfully renewed, use the reconfigure command on Raisin:
sudo certbot reconfigure --cert-name seaoffate.net --deploy-hook /usr/local/bin/deploy-wildcard.sh
Docker Volume Mapping (For Blackberry & Quince)
Since these nodes run on Docker, the certificates sitting on the host OS don't help the containers unless they are "mapped" in.
Using Certs in Docker On Docker nodes like Quince, do not install Apache. Instead, map the certificates into your docker-compose.yml volumes: volumes:
- /etc/nginx/ssl/seaoffate.net/fullchain.pem:/etc/ssl/certs/fullchain.pem:ro - /etc/nginx/ssl/seaoffate.net/privkey.pem:/etc/ssl/private/privkey.pem:ro