nginx-certbot
nginx-certbot copied to clipboard
Multiple domains don't really work well!
My proposed fix is below:
Main difference: Use each item from the array of domains...
#!/bin/bash
domains=(www.domain.com cdn.domain.com api_domain.com registry.domain.com www-registry.domain.com)
rsa_key_size=4096
data_path="./data/certbot"
email="[email protected]" # Adding a valid address is strongly recommended
staging=1 # Set to 1 if you're testing your setup to avoid hitting request limits
if ! [ -x "$(command -v docker-compose)" ]; then
echo 'Error: docker-compose is not installed.' >&2
exit 1
fi
if [ -d "$data_path" ]; then
read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision
if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then
exit
fi
fi
if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
echo "### Downloading recommended TLS parameters ..."
mkdir -p "$data_path/conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > "$data_path/conf/options-ssl-nginx.conf"
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > "$data_path/conf/ssl-dhparams.pem"
echo
fi
for domain in "${domains[@]}"
do
echo "### Creating dummy certificate for ${domain} ..."
path="/etc/letsencrypt/live/$domain"
mkdir -p "$data_path/conf/live/$domain"
docker-compose run --rm --entrypoint "\
openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 1\
-keyout '$path/privkey.pem' \
-out '$path/fullchain.pem' \
-subj '/CN=localhost'" certbot
echo
done
echo "### Starting nginx ..."
docker-compose up --force-recreate -d nginx
echo
for domain in "${domains[@]}"
do
echo "### Deleting dummy certificate for ${domain} ..."
docker-compose run --rm --entrypoint "\
rm -Rf /etc/letsencrypt/live/$domain && \
rm -Rf /etc/letsencrypt/archive/$domain && \
rm -Rf /etc/letsencrypt/renewal/$domain.conf" certbot
echo
done
for domain in "${domains[@]}"; do
echo "### Requesting Let's Encrypt certificate for ${domain} ..."
# Select appropriate email arg
case "$email" in
"") email_arg="--register-unsafely-without-email" ;;
*) email_arg="--email $email" ;;
esac
# Enable staging mode if needed
if [ $staging != "0" ]; then staging_arg="--staging"; fi
docker-compose run --rm --entrypoint "\
certbot certonly --webroot -w /var/www/certbot \
$staging_arg \
$email_arg \
-d $domain \
--rsa-key-size $rsa_key_size \
--agree-tos \
--force-renewal" certbot
echo
done
echo "### Reloading nginx ..."
docker-compose exec nginx nginx -s reload
Worked like a charm, thanks @masikh !
I disagree, the original script works very well for multiple domains.
When I first read the script, I was also a bit surprised by this mkdir statement:
domains=(example.org www.example.org)
rsa_key_size=4096
data_path="./data/certbot"
# ...
mkdir -p "$data_path/conf/live/$domains"
But this is actually fine, domains is a Bash array, and using $domains will give you the first element of the array.
Try this:
echo "The value of domains is: $domains"
It will print The value of domains is: example.org, without mentioning the second domain www.example.org. So the mkdir command is fine.
Now as far as the actual certbot command is concerned, the original script is IMHO much better than @masikh's version above, because it only creates one certificate, which is valid for all the given domains. The above version on the other hand creates a separate certificate for every domain.
https://eff-certbot.readthedocs.io/en/stable/using.html#certbot-command-line-options says:
-d DOMAIN, --domains DOMAIN, --domain DOMAIN
Domain names to include. For multiple domains you can
use multiple -d flags or enter a comma separated list
of domains as a parameter. All domains will be
included as Subject Alternative Names on the
certificate. The first domain will be used as the
certificate name, unless otherwise specified or if you
already have a certificate with the same name. In the
case of a name conflict, a number like -0001 will be
appended to the certificate name. (default: Ask)
The problem seem to be that what @dietmar is saying works only for bash. In bash I get the same result that you got executing:
echo "The value of domains is: $domains"
But when executing the same 2 commands (including the same variable assignment) in zsh I got:
The value of domains is: example.org www.example.org
Met the same issue today on Ubuntu 20.0.4. I defined 2 domains in array, but all commands were completed for first domain only. I like the solution by masich more, because it's more intuitive, it's easier to read the code with explicitly defined cycles, and ofk it's more convinient to debug it.
Each has its own advantages, @masich is solution allows ssl for multiple different primary domains,@dietmar can only be configured for multiple second-level domain names under a single primary domain name