mirror of
https://github.com/nginx-proxy/docker-letsencrypt-nginx-proxy-companion
synced 2024-12-03 17:28:20 +01:00
174 lines
7.7 KiB
Bash
Executable File
174 lines
7.7 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
set -u
|
|
|
|
# shellcheck source=functions.sh
|
|
source /app/functions.sh
|
|
|
|
function print_version {
|
|
if [[ -n "${COMPANION_VERSION:-}" ]]; then
|
|
echo "Info: running letsencrypt-nginx-proxy-companion version ${COMPANION_VERSION}"
|
|
fi
|
|
}
|
|
|
|
function check_docker_socket {
|
|
if [[ $DOCKER_HOST == unix://* ]]; then
|
|
socket_file=${DOCKER_HOST#unix://}
|
|
if [[ ! -S $socket_file ]]; then
|
|
echo "Error: you need to share your Docker host socket with a volume at $socket_file" >&2
|
|
echo "Typically you should run your container with: '-v /var/run/docker.sock:$socket_file:ro'" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
function check_writable_directory {
|
|
local dir="$1"
|
|
if [[ $(get_self_cid) ]]; then
|
|
if ! docker_api "/containers/$(get_self_cid)/json" | jq ".Mounts[].Destination" | grep -q "^\"$dir\"$"; then
|
|
echo "Warning: '$dir' does not appear to be a mounted volume."
|
|
fi
|
|
else
|
|
echo "Warning: can't check if '$dir' is a mounted volume without self container ID."
|
|
fi
|
|
if [[ ! -d "$dir" ]]; then
|
|
echo "Error: can't access to '$dir' directory !" >&2
|
|
echo "Check that '$dir' directory is declared as a writable volume." >&2
|
|
exit 1
|
|
fi
|
|
if ! touch "$dir/.check_writable" 2>/dev/null ; then
|
|
echo "Error: can't write to the '$dir' directory !" >&2
|
|
echo "Check that '$dir' directory is export as a writable volume." >&2
|
|
exit 1
|
|
fi
|
|
rm -f "$dir/.check_writable"
|
|
}
|
|
|
|
function check_dh_group {
|
|
# Credits to Steve Kamerman for the background Diffie-Hellman creation logic.
|
|
# https://github.com/nginx-proxy/nginx-proxy/pull/589
|
|
local DHPARAM_BITS="${DHPARAM_BITS:-2048}"
|
|
re='^[0-9]*$'
|
|
if ! [[ "$DHPARAM_BITS" =~ $re ]] ; then
|
|
echo "Error: invalid Diffie-Hellman size of $DHPARAM_BITS !" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# If a dhparam file is not available, use the pre-generated one and generate a new one in the background.
|
|
local PREGEN_DHPARAM_FILE="/app/dhparam.pem.default"
|
|
local DHPARAM_FILE="/etc/nginx/certs/dhparam.pem"
|
|
local GEN_LOCKFILE="/tmp/le_companion_dhparam_generating.lock"
|
|
|
|
# The hash of the pregenerated dhparam file is used to check if the pregen dhparam is already in use
|
|
local PREGEN_HASH; PREGEN_HASH=$(sha256sum "$PREGEN_DHPARAM_FILE" | cut -d ' ' -f1)
|
|
if [[ -f "$DHPARAM_FILE" ]]; then
|
|
local CURRENT_HASH; CURRENT_HASH=$(sha256sum "$DHPARAM_FILE" | cut -d ' ' -f1)
|
|
if [[ "$PREGEN_HASH" != "$CURRENT_HASH" ]]; then
|
|
# There is already a dhparam, and it's not the default
|
|
set_ownership_and_permissions "$DHPARAM_FILE"
|
|
echo "Info: Custom Diffie-Hellman group found, generation skipped."
|
|
return 0
|
|
fi
|
|
|
|
if [[ -f "$GEN_LOCKFILE" ]]; then
|
|
# Generation is already in progress
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
echo "Info: Creating Diffie-Hellman group in the background."
|
|
echo "A pre-generated Diffie-Hellman group will be used for now while the new one is being created."
|
|
|
|
# Put the default dhparam file in place so we can start immediately
|
|
cp "$PREGEN_DHPARAM_FILE" "$DHPARAM_FILE"
|
|
set_ownership_and_permissions "$DHPARAM_FILE"
|
|
touch "$GEN_LOCKFILE"
|
|
|
|
# Generate a new dhparam in the background in a low priority and reload nginx when finished (grep removes the progress indicator).
|
|
(
|
|
(
|
|
nice -n +5 openssl dhparam -out "${DHPARAM_FILE}.new" "$DHPARAM_BITS" 2>&1 \
|
|
&& mv "${DHPARAM_FILE}.new" "$DHPARAM_FILE" \
|
|
&& echo "Info: Diffie-Hellman group creation complete, reloading nginx." \
|
|
&& set_ownership_and_permissions "$DHPARAM_FILE" \
|
|
&& reload_nginx
|
|
) | grep -vE '^[\.+]+'
|
|
rm "$GEN_LOCKFILE"
|
|
) & disown
|
|
}
|
|
|
|
function check_default_cert_key {
|
|
local cn='letsencrypt-nginx-proxy-companion'
|
|
|
|
if [[ -e /etc/nginx/certs/default.crt && -e /etc/nginx/certs/default.key ]]; then
|
|
default_cert_cn="$(openssl x509 -noout -subject -in /etc/nginx/certs/default.crt)"
|
|
# Check if the existing default certificate is still valid for more
|
|
# than 3 months / 7776000 seconds (60 x 60 x 24 x 30 x 3).
|
|
check_cert_min_validity /etc/nginx/certs/default.crt 7776000
|
|
cert_validity=$?
|
|
[[ "$DEBUG" == 1 ]] && echo "Debug: a default certificate with $default_cert_cn is present."
|
|
fi
|
|
|
|
# Create a default cert and private key if:
|
|
# - either default.crt or default.key are absent
|
|
# OR
|
|
# - the existing default cert/key were generated by the container
|
|
# and the cert validity is less than three months
|
|
if [[ ! -e /etc/nginx/certs/default.crt || ! -e /etc/nginx/certs/default.key ]] || [[ "${default_cert_cn:-}" =~ $cn && "${cert_validity:-}" -ne 0 ]]; then
|
|
openssl req -x509 \
|
|
-newkey rsa:4096 -sha256 -nodes -days 365 \
|
|
-subj "/CN=$cn" \
|
|
-keyout /etc/nginx/certs/default.key.new \
|
|
-out /etc/nginx/certs/default.crt.new \
|
|
&& mv /etc/nginx/certs/default.key.new /etc/nginx/certs/default.key \
|
|
&& mv /etc/nginx/certs/default.crt.new /etc/nginx/certs/default.crt \
|
|
&& reload_nginx
|
|
echo "Info: a default key and certificate have been created at /etc/nginx/certs/default.key and /etc/nginx/certs/default.crt."
|
|
elif [[ "$DEBUG" == 1 && "${default_cert_cn:-}" =~ $cn ]]; then
|
|
echo "Debug: the self generated default certificate is still valid for more than three months. Skipping default certificate creation."
|
|
elif [[ "$DEBUG" == 1 ]]; then
|
|
echo "Debug: the default certificate is user provided. Skipping default certificate creation."
|
|
fi
|
|
set_ownership_and_permissions "/etc/nginx/certs/default.key"
|
|
set_ownership_and_permissions "/etc/nginx/certs/default.crt"
|
|
}
|
|
|
|
function check_default_account {
|
|
# The default account is now for empty account email
|
|
if [[ -f /etc/acme.sh/default/account.conf ]]; then
|
|
if grep -q ACCOUNT_EMAIL /etc/acme.sh/default/account.conf; then
|
|
sed -i '/ACCOUNT_EMAIL/d' /etc/acme.sh/default/account.conf
|
|
fi
|
|
fi
|
|
}
|
|
|
|
if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
|
|
print_version
|
|
check_docker_socket
|
|
if [[ -z "$(get_nginx_proxy_container)" ]]; then
|
|
echo "Error: can't get nginx-proxy container ID !" >&2
|
|
echo "Check that you are doing one of the following :" >&2
|
|
echo -e "\t- Use the --volumes-from option to mount volumes from the nginx-proxy container." >&2
|
|
echo -e "\t- Set the NGINX_PROXY_CONTAINER env var on the letsencrypt-companion container to the name of the nginx-proxy container." >&2
|
|
echo -e "\t- Label the nginx-proxy container to use with 'com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy'." >&2
|
|
exit 1
|
|
elif [[ -z "$(get_docker_gen_container)" ]] && ! is_docker_gen_container "$(get_nginx_proxy_container)"; then
|
|
echo "Error: can't get docker-gen container id !" >&2
|
|
echo "If you are running a three containers setup, check that you are doing one of the following :" >&2
|
|
echo -e "\t- Set the NGINX_DOCKER_GEN_CONTAINER env var on the letsencrypt-companion container to the name of the docker-gen container." >&2
|
|
echo -e "\t- Label the docker-gen container to use with 'com.github.jrcs.letsencrypt_nginx_proxy_companion.docker_gen'." >&2
|
|
exit 1
|
|
fi
|
|
check_writable_directory '/etc/nginx/certs'
|
|
check_writable_directory '/etc/nginx/vhost.d'
|
|
check_writable_directory '/etc/acme.sh'
|
|
check_writable_directory '/usr/share/nginx/html'
|
|
[[ -f /app/letsencrypt_user_data ]] && check_writable_directory '/etc/nginx/conf.d'
|
|
check_default_cert_key
|
|
check_dh_group
|
|
reload_nginx
|
|
check_default_account
|
|
fi
|
|
|
|
exec "$@"
|