Made this during my learning experience and figured who knows maybe someone else could use it at some point so here it is!
Its only for ubuntu 22.04 running nginx since thats what I use across the board for webservers but feel free to modify!
At a minimum change the certbot_email variable to your email and change out the domain names.
I build www subdomains for all my sites because of how many people still use it so if the domain name is not a subdomain for example example.com
it will automatically look for running certbot against www.example.com
in addition to and at the same time as example.com
.
There are also variables for using the testing certs which is the default option for safety and expanding certificates which is off by default.
#!/bin/bash
# Check the OS version
if [[ $(lsb_release -rs) != "22.04" ]]; then
echo
echo "----------------------"
echo
echo "This script is only designed for and tested on Ubuntu 22.04, so modify at your own risk."
echo
echo "----------------------"
echo
exit 1
fi
# Variables
CERTBOT_EMAIL="YOUR EMAIL HERE"
DOMAINS=(
"DOMAIN1.COM"
"DOMAIN2.COM"
"DOMAIN3.COM"
"DOMAIN4.COM"
)
testingcert=true # Set this to false to run without --test-cert
expandcert=false # Set this to true to enable --expand option
FAILED_DOMAINS=() # Array to store failed domains
EXISTING_CERTS=() # Array to store domains that already have certs
SUCCESS_DOMAINS=() # Array to store domains that succeeded
# Function to check if a certificate exists for a domain
certificate_exists() {
domain=$1
# Use Certbot to list certificates and grep to search for the domain
sudo certbot certificates | grep -Eq "Domains: $domain"
return $?
}
# Command options for testing and expanding certificates
CERTBOT_OPTIONS=""
if [ "$testingcert" = true ]; then
CERTBOT_OPTIONS="$CERTBOT_OPTIONS --test-cert"
fi
if [ "$expandcert" = true ]; then
CERTBOT_OPTIONS="$CERTBOT_OPTIONS --expand"
fi
# Install snapd and manage certbot installation
echo
echo "----------------------"
echo
echo "Installing snapd and managing Certbot installation..."
echo
echo "----------------------"
echo
sudo apt install snapd
if [ $? -ne 0 ]; then
echo
echo "----------------------"
echo
echo "Failed to install snapd."
echo
echo "----------------------"
echo
exit 1
fi
sudo apt-get remove certbot -y
if [ $? -ne 0 ]; then
echo
echo "----------------------"
echo
echo "Failed to remove existing Certbot installation."
echo
echo "----------------------"
echo
exit 1
fi
sudo snap install --classic certbot
if [ $? -ne 0 ]; then
echo
echo "----------------------"
echo
echo "Failed to install Certbot via Snap."
echo
echo "----------------------"
echo
exit 1
fi
# Ensure Certbot is accessible globally
sudo ln -sf /snap/bin/certbot /usr/bin/certbot
# Process each domain
for domain in "${DOMAINS[@]}"; do
if certificate_exists $domain; then
echo
echo "----------------------"
echo
echo "$domain: A certificate already exists. Skipping Certbot for this domain."
echo
echo "----------------------"
echo
EXISTING_CERTS+=("$domain")
continue
fi
# Check if the domain is a subdomain (contains more than one dot)
if [[ $(echo $domain | grep -o "\." | wc -l) -eq 1 ]]; then
# Domain is not a subdomain, add www
domain_with_www="www.$domain"
cert_domains="-d $domain -d $domain_with_www"
else
# Domain is a subdomain, do not add www
cert_domains="-d $domain"
fi
echo
echo "----------------------"
echo
echo "Performing dry run for $domain..."
echo
echo "----------------------"
echo
sudo certbot certonly -v --nginx --dry-run $cert_domains --email $CERTBOT_EMAIL --agree-tos --non-interactive $CERTBOT_OPTIONS
if [ $? -eq 0 ]; then
echo
echo "----------------------"
echo
echo "Dry run successful for $domain, proceeding with actual certificate request."
echo
echo "----------------------"
echo
sudo certbot -v --nginx $cert_domains --email $CERTBOT_EMAIL --agree-tos --non-interactive $CERTBOT_OPTIONS
if [ $? -eq 0 ]; then
echo
echo "----------------------"
echo
echo "Certificate successfully obtained for $domain."
echo
echo "----------------------"
echo
SUCCESS_DOMAINS+=("$domain")
else
echo
echo "----------------------"
echo
echo "Failed to obtain a certificate for $domain."
echo
echo "----------------------"
echo
FAILED_DOMAINS+=("$domain")
fi
else
echo
echo "----------------------"
echo
echo "Dry run failed for $domain, skipping actual certificate request."
echo
echo "----------------------"
echo
FAILED_DOMAINS+=("$domain")
fi
done
# Function to sort and print domains in a two-column format
sort_and_print_domains() {
local -n domains=$1 # Use nameref for indirect array handling
declare -A seen # associative array to track seen domains
echo "Domains | www Variants"
echo "-------------------------------|----------------------------------"
for domain in "${domains[@]}"; do
# Check if the domain is a root domain with exactly two segments
if [[ "$domain" =~ ^[^.]+\.[^.]+$ ]]; then
# Prepare to print both the root and www version if not already processed
local base_domain="$domain"
local www_domain="www.$domain"
# Check if either version has already been processed
if [[ ${seen["$base_domain"]} == 1 || ${seen["$www_domain"]} == 1 ]]; then
continue # Skip to next if already handled
fi
# Print the domain and its www version if they haven't been marked as seen
printf "%-30s | %-30s\n" "$base_domain" "$www_domain"
seen["$base_domain"]=1
seen["$www_domain"]=1
else
# If not a root domain, just print the domain if not already seen
if [[ ${seen["$domain"]} != 1 ]]; then
printf "%-30s | %-30s\n" "$domain" ""
seen["$domain"]=1
fi
fi
done
}
# Final report
echo
echo "----------------------"
echo
echo "Summary of Operations:"
echo
echo "----------------------"
echo
echo "Existing Certificates:"
echo
echo "----------------------"
echo
sort_and_print_domains EXISTING_CERTS
echo
echo "----------------------"
echo
echo "Certificates Successfully Obtained:"
echo
echo "----------------------"
echo
sort_and_print_domains SUCCESS_DOMAINS
echo
echo "----------------------"
echo
echo "Failed Certificate Requests:"
echo
echo "----------------------"
echo
sort_and_print_domains FAILED_DOMAINS
echo
echo "----------------------"
echo