mirror of
https://github.com/nginx-proxy/docker-letsencrypt-nginx-proxy-companion
synced 2024-04-27 04:25:07 +02:00
Change ACME client to acme.sh
This commit is contained in:
parent
96c9cbf821
commit
c821d809f6
|
@ -2,6 +2,7 @@ certs/
|
|||
conf.d/
|
||||
data/
|
||||
vhost.d/
|
||||
.vscode
|
||||
|
||||
# tests
|
||||
go/
|
||||
|
|
|
@ -28,8 +28,7 @@ before_install:
|
|||
install:
|
||||
- docker build -t "$IMAGE" .
|
||||
- docker inspect "$IMAGE"
|
||||
- docker run --rm "$IMAGE" simp_le --version
|
||||
- docker run --rm "$IMAGE" simp_le -v --test
|
||||
- docker run --rm "$IMAGE" acme.sh --version
|
||||
- docker images
|
||||
|
||||
before_script:
|
||||
|
|
17
Dockerfile
17
Dockerfile
|
@ -21,32 +21,35 @@ FROM alpine:3.11
|
|||
|
||||
LABEL maintainer="Yves Blusseau <90z7oey02@sneakemail.com> (@blusseau)"
|
||||
|
||||
ENV DEBUG=false \
|
||||
DOCKER_HOST=unix:///var/run/docker.sock
|
||||
ENV DOCKER_HOST=unix:///var/run/docker.sock \
|
||||
PATH=$PATH:/app
|
||||
|
||||
# Install packages required by the image
|
||||
RUN apk add --update \
|
||||
bash \
|
||||
ca-certificates \
|
||||
coreutils \
|
||||
curl \
|
||||
jq \
|
||||
netcat-openbsd \
|
||||
openssl \
|
||||
socat \
|
||||
&& rm /var/cache/apk/*
|
||||
|
||||
# Install docker-gen from build stage
|
||||
COPY --from=go-builder /go/src/github.com/jwilder/docker-gen/docker-gen /usr/local/bin/
|
||||
|
||||
# Install simp_le
|
||||
COPY /install_simp_le.sh /app/install_simp_le.sh
|
||||
RUN chmod +rx /app/install_simp_le.sh \
|
||||
COPY /install_acme.sh /app/install_acme.sh
|
||||
RUN chmod +rx /app/install_acme.sh \
|
||||
&& sync \
|
||||
&& /app/install_simp_le.sh \
|
||||
&& rm -f /app/install_simp_le.sh
|
||||
&& /app/install_acme.sh \
|
||||
&& rm -f /app/install_acme.sh
|
||||
|
||||
COPY /app/ /app/
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
VOLUME ["/etc/acme.sh", "/etc/nginx/certs"]
|
||||
|
||||
ENTRYPOINT [ "/bin/bash", "/app/entrypoint.sh" ]
|
||||
CMD [ "/bin/bash", "/app/start.sh" ]
|
||||
|
|
|
@ -4,7 +4,6 @@ set -u
|
|||
|
||||
# shellcheck source=functions.sh
|
||||
source /app/functions.sh
|
||||
DEBUG="$(lc "$DEBUG")"
|
||||
|
||||
function check_deprecated_env_var {
|
||||
if [[ -n "${ACME_TOS_HASH:-}" ]]; then
|
||||
|
@ -109,7 +108,7 @@ function check_default_cert_key {
|
|||
# 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" == true ]] && echo "Debug: a default certificate with $default_cert_cn is present."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: a default certificate with $default_cert_cn is present."
|
||||
fi
|
||||
|
||||
# Create a default cert and private key if:
|
||||
|
@ -126,23 +125,35 @@ function check_default_cert_key {
|
|||
&& mv /etc/nginx/certs/default.key.new /etc/nginx/certs/default.key \
|
||||
&& mv /etc/nginx/certs/default.crt.new /etc/nginx/certs/default.crt
|
||||
echo "Info: a default key and certificate have been created at /etc/nginx/certs/default.key and /etc/nginx/certs/default.crt."
|
||||
elif [[ "$DEBUG" == true && "${default_cert_cn:-}" =~ $cn ]]; then
|
||||
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" == true ]]; then
|
||||
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"
|
||||
}
|
||||
|
||||
if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
|
||||
acmev1_r='acme-(v01\|staging)\.api\.letsencrypt\.org'
|
||||
if [[ "${ACME_CA_URI:-}" =~ $acmev1_r ]]; then
|
||||
echo "Error: the ACME v1 API is no longer supported by simp_le."
|
||||
echo "See https://github.com/zenhack/simp_le/pull/119"
|
||||
echo "Please use one of Let's Encrypt ACME v2 endpoints instead."
|
||||
exit 1
|
||||
function configure_default_email {
|
||||
# Configure the email used by the default config
|
||||
[[ -d /etc/acme.sh/default ]] || mkdir -p /etc/acme.sh/default
|
||||
if [[ -f /etc/acme.sh/default/account.conf ]]; then
|
||||
if [[ -f /etc/acme.sh/default/ca/acme-v01.api.letsencrypt.org/account.json ]]; then
|
||||
acme.sh --update-account --accountemail "${DEFAULT_EMAIL:-}"
|
||||
return 0
|
||||
elif grep -q ACCOUNT_EMAIL /etc/acme.sh/default/account.conf; then
|
||||
if grep -q "${DEFAULT_EMAIL:-}" /etc/acme.sh/default/account.conf; then
|
||||
return 0
|
||||
else
|
||||
sed -i "s/^ACCOUNT_EMAIL=.*$/ACCOUNT_EMAIL='${DEFAULT_EMAIL:-}'/g" /etc/acme.sh/default/account.conf
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
echo "ACCOUNT_EMAIL='${DEFAULT_EMAIL:-}'" >> /etc/acme.sh/default/account.conf
|
||||
}
|
||||
|
||||
if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
|
||||
check_docker_socket
|
||||
if [[ -z "$(get_nginx_proxy_container)" ]]; then
|
||||
echo "Error: can't get nginx-proxy container ID !" >&2
|
||||
|
@ -160,12 +171,13 @@ if [[ "$*" == "/bin/bash /app/start.sh" ]]; then
|
|||
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_deprecated_env_var
|
||||
check_default_cert_key
|
||||
check_dh_group
|
||||
reload_nginx
|
||||
[[ -n ${DEFAULT_EMAIL:-} ]] && configure_default_email
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
|
|
@ -5,7 +5,10 @@ function lc {
|
|||
echo "${@,,}"
|
||||
}
|
||||
|
||||
DEBUG="$(lc "$DEBUG")"
|
||||
DEBUG="$(lc "${DEBUG:-}")"
|
||||
if [[ "$DEBUG" == true ]]; then
|
||||
DEBUG=1 && export DEBUG
|
||||
fi
|
||||
|
||||
[[ -z "${VHOST_DIR:-}" ]] && \
|
||||
declare -r VHOST_DIR=/etc/nginx/vhost.d
|
||||
|
@ -325,7 +328,7 @@ function set_ownership_and_permissions {
|
|||
return 1
|
||||
fi
|
||||
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: checking $path ownership and permissions."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: checking $path ownership and permissions."
|
||||
|
||||
# Find the user numeric ID if the FILES_UID environment variable isn't numeric.
|
||||
if [[ "$user" =~ ^[0-9]+$ ]]; then
|
||||
|
@ -334,7 +337,7 @@ function set_ownership_and_permissions {
|
|||
elif id -u "$user" > /dev/null 2>&1; then
|
||||
# Convert the user name to numeric ID
|
||||
local user_num; user_num="$(id -u "$user")"
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: numeric ID of user $user is $user_num."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: numeric ID of user $user is $user_num."
|
||||
else
|
||||
echo "Warning: user $user not found in the container, please use a numeric user ID instead of a user name. Skipping ownership and permissions check."
|
||||
return 1
|
||||
|
@ -347,7 +350,7 @@ function set_ownership_and_permissions {
|
|||
elif getent group "$group" > /dev/null 2>&1; then
|
||||
# Convert the group name to numeric ID
|
||||
local group_num; group_num="$(getent group "$group" | awk -F ':' '{print $3}')"
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: numeric ID of group $group is $group_num."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: numeric ID of group $group is $group_num."
|
||||
else
|
||||
echo "Warning: group $group not found in the container, please use a numeric group ID instead of a group name. Skipping ownership and permissions check."
|
||||
return 1
|
||||
|
@ -356,7 +359,7 @@ function set_ownership_and_permissions {
|
|||
# Check and modify ownership if required.
|
||||
if [[ -e "$path" ]]; then
|
||||
if [[ "$(stat -c %u:%g "$path" )" != "$user_num:$group_num" ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: setting $path ownership to $user:$group."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: setting $path ownership to $user:$group."
|
||||
if [[ -L "$path" ]]; then
|
||||
chown -h "$user_num:$group_num" "$path"
|
||||
else
|
||||
|
@ -366,7 +369,7 @@ function set_ownership_and_permissions {
|
|||
# If the path is a folder, check and modify permissions if required.
|
||||
if [[ -d "$path" ]]; then
|
||||
if [[ "$(stat -c %a "$path")" != "$d_perms" ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: setting $path permissions to $d_perms."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: setting $path permissions to $d_perms."
|
||||
chmod "$d_perms" "$path"
|
||||
fi
|
||||
# If the path is a file, check and modify permissions if required.
|
||||
|
@ -374,13 +377,13 @@ function set_ownership_and_permissions {
|
|||
# Use different permissions for private files (private keys and ACME account files) ...
|
||||
if [[ "$path" =~ ^.*(default\.key|key\.pem|\.json)$ ]]; then
|
||||
if [[ "$(stat -c %a "$path")" != "$f_perms" ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: setting $path permissions to $f_perms."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: setting $path permissions to $f_perms."
|
||||
chmod "$f_perms" "$path"
|
||||
fi
|
||||
# ... and for public files (certificates, chains, fullchains, DH parameters).
|
||||
else
|
||||
if [[ "$(stat -c %a "$path")" != "644" ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "Debug: setting $path permissions to 644."
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: setting $path permissions to 644."
|
||||
chmod "644" "$path"
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -2,20 +2,18 @@
|
|||
|
||||
# shellcheck source=functions.sh
|
||||
source /app/functions.sh
|
||||
DEBUG="$(lc "$DEBUG")"
|
||||
|
||||
seconds_to_wait=3600
|
||||
ACME_CA_URI="${ACME_CA_URI:-https://acme-v02.api.letsencrypt.org/directory}"
|
||||
DEFAULT_KEY_SIZE=4096
|
||||
REUSE_ACCOUNT_KEYS="$(lc "${REUSE_ACCOUNT_KEYS:-true}")"
|
||||
REUSE_PRIVATE_KEYS="$(lc "${REUSE_PRIVATE_KEYS:-false}")"
|
||||
DEFAULT_KEY_SIZE="${DEFAULT_KEY_SIZE:-4096}"
|
||||
RENEW_PRIVATE_KEYS="$(lc "${RENEW_PRIVATE_KEYS:-true}")"
|
||||
|
||||
function create_link {
|
||||
local -r source=${1?missing source argument}
|
||||
local -r target=${2?missing target argument}
|
||||
if [[ -f "$target" ]] && [[ "$(readlink "$target")" == "$source" ]]; then
|
||||
set_ownership_and_permissions "$target"
|
||||
[[ "$DEBUG" == true ]] && echo "$target already linked to $source"
|
||||
[[ "$DEBUG" == 1 ]] && echo "$target already linked to $source"
|
||||
return 1
|
||||
else
|
||||
ln -sf "$source" "$target" \
|
||||
|
@ -62,7 +60,7 @@ function cleanup_links {
|
|||
symlinked_domain="${symlinked_domain%*.crt}"
|
||||
SYMLINKED_DOMAINS+=("$symlinked_domain")
|
||||
done
|
||||
[[ "$DEBUG" == true ]] && echo "Symlinked domains: ${SYMLINKED_DOMAINS[*]}"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Symlinked domains: ${SYMLINKED_DOMAINS[*]}"
|
||||
|
||||
# Create an array containing domains that are considered
|
||||
# enabled (ie present on /app/letsencrypt_service_data or /app/letsencrypt_user_data).
|
||||
|
@ -77,7 +75,7 @@ function cleanup_links {
|
|||
ENABLED_DOMAINS+=("$domain")
|
||||
done
|
||||
done
|
||||
[[ "$DEBUG" == true ]] && echo "Enabled domains: ${ENABLED_DOMAINS[*]}"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Enabled domains: ${ENABLED_DOMAINS[*]}"
|
||||
|
||||
# Create an array containing only domains for which a symlinked private key exists
|
||||
# in /etc/nginx/certs but that no longer have a corresponding LETSENCRYPT_HOST set
|
||||
|
@ -88,28 +86,28 @@ function cleanup_links {
|
|||
"${ENABLED_DOMAINS[@]}" \
|
||||
| tr ' ' '\n' | sort | uniq -u)
|
||||
fi
|
||||
[[ "$DEBUG" == true ]] && echo "Disabled domains: ${DISABLED_DOMAINS[*]}"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Disabled domains: ${DISABLED_DOMAINS[*]}"
|
||||
|
||||
|
||||
# Remove disabled domains symlinks if present.
|
||||
# Return 1 if nothing was removed and 0 otherwise.
|
||||
if [[ ${#DISABLED_DOMAINS[@]} -gt 0 ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "Some domains are disabled :"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Some domains are disabled :"
|
||||
for disabled_domain in "${DISABLED_DOMAINS[@]}"; do
|
||||
[[ "$DEBUG" == true ]] && echo "Checking domain ${disabled_domain}"
|
||||
cert_folder="$(readlink -f /etc/nginx/certs/"${disabled_domain}".crt)"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Checking domain ${disabled_domain}"
|
||||
cert_folder="$(readlink -f "/etc/nginx/certs/${disabled_domain}.crt")"
|
||||
# If the dotfile is absent, skip domain.
|
||||
if [[ ! -e "${cert_folder%/*}/.companion" ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "No .companion file found in ${cert_folder}. ${disabled_domain} is not managed by letsencrypt-nginx-proxy-companion. Skipping domain."
|
||||
[[ "$DEBUG" == 1 ]] && echo "No .companion file found in ${cert_folder}. ${disabled_domain} is not managed by letsencrypt-nginx-proxy-companion. Skipping domain."
|
||||
continue
|
||||
else
|
||||
[[ "$DEBUG" == true ]] && echo "${disabled_domain} is managed by letsencrypt-nginx-proxy-companion. Removing unused symlinks."
|
||||
[[ "$DEBUG" == 1 ]] && echo "${disabled_domain} is managed by letsencrypt-nginx-proxy-companion. Removing unused symlinks."
|
||||
fi
|
||||
|
||||
for extension in .crt .key .dhparam.pem .chain.pem; do
|
||||
file="${disabled_domain}${extension}"
|
||||
if [[ -n "${file// }" ]] && [[ -L "/etc/nginx/certs/${file}" ]]; then
|
||||
[[ "$DEBUG" == true ]] && echo "Removing /etc/nginx/certs/${file}"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Removing /etc/nginx/certs/${file}"
|
||||
rm -f "/etc/nginx/certs/${file}"
|
||||
fi
|
||||
done
|
||||
|
@ -124,6 +122,7 @@ function update_certs {
|
|||
local -a LETSENCRYPT_CONTAINERS
|
||||
local -a LETSENCRYPT_STANDALONE_CERTS
|
||||
|
||||
pushd /etc/nginx/certs > /dev/null || return
|
||||
check_nginx_proxy_container_run || return
|
||||
|
||||
# Load relevant container settings
|
||||
|
@ -163,18 +162,10 @@ function update_certs {
|
|||
|
||||
params_d_arr=()
|
||||
|
||||
# Use container's LETSENCRYPT_EMAIL if set, fallback to DEFAULT_EMAIL
|
||||
email_varname="LETSENCRYPT_${cid}_EMAIL"
|
||||
email_address="${!email_varname:-"<no value>"}"
|
||||
if [[ "$email_address" != "<no value>" ]]; then
|
||||
params_d_arr+=(--email "$email_address")
|
||||
elif [[ -n "${DEFAULT_EMAIL:-}" ]]; then
|
||||
params_d_arr+=(--email "$DEFAULT_EMAIL")
|
||||
fi
|
||||
|
||||
keysize_varname="LETSENCRYPT_${cid}_KEYSIZE"
|
||||
cert_keysize="${!keysize_varname:-"<no value>"}"
|
||||
if [[ "$cert_keysize" == "<no value>" ]]; then
|
||||
if [[ "$cert_keysize" == "<no value>" ]] || \
|
||||
[[ ! "$cert_keysize" =~ ^(2048|3072|4096|8192|ec-256|ec-384)$ ]]; then
|
||||
cert_keysize=$DEFAULT_KEY_SIZE
|
||||
fi
|
||||
|
||||
|
@ -192,114 +183,61 @@ function update_certs {
|
|||
certificate_dir="/etc/nginx/certs/$base_domain"
|
||||
fi
|
||||
|
||||
account_varname="LETSENCRYPT_${cid}_ACCOUNT_ALIAS"
|
||||
account_alias="${!account_varname:-"<no value>"}"
|
||||
if [[ "$account_alias" == "<no value>" ]]; then
|
||||
account_alias=default
|
||||
config_varname="LETSENCRYPT_${cid}_ACMESH_CONFIG"
|
||||
config_name="${!config_varname:-"<no value>"}"
|
||||
if [[ "$config_name" == "<no value>" ]]; then
|
||||
config_name=default
|
||||
else
|
||||
[[ ! -d "/etc/acme.sh/$config_name" ]] && mkdir -p "/etc/acme.sh/$config_name"
|
||||
fi
|
||||
|
||||
[[ "$DEBUG" == true ]] && params_d_arr+=(-v)
|
||||
[[ $REUSE_PRIVATE_KEYS == true ]] && params_d_arr+=(--reuse_key)
|
||||
[[ "${1}" == "--force-renew" ]] && params_d_arr+=(--valid_min 7776000)
|
||||
[[ "$DEBUG" == 1 ]] && params_d_arr+=("--debug")
|
||||
[[ "$RENEW_PRIVATE_KEYS" == true ]] && params_d_arr+=("--always-force-new-domain-key")
|
||||
[[ "$1" == "--force-renew" ]] && params_d_arr+=("--force")
|
||||
|
||||
# Create directory for the first domain,
|
||||
# make it root readable only and make it the cwd
|
||||
# Create directory for the first domain
|
||||
mkdir -p "$certificate_dir"
|
||||
set_ownership_and_permissions "$certificate_dir"
|
||||
pushd "$certificate_dir" || return
|
||||
|
||||
for domain in "${!hosts_array}"; do
|
||||
# Add all the domains to certificate
|
||||
params_d_arr+=(-d "$domain")
|
||||
params_d_arr+=("--domain" "$domain")
|
||||
# Add location configuration for the domain
|
||||
add_location_configuration "$domain" || reload_nginx
|
||||
done
|
||||
|
||||
if [[ -e "./account_key.json" ]] && [[ ! -e "./account_reg.json" ]]; then
|
||||
# If there is an account key present without account registration, this is
|
||||
# a leftover from the ACME v1 version of simp_le. Remove this account key.
|
||||
rm -f ./account_key.json
|
||||
[[ "$DEBUG" == true ]] \
|
||||
&& echo "Debug: removed ACME v1 account key $certificate_dir/account_key.json"
|
||||
fi
|
||||
|
||||
# The ACME account key and registration full path are derived from the
|
||||
# endpoint URI + the account alias (set to 'default' if no alias is provided)
|
||||
account_dir="../accounts/${acme_ca_uri#*://}"
|
||||
if [[ $REUSE_ACCOUNT_KEYS == true ]]; then
|
||||
for type in "key" "reg"; do
|
||||
file_full_path="${account_dir}/${account_alias}_${type}.json"
|
||||
simp_le_file="./account_${type}.json"
|
||||
if [[ -f "$file_full_path" ]]; then
|
||||
# If there is no symlink to the account file, create it
|
||||
if [[ ! -L "$simp_le_file" ]]; then
|
||||
ln -sf "$file_full_path" "$simp_le_file" \
|
||||
&& set_ownership_and_permissions "$simp_le_file"
|
||||
# If the symlink target the wrong account file, replace it
|
||||
elif [[ "$(readlink -f "$simp_le_file")" != "$file_full_path" ]]; then
|
||||
ln -sf "$file_full_path" "$simp_le_file" \
|
||||
&& set_ownership_and_permissions "$simp_le_file"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Creating/renewal $base_domain certificates... (${hosts_array_expanded[*]})"
|
||||
/usr/bin/simp_le \
|
||||
-f account_key.json -f account_reg.json \
|
||||
-f key.pem -f chain.pem -f fullchain.pem -f cert.pem \
|
||||
"${params_d_arr[@]}" \
|
||||
--cert_key_size="$cert_keysize" \
|
||||
--server="$acme_ca_uri" \
|
||||
--default_root /usr/share/nginx/html/
|
||||
acme.sh --issue \
|
||||
--log /dev/null \
|
||||
--config-home "/etc/acme.sh/$config_name" \
|
||||
"${params_d_arr[@]}" \
|
||||
--keylength "$cert_keysize" \
|
||||
--server "$acme_ca_uri" \
|
||||
--webroot /usr/share/nginx/html \
|
||||
--cert-file "${certificate_dir}/cert.pem" \
|
||||
--key-file "${certificate_dir}/key.pem" \
|
||||
--ca-file "${certificate_dir}/chain.pem" \
|
||||
--fullchain-file "${certificate_dir}/fullchain.pem"
|
||||
|
||||
simp_le_return=$?
|
||||
acmesh_return=$?
|
||||
|
||||
if [[ $REUSE_ACCOUNT_KEYS == true ]]; then
|
||||
mkdir -p "$account_dir"
|
||||
for type in "key" "reg"; do
|
||||
file_full_path="${account_dir}/${account_alias}_${type}.json"
|
||||
simp_le_file="./account_${type}.json"
|
||||
# If the account file to be reused does not exist yet, copy it
|
||||
# from the CWD and replace the file in CWD with a symlink
|
||||
if [[ ! -f "$file_full_path" && -f "$simp_le_file" ]]; then
|
||||
cp "$simp_le_file" "$file_full_path"
|
||||
ln -sf "$file_full_path" "$simp_le_file"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
popd || return
|
||||
|
||||
if [[ $simp_le_return -ne 2 ]]; then
|
||||
if [[ $acmesh_return -ne 2 ]]; then
|
||||
for domain in "${!hosts_array}"; do
|
||||
if [[ "$acme_ca_uri" == "$le_staging_uri" ]]; then
|
||||
if [[ $acme_ca_uri =~ ^https://acme-staging.* ]]; then
|
||||
create_links "_test_$base_domain" "$domain" && should_reload_nginx='true' && should_restart_container='true'
|
||||
else
|
||||
create_links "$base_domain" "$domain" && should_reload_nginx='true' && should_restart_container='true'
|
||||
fi
|
||||
done
|
||||
touch "${certificate_dir}/.companion"
|
||||
# Set ownership and permissions of the files inside $certificate_dir
|
||||
for file in .companion cert.pem key.pem chain.pem fullchain.pem account_key.json account_reg.json; do
|
||||
set_ownership_and_permissions "${certificate_dir}/.companion"
|
||||
# Make private key root readable only
|
||||
for file in cert.pem key.pem chain.pem fullchain.pem; do
|
||||
file_path="${certificate_dir}/${file}"
|
||||
[[ -e "$file_path" ]] && set_ownership_and_permissions "$file_path"
|
||||
done
|
||||
account_path="/etc/nginx/certs/accounts/${acme_ca_uri#*://}"
|
||||
account_key_perm_path="${account_path}/${account_alias}_key.json"
|
||||
account_reg_perm_path="${account_path}/${account_alias}_reg.json"
|
||||
# Account key and registration files do not necessarily exists after
|
||||
# simp_le exit code 1. Check if they exist before perm check (#591).
|
||||
[[ -f "$account_key_perm_path" ]] && set_ownership_and_permissions "$account_key_perm_path"
|
||||
[[ -f "$account_reg_perm_path" ]] && set_ownership_and_permissions "$account_reg_perm_path"
|
||||
# Set ownership and permissions of the ACME account folder and its
|
||||
# parent folders (up to /etc/nginx/certs/accounts included)
|
||||
until [[ "$account_path" == /etc/nginx/certs ]]; do
|
||||
set_ownership_and_permissions "$account_path"
|
||||
account_path="$(dirname "$account_path")"
|
||||
done
|
||||
# Queue nginx reload if a certificate was issued or renewed
|
||||
[[ $simp_le_return -eq 0 ]] && should_reload_nginx='true' && should_restart_container='true'
|
||||
[[ $acmesh_return -eq 0 ]] && should_reload_nginx='true' && should_restart_container='true'
|
||||
fi
|
||||
|
||||
# Restart container if certs are updated and the respective environmental variable is set
|
||||
|
@ -311,7 +249,7 @@ function update_certs {
|
|||
|
||||
for domain in "${!hosts_array}"; do
|
||||
if [[ -f "/etc/nginx/conf.d/standalone-cert-$domain.conf" ]]; then
|
||||
[[ $DEBUG == true ]] && echo "Debug: removing standalone configuration file /etc/nginx/conf.d/standalone-cert-$domain.conf"
|
||||
[[ "$DEBUG" == 1 ]] && echo "Debug: removing standalone configuration file /etc/nginx/conf.d/standalone-cert-$domain.conf"
|
||||
rm -f "/etc/nginx/conf.d/standalone-cert-$domain.conf" && should_reload_nginx='true'
|
||||
fi
|
||||
done
|
||||
|
@ -321,6 +259,8 @@ function update_certs {
|
|||
cleanup_links && should_reload_nginx='true'
|
||||
|
||||
[[ "$should_reload_nginx" == 'true' ]] && reload_nginx
|
||||
|
||||
popd > /dev/null || return
|
||||
}
|
||||
|
||||
# Allow the script functions to be sourced without starting the Service Loop.
|
||||
|
|
|
@ -25,18 +25,16 @@ LETSENCRYPT_CONTAINERS=(
|
|||
{{ $host := trimSuffix "." $host }}
|
||||
{{ $hostHash := sha1 $host }}
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_HOST=('{{ $host }}')
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_EMAIL="{{ $container.Env.LETSENCRYPT_EMAIL }}"
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_KEYSIZE="{{ $container.Env.LETSENCRYPT_KEYSIZE }}"
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_TEST="{{ $container.Env.LETSENCRYPT_TEST }}"
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_ACCOUNT_ALIAS="{{ $container.Env.LETSENCRYPT_ACCOUNT_ALIAS }}"
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_ACMESH_CONFIG="{{ $container.Env.LETSENCRYPT_ACMESH_CONFIG }}"
|
||||
LETSENCRYPT_{{ $cid }}_{{ $hostHash }}_RESTART_CONTAINER="{{ $container.Env.LETSENCRYPT_RESTART_CONTAINER }}"
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
LETSENCRYPT_{{ $cid }}_HOST=( {{ range $host := split $hosts "," }}{{ $host := trim $host }}{{ $host := trimSuffix "." $host }}'{{ $host }}' {{ end }})
|
||||
LETSENCRYPT_{{ $cid }}_EMAIL="{{ $container.Env.LETSENCRYPT_EMAIL }}"
|
||||
LETSENCRYPT_{{ $cid }}_KEYSIZE="{{ $container.Env.LETSENCRYPT_KEYSIZE }}"
|
||||
LETSENCRYPT_{{ $cid }}_TEST="{{ $container.Env.LETSENCRYPT_TEST }}"
|
||||
LETSENCRYPT_{{ $cid }}_ACCOUNT_ALIAS="{{ $container.Env.LETSENCRYPT_ACCOUNT_ALIAS }}"
|
||||
LETSENCRYPT_{{ $cid }}_ACMESH_CONFIG="{{ $container.Env.LETSENCRYPT_ACMESH_CONFIG }}"
|
||||
LETSENCRYPT_{{ $cid }}_RESTART_CONTAINER="{{ $container.Env.LETSENCRYPT_RESTART_CONTAINER }}"
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Install git (required to fetch acme.sh)
|
||||
apk --update add git
|
||||
|
||||
# Get acme.sh Let's Encrypt client source
|
||||
tag="2.8.7"
|
||||
mkdir /src
|
||||
git -C /src clone https://github.com/Neilpang/acme.sh.git
|
||||
cd /src/acme.sh
|
||||
git checkout "$tag"
|
||||
|
||||
# Install acme.sh in /app
|
||||
./acme.sh --install \
|
||||
--nocron \
|
||||
--auto-upgrade 0 \
|
||||
--home /app \
|
||||
--config-home /etc/acme.sh/default
|
||||
|
||||
# Make house cleaning
|
||||
cd /
|
||||
rm -rf /src
|
||||
apk del git
|
||||
rm -rf /var/cache/apk/*
|
|
@ -1,30 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Install python and packages needed to build simp_le
|
||||
apk add --update python3 git gcc musl-dev libffi-dev python3-dev openssl-dev
|
||||
|
||||
# Create expected symlinks if they don't exist
|
||||
[[ -e /usr/bin/pip ]] || ln -sf /usr/bin/pip3 /usr/bin/pip
|
||||
[[ -e /usr/bin/python ]] || ln -sf /usr/bin/python3 /usr/bin/python
|
||||
|
||||
# Get Let's Encrypt simp_le client source
|
||||
branch="0.18.0"
|
||||
mkdir -p /src
|
||||
git -C /src clone --depth=1 --branch $branch https://github.com/zenhack/simp_le.git
|
||||
|
||||
# Install simp_le in /usr/bin
|
||||
cd /src/simp_le
|
||||
#pip install wheel requests
|
||||
for pkg in pip setuptools wheel
|
||||
do
|
||||
pip3 install -U "${pkg?}"
|
||||
done
|
||||
pip3 install .
|
||||
|
||||
# Make house cleaning
|
||||
cd /
|
||||
rm -rf /src
|
||||
apk del git gcc musl-dev libffi-dev python3-dev openssl-dev
|
||||
rm -rf /var/cache/apk/*
|
|
@ -12,12 +12,16 @@ setup_boulder() {
|
|||
pushd $GOPATH/src/github.com/letsencrypt/boulder
|
||||
git checkout release-2019-10-07
|
||||
if [[ "$(uname)" == 'Darwin' ]]; then
|
||||
# Set Standard Ports
|
||||
sed -i '' 's/ 5002/ 80/g' test/config/va.json
|
||||
sed -i '' 's/ 5001/ 443/g' test/config/va.json
|
||||
# Modify custom rate limit
|
||||
sed -i '' 's/le.wtf,le1.wtf/le1.wtf,le2.wtf,le3.wtf/g' test/rate-limit-policies.yml
|
||||
else
|
||||
# Set Standard Ports
|
||||
sed --in-place 's/ 5002/ 80/g' test/config/va.json
|
||||
sed --in-place 's/ 5001/ 443/g' test/config/va.json
|
||||
# Modify custom rate limit
|
||||
sed --in-place 's/le.wtf,le1.wtf/le1.wtf,le2.wtf,le3.wtf/g' test/rate-limit-policies.yml
|
||||
fi
|
||||
docker-compose build --pull
|
||||
|
|
|
@ -35,7 +35,7 @@ The correct certificate for le2.wtf was served by Nginx.
|
|||
le3.wtf is on certificate.
|
||||
Connection to le3.wtf using https was successful.
|
||||
The correct certificate for le3.wtf was served by Nginx.
|
||||
Started test web server for le1.wtf.,le2.wtf.,le3.wtf
|
||||
Started test web server for le1.wtf.,le3.wtf.,le2.wtf
|
||||
Symlink to le1.wtf certificate has been generated.
|
||||
The link is pointing to the file ./le1.wtf/fullchain.pem
|
||||
le1.wtf is on certificate.
|
||||
|
|
|
@ -21,7 +21,7 @@ function cleanup {
|
|||
i=$(( $i + 1 ))
|
||||
done
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ letsencrypt_hosts=( \
|
|||
[0]="${domains[0]},${domains[1]},${domains[2]}" \ #straight comma separated list
|
||||
[1]="${domains[1]}, ${domains[2]}, ${domains[0]}" \ #comma separated list with spaces
|
||||
[2]="${domains[2]}, ${domains[0]}, ${domains[1]}," \ #comma separated list with spaces and a trailing comma
|
||||
[3]="${domains[0]}.,${domains[1]}.,${domains[2]}" ) #trailing dots
|
||||
[3]="${domains[0]}.,${domains[2]}.,${domains[1]}" ) #trailing dots
|
||||
|
||||
i=1
|
||||
|
||||
|
@ -94,7 +94,7 @@ for hosts in "${letsencrypt_hosts[@]}"; do
|
|||
done
|
||||
|
||||
docker stop "$container" > /dev/null 2>&1
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
i=$(( $i + 1 ))
|
||||
|
||||
done
|
||||
|
|
|
@ -19,7 +19,7 @@ function cleanup {
|
|||
docker rm --force "$domain" > /dev/null 2>&1
|
||||
done
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ function cleanup {
|
|||
i=$(( $i + 1 ))
|
||||
done
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ for hosts in "${letsencrypt_hosts[@]}"; do
|
|||
done
|
||||
|
||||
docker stop "$container" > /dev/null 2>&1
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
i=$(( $i + 1 ))
|
||||
|
||||
done
|
||||
|
|
|
@ -17,7 +17,7 @@ function cleanup {
|
|||
# Remove the Nginx container silently.
|
||||
docker rm --force "$subdomain" > /dev/null 2>&1
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ function cleanup {
|
|||
docker rm --force "$domain" > /dev/null 2>&1
|
||||
done
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ function cleanup {
|
|||
# Remove the Nginx container silently.
|
||||
docker rm --force "${domains[0]}" > /dev/null 2>&1
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ function cleanup {
|
|||
# Remove the ${domains[0]} Nginx container silently.
|
||||
docker rm --force "${domains[0]}" > /dev/null 2>&1
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
@ -41,10 +41,7 @@ wait_for_symlink "${domains[0]}" "$le_container_name"
|
|||
|
||||
# Array of folder paths to test
|
||||
folders=( \
|
||||
[0]="/etc/nginx/certs/accounts" \
|
||||
[1]="/etc/nginx/certs/accounts/boulder:4001" \
|
||||
[2]="/etc/nginx/certs/accounts/boulder:4001/directory" \
|
||||
[3]="/etc/nginx/certs/${domains[0]}" \
|
||||
[0]="/etc/nginx/certs/${domains[0]}" \
|
||||
)
|
||||
|
||||
# Test folder paths
|
||||
|
@ -61,8 +58,6 @@ symlinks=( \
|
|||
[1]="/etc/nginx/certs/${domains[0]}.key" \
|
||||
[2]="/etc/nginx/certs/${domains[0]}.chain.pem" \
|
||||
[3]="/etc/nginx/certs/${domains[0]}.dhparam.pem" \
|
||||
[4]="/etc/nginx/certs/${domains[0]}/account_key.json" \
|
||||
[5]="/etc/nginx/certs/${domains[0]}/account_reg.json" \
|
||||
)
|
||||
|
||||
# Test symlinks paths
|
||||
|
@ -76,9 +71,7 @@ symlinks=( \
|
|||
# Array of private file paths to test
|
||||
private_files=( \
|
||||
[0]="/etc/nginx/certs/default.key" \
|
||||
[1]="/etc/nginx/certs/accounts/boulder:4001/directory/default_key.json" \
|
||||
[2]="/etc/nginx/certs/accounts/boulder:4001/directory/default_reg.json" \
|
||||
[3]="/etc/nginx/certs/${domains[0]}/key.pem" \
|
||||
[1]="/etc/nginx/certs/${domains[0]}/key.pem" \
|
||||
)
|
||||
|
||||
# Test private file paths
|
||||
|
|
|
@ -17,7 +17,7 @@ function cleanup {
|
|||
# Remove the ${domains[0]} Nginx container silently.
|
||||
docker rm --force "${domains[0]}" > /dev/null 2>&1
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
@ -35,10 +35,7 @@ wait_for_symlink "${domains[0]}" "$le_container_name"
|
|||
|
||||
# Array of folder paths to test
|
||||
folders=( \
|
||||
[0]="/etc/nginx/certs/accounts" \
|
||||
[1]="/etc/nginx/certs/accounts/boulder:4001" \
|
||||
[2]="/etc/nginx/certs/accounts/boulder:4001/directory" \
|
||||
[3]="/etc/nginx/certs/${domains[0]}" \
|
||||
[0]="/etc/nginx/certs/${domains[0]}" \
|
||||
)
|
||||
|
||||
# Test folder paths
|
||||
|
@ -55,8 +52,6 @@ symlinks=( \
|
|||
[1]="/etc/nginx/certs/${domains[0]}.key" \
|
||||
[2]="/etc/nginx/certs/${domains[0]}.chain.pem" \
|
||||
[3]="/etc/nginx/certs/${domains[0]}.dhparam.pem" \
|
||||
[4]="/etc/nginx/certs/${domains[0]}/account_key.json" \
|
||||
[5]="/etc/nginx/certs/${domains[0]}/account_reg.json" \
|
||||
)
|
||||
|
||||
# Test symlinks paths
|
||||
|
@ -70,9 +65,7 @@ symlinks=( \
|
|||
# Array of private file paths to test
|
||||
private_files=( \
|
||||
[0]="/etc/nginx/certs/default.key" \
|
||||
[1]="/etc/nginx/certs/accounts/boulder:4001/directory/default_key.json" \
|
||||
[2]="/etc/nginx/certs/accounts/boulder:4001/directory/default_reg.json" \
|
||||
[3]="/etc/nginx/certs/${domains[0]}/key.pem" \
|
||||
[1]="/etc/nginx/certs/${domains[0]}/key.pem" \
|
||||
)
|
||||
|
||||
# Test private file paths
|
||||
|
|
|
@ -23,8 +23,8 @@ function cleanup {
|
|||
symlink-lim-le2 \
|
||||
> /dev/null 2>&1
|
||||
# Cleanup the files created by this run of the test to avoid foiling following test(s).
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/lim.it*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/le?.wtf* && rm -rf /etc/acme.sh/default/le?.wtf*'
|
||||
docker exec "$le_container_name" bash -c 'rm -rf /etc/nginx/certs/lim.it* && rm -rf /etc/acme.sh/default/lim.it*'
|
||||
# Stop the LE container
|
||||
docker stop "$le_container_name" > /dev/null
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ function run_le_container {
|
|||
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||
$cli_args \
|
||||
--env "DHPARAM_BITS=256" \
|
||||
--env "DEBUG=true" \
|
||||
--env "DEBUG=2" \
|
||||
--env "ACME_CA_URI=http://boulder:4001/directory" \
|
||||
--label com.github.jrcs.letsencrypt_nginx_proxy_companion.test_suite \
|
||||
--network boulder_bluenet \
|
||||
|
|
Loading…
Reference in New Issue