1
0
docker-letsencrypt-nginx-pr.../app/letsencrypt_service
2017-11-16 09:33:47 +01:00

155 lines
5.3 KiB
Bash
Executable File

#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
seconds_to_wait=3600
ACME_CA_URI="${ACME_CA_URI:-https://acme-v01.api.letsencrypt.org/directory}"
DEFAULT_KEY_SIZE=4096
source /app/functions.sh
create_link() {
local readonly target=${1?missing target argument}
local readonly source=${2?missing source argument}
[[ -f "$target" ]] && return 1
ln -sf "$source" "$target"
}
create_links() {
local readonly base_domain=${1?missing base_domain argument}
local readonly domain=${2?missing base_domain argument}
if [[ ! -f "/etc/nginx/certs/$base_domain"/fullchain.pem || \
! -f "/etc/nginx/certs/$base_domain"/key.pem ]]; then
return 1
fi
local return_code=1
create_link "/etc/nginx/certs/$domain".crt "./$base_domain"/fullchain.pem
return_code=$(( $return_code & $? ))
create_link "/etc/nginx/certs/$domain".key "./$base_domain"/key.pem
return_code=$(( $return_code & $? ))
if [[ -f "/etc/nginx/certs/dhparam.pem" ]]; then
create_link "/etc/nginx/certs/$domain".dhparam.pem ./dhparam.pem
return_code=$(( $return_code & $? ))
fi
if [[ -f "/etc/nginx/certs/$base_domain"/chain.pem ]]; then
create_link "/etc/nginx/certs/$domain".chain.pem "./$base_domain"/chain.pem
return_code=$(( $return_code & $? ))
fi
return $return_code
}
update_certs() {
[[ ! -f "$DIR"/letsencrypt_service_data ]] && return
# Load relevant container settings
unset LETSENCRYPT_CONTAINERS
source "$DIR"/letsencrypt_service_data
reload_nginx='false'
for cid in "${LETSENCRYPT_CONTAINERS[@]}"; do
# Derive host and email variable names
host_varname="LETSENCRYPT_${cid}_HOST"
# Array variable indirection hack: http://stackoverflow.com/a/25880676/350221
hosts_array=$host_varname[@]
email_varname="LETSENCRYPT_${cid}_EMAIL"
keysize_varname="LETSENCRYPT_${cid}_KEYSIZE"
cert_keysize="${!keysize_varname}"
if [[ "$cert_keysize" == "<no value>" ]]; then
cert_keysize=$DEFAULT_KEY_SIZE
fi
test_certificate_varname="LETSENCRYPT_${cid}_TEST"
create_test_certificate=false
if [[ $(lc "${!test_certificate_varname:-}") == true ]]; then
create_test_certificate=true
fi
params_d_str=""
[[ $DEBUG == true ]] && params_d_str+=" -v"
[[ -n $ACME_TOS_HASH ]] && params_d_str+=" --tos_sha256 $ACME_TOS_HASH"
[[ $REUSE_KEY == true ]] && params_d_str+=" --reuse_key"
[[ "${1}" == "--force-renew" ]] && params_d_str+=" --valid_min 7776000"
hosts_array_expanded=("${!hosts_array}")
# First domain will be our base domain
base_domain="${hosts_array_expanded[0]}"
if [[ "$create_test_certificate" == true ]]; then
# Use staging acme end point
acme_ca_uri="https://acme-staging.api.letsencrypt.org/directory"
if [[ ! -f /etc/nginx/certs/.${base_domain}.test ]]; then
# Remove old certificates
rm -rf /etc/nginx/certs/${base_domain}
for domain in "${!hosts_array}"; do
rm -f /etc/nginx/certs/$domain.{crt,key,dhparam.pem}
done
touch /etc/nginx/certs/.${base_domain}.test
fi
else
acme_ca_uri="$ACME_CA_URI"
if [[ -f /etc/nginx/certs/.${base_domain}.test ]]; then
# Remove old test certificates
rm -rf /etc/nginx/certs/${base_domain}
for domain in "${!hosts_array}"; do
rm -f /etc/nginx/certs/$domain.{crt,key,dhparam.pem}
done
rm -f /etc/nginx/certs/.${base_domain}.test
fi
fi
# Create directory for the first domain
mkdir -p /etc/nginx/certs/$base_domain
cd /etc/nginx/certs/$base_domain
for domain in "${!hosts_array}"; do
# Add all the domains to certificate
params_d_str+=" -d $domain"
# Add location configuration for the domain
add_location_configuration "$domain" || reload_nginx
done
echo "Creating/renewal $base_domain certificates... (${hosts_array_expanded[*]})"
/usr/bin/simp_le \
-f account_key.json -f key.pem -f chain.pem -f fullchain.pem -f cert.pem \
$params_d_str \
--cert_key_size=$cert_keysize \
--email "${!email_varname}" \
--server=$acme_ca_uri \
--default_root /usr/share/nginx/html/
simp_le_return=$?
for altnames in ${hosts_array_expanded[@]:1}; do
# Remove old CN domain that now are altnames
rm -rf /etc/nginx/certs/$altnames
done
for domain in "${!hosts_array}"; do
create_links $base_domain $domain && reload_nginx='true'
[[ $simp_le_return -eq 0 ]] && reload_nginx='true'
done
done
[[ "$reload_nginx" == 'true' ]] && reload_nginx
}
# Allow the script functions to be sourced without starting the Service Loop.
if [ "${1}" == "--source-only" ]; then
return 0
fi
pid=
# Service Loop: When this script exits, start it again.
trap '[[ $pid ]] && kill $pid; exec $0' EXIT
trap 'trap - EXIT' INT TERM
update_certs
# Wait some amount of time
echo "Sleep for ${seconds_to_wait}s"
sleep $seconds_to_wait & pid=$!
wait
pid=