2017-06-12 16:45:12 +08:00
#!/bin/bash
2017-09-21 15:46:09 +08:00
set -o pipefail
exec 5>& 1
2017-06-12 16:45:12 +08:00
2020-02-05 17:53:23 +08:00
# Do not attempt to write to slave
if [ [ ! -z ${ REDIS_SLAVEOF_IP } ] ] ; then
export REDIS_CMDLINE = " redis-cli -h ${ REDIS_SLAVEOF_IP } -p ${ REDIS_SLAVEOF_PORT } "
else
export REDIS_CMDLINE = "redis-cli -h redis -p 6379"
fi
2020-03-09 03:23:32 +08:00
until [ [ $( ${ REDIS_CMDLINE } PING) = = "PONG" ] ] ; do
echo "Waiting for Redis..."
sleep 2
done
2019-10-19 18:48:56 +08:00
source /srv/functions.sh
2018-06-27 05:10:24 +08:00
# Thanks to https://github.com/cvmiller -> https://github.com/cvmiller/expand6
source /srv/expand6.sh
2019-03-29 14:46:52 +08:00
# Skipping IP check when we like to live dangerously
if [ [ " ${ SKIP_IP_CHECK } " = ~ ^( [ yY] [ eE] [ sS] | [ yY] ) +$ ] ] ; then
SKIP_IP_CHECK = y
fi
# Skipping HTTP check when we like to live dangerously
if [ [ " ${ SKIP_HTTP_VERIFICATION } " = ~ ^( [ yY] [ eE] [ sS] | [ yY] ) +$ ] ] ; then
SKIP_HTTP_VERIFICATION = y
fi
2019-10-19 18:48:56 +08:00
# Request certificate for MAILCOW_HOSTNAME only
2019-04-27 03:15:46 +08:00
if [ [ " ${ ONLY_MAILCOW_HOSTNAME } " = ~ ^( [ yY] [ eE] [ sS] | [ yY] ) +$ ] ] ; then
ONLY_MAILCOW_HOSTNAME = y
fi
2019-10-19 18:48:56 +08:00
# Request individual certificate for every domain
if [ [ " ${ ENABLE_SSL_SNI } " = ~ ^( [ yY] [ eE] [ sS] | [ yY] ) +$ ] ] ; then
ENABLE_SSL_SNI = y
fi
2017-12-09 20:15:24 +08:00
2017-11-14 17:44:00 +08:00
if [ [ " ${ SKIP_LETS_ENCRYPT } " = ~ ^( [ yY] [ eE] [ sS] | [ yY] ) +$ ] ] ; then
log_f "SKIP_LETS_ENCRYPT=y, skipping Let's Encrypt..."
sleep 365d
exec $( readlink -f " $0 " )
fi
2020-09-29 01:58:30 +08:00
log_f "Waiting for Docker API..."
2017-11-16 21:57:17 +08:00
until ping dockerapi -c1 > /dev/null; do
sleep 1
done
2020-09-29 01:58:30 +08:00
log_f "Docker API OK"
2017-11-16 21:57:17 +08:00
2020-09-29 01:58:30 +08:00
log_f "Waiting for Postfix..."
2020-09-27 05:33:28 +08:00
until ping postfix -c1 > /dev/null; do
sleep 1
done
2020-09-29 01:58:30 +08:00
log_f "Postfix OK"
2020-09-27 05:33:28 +08:00
2020-09-29 01:58:30 +08:00
log_f "Waiting for Dovecot..."
2020-09-27 05:33:28 +08:00
until ping dovecot -c1 > /dev/null; do
sleep 1
done
2020-09-29 01:58:30 +08:00
log_f "Dovecot OK"
2020-09-27 05:33:28 +08:00
2017-06-12 16:45:12 +08:00
ACME_BASE = /var/lib/acme
2017-06-21 02:06:54 +08:00
SSL_EXAMPLE = /var/lib/ssl-example
2017-06-29 16:25:32 +08:00
2019-02-05 05:36:17 +08:00
mkdir -p ${ ACME_BASE } /acme
# Migrate
[ [ -f ${ ACME_BASE } /acme/private/privkey.pem ] ] && mv ${ ACME_BASE } /acme/private/privkey.pem ${ ACME_BASE } /acme/key.pem
[ [ -f ${ ACME_BASE } /acme/private/account.key ] ] && mv ${ ACME_BASE } /acme/private/account.key ${ ACME_BASE } /acme/account.pem
2019-10-19 18:48:56 +08:00
if [ [ -f ${ ACME_BASE } /acme/key.pem && -f ${ ACME_BASE } /acme/cert.pem ] ] ; then
if verify_hash_match ${ ACME_BASE } /acme/cert.pem ${ ACME_BASE } /acme/key.pem; then
2020-09-29 01:58:30 +08:00
log_f "Migrating to SNI folder structure..."
2019-10-19 18:48:56 +08:00
CERT_DOMAIN = ( $( openssl x509 -noout -text -in ${ ACME_BASE } /acme/cert.pem | grep "Subject:" | sed -e 's/\(Subject:\)\|\(CN = \)\|\(CN=\)//g' | sed -e 's/^[[:space:]]*//' ) )
CERT_DOMAINS = ( ${ CERT_DOMAIN } $( openssl x509 -noout -text -in ${ ACME_BASE } /acme/cert.pem | grep "DNS:" | sed -e 's/\(DNS:\)\|,//g' | sed " s/ ${ CERT_DOMAIN } // " | sed -e 's/^[[:space:]]*//' ) )
mkdir -p ${ ACME_BASE } /${ CERT_DOMAIN }
mv ${ ACME_BASE } /acme/cert.pem ${ ACME_BASE } /${ CERT_DOMAIN } /cert.pem
# key is only copied, not moved, because it is used by all other requests too
cp ${ ACME_BASE } /acme/key.pem ${ ACME_BASE } /${ CERT_DOMAIN } /key.pem
chmod 600 ${ ACME_BASE } /${ CERT_DOMAIN } /key.pem
echo -n ${ CERT_DOMAINS [*] } > ${ ACME_BASE } /${ CERT_DOMAIN } /domains
mv ${ ACME_BASE } /acme/acme.csr ${ ACME_BASE } /${ CERT_DOMAIN } /acme.csr
log_f "OK" no_date
2017-10-21 16:08:14 +08:00
fi
2019-10-19 18:48:56 +08:00
fi
2019-02-05 05:36:17 +08:00
2017-06-29 06:56:51 +08:00
[ [ ! -f ${ ACME_BASE } /dhparams.pem ] ] && cp ${ SSL_EXAMPLE } /dhparams.pem ${ ACME_BASE } /dhparams.pem
2019-04-27 16:23:00 +08:00
if [ [ -f ${ ACME_BASE } /cert.pem ] ] && [ [ -f ${ ACME_BASE } /key.pem ] ] && [ [ $( stat -c%s ${ ACME_BASE } /cert.pem) != 0 ] ] ; then
2017-10-21 16:08:14 +08:00
ISSUER = $( openssl x509 -in ${ ACME_BASE } /cert.pem -noout -issuer)
2018-10-25 02:14:59 +08:00
if [ [ ${ ISSUER } != *"Let's Encrypt" * && ${ ISSUER } != *"mailcow" * && ${ ISSUER } != *"Fake LE Intermediate" * ] ] ; then
2017-10-21 16:08:14 +08:00
log_f "Found certificate with issuer other than mailcow snake-oil CA and Let's Encrypt, skipping ACME client..."
sleep 3650d
exec $( readlink -f " $0 " )
fi
2017-06-21 02:06:54 +08:00
else
2019-10-19 18:48:56 +08:00
if [ [ -f ${ ACME_BASE } /${ MAILCOW_HOSTNAME } /cert.pem ] ] && [ [ -f ${ ACME_BASE } /${ MAILCOW_HOSTNAME } /key.pem ] ] && verify_hash_match ${ ACME_BASE } /${ MAILCOW_HOSTNAME } /cert.pem ${ ACME_BASE } /${ MAILCOW_HOSTNAME } /key.pem; then
log_f "Restoring previous acme certificate and restarting script..."
cp ${ ACME_BASE } /${ MAILCOW_HOSTNAME } /cert.pem ${ ACME_BASE } /cert.pem
cp ${ ACME_BASE } /${ MAILCOW_HOSTNAME } /key.pem ${ ACME_BASE } /key.pem
# Restarting with env var set to trigger a restart,
exec env TRIGGER_RESTART = 1 $( readlink -f " $0 " )
2017-10-21 16:08:14 +08:00
else
log_f "Restoring mailcow snake-oil certificates and restarting script..."
cp ${ SSL_EXAMPLE } /cert.pem ${ ACME_BASE } /cert.pem
cp ${ SSL_EXAMPLE } /key.pem ${ ACME_BASE } /key.pem
exec env TRIGGER_RESTART = 1 $( readlink -f " $0 " )
fi
2017-06-17 16:08:12 +08:00
fi
2019-10-19 18:48:56 +08:00
2019-03-13 06:24:03 +08:00
chmod 600 ${ ACME_BASE } /key.pem
2017-06-17 16:08:12 +08:00
2020-09-29 01:58:30 +08:00
log_f "Waiting for database..."
while ! mysqladmin status --socket= /var/run/mysqld/mysqld.sock -u${ DBUSER } -p${ DBPASS } --silent > /dev/null; do
2017-10-21 16:08:14 +08:00
sleep 2
2017-09-28 01:48:25 +08:00
done
2020-09-29 01:58:30 +08:00
log_f "Database OK"
2019-02-11 00:36:25 +08:00
2020-09-29 01:58:30 +08:00
log_f "Waiting for Nginx..."
2019-02-11 00:36:25 +08:00
until $( curl --output /dev/null --silent --head --fail http://nginx:8081) ; do
sleep 2
done
2020-09-29 01:58:30 +08:00
log_f "Nginx OK"
log_f "Waiting for resolver..."
until dig letsencrypt.org +time= 3 +tries= 1 @unbound > /dev/null; do
sleep 2
done
log_f "Resolver OK"
2018-06-27 05:35:17 +08:00
2019-02-05 05:36:17 +08:00
# Waiting for domain table
2020-09-29 01:58:30 +08:00
log_f "Waiting for domain table..."
2019-02-05 05:36:17 +08:00
while [ [ -z ${ DOMAIN_TABLE } ] ] ; do
curl --silent http://nginx/ >/dev/null 2>& 1
DOMAIN_TABLE = $( mysql --socket= /var/run/mysqld/mysqld.sock -u ${ DBUSER } -p${ DBPASS } ${ DBNAME } -e "SHOW TABLES LIKE 'domain'" -Bs)
[ [ -z ${ DOMAIN_TABLE } ] ] && sleep 10
done
log_f "OK" no_date
2020-09-29 01:58:30 +08:00
log_f "Initializing, please wait..."
2017-09-28 01:48:25 +08:00
2017-06-12 16:45:12 +08:00
while true; do
2020-09-27 05:33:28 +08:00
POSTFIX_CERT_SERIAL = " $( echo | openssl s_client -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2) "
DOVECOT_CERT_SERIAL = " $( echo | openssl s_client -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2) "
POSTFIX_CERT_SERIAL_NEW = " $( echo | openssl s_client -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2) "
DOVECOT_CERT_SERIAL_NEW = " $( echo | openssl s_client -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2) "
2019-02-05 05:36:17 +08:00
# Re-using previous acme-mailcow account and domain keys
if [ [ ! -f ${ ACME_BASE } /acme/key.pem ] ] ; then
2019-10-19 18:48:56 +08:00
log_f "Generating missing domain private rsa key..."
2019-02-05 05:36:17 +08:00
openssl genrsa 4096 > ${ ACME_BASE } /acme/key.pem
else
2019-10-19 18:48:56 +08:00
log_f " Using existing domain rsa key ${ ACME_BASE } /acme/key.pem "
2019-02-05 05:36:17 +08:00
fi
if [ [ ! -f ${ ACME_BASE } /acme/account.pem ] ] ; then
log_f "Generating missing Lets Encrypt account key..."
openssl genrsa 4096 > ${ ACME_BASE } /acme/account.pem
else
log_f " Using existing Lets Encrypt account key ${ ACME_BASE } /acme/account.pem "
fi
2019-03-13 06:24:03 +08:00
chmod 600 ${ ACME_BASE } /acme/key.pem
chmod 600 ${ ACME_BASE } /acme/account.pem
2019-10-19 18:48:56 +08:00
unset EXISTING_CERTS
declare -a EXISTING_CERTS
for cert_dir in ${ ACME_BASE } /*/ ; do
if [ [ ! -f ${ cert_dir } domains ] ] || [ [ ! -f ${ cert_dir } cert.pem ] ] || [ [ ! -f ${ cert_dir } key.pem ] ] ; then
continue
fi
EXISTING_CERTS += ( " $( basename ${ cert_dir } ) " )
done
2019-02-05 05:36:17 +08:00
# Cleaning up and init validation arrays
2017-10-21 16:08:14 +08:00
unset SQL_DOMAIN_ARR
unset VALIDATED_CONFIG_DOMAINS
unset ADDITIONAL_VALIDATED_SAN
2019-02-05 05:36:17 +08:00
unset ADDITIONAL_WC_ARR
unset ADDITIONAL_SAN_ARR
2019-10-19 18:48:56 +08:00
unset CERT_ERRORS
unset CERT_CHANGED
unset CERT_AMOUNT_CHANGED
unset VALIDATED_CERTIFICATES
CERT_ERRORS = 0
CERT_CHANGED = 0
CERT_AMOUNT_CHANGED = 0
2017-10-21 16:08:14 +08:00
declare -a SQL_DOMAIN_ARR
declare -a VALIDATED_CONFIG_DOMAINS
declare -a ADDITIONAL_VALIDATED_SAN
2019-02-05 05:36:17 +08:00
declare -a ADDITIONAL_WC_ARR
declare -a ADDITIONAL_SAN_ARR
2019-10-19 18:48:56 +08:00
declare -a VALIDATED_CERTIFICATES
2018-04-04 20:06:41 +08:00
IFS = ',' read -r -a TMP_ARR <<< " ${ ADDITIONAL_SAN } "
for i in " ${ TMP_ARR [@] } " ; do
if [ [ " $i " = ~ \. \* $ ] ] ; then
ADDITIONAL_WC_ARR += ( ${ i : :- 2 } )
else
ADDITIONAL_SAN_ARR += ( $i )
fi
done
2019-06-26 00:52:05 +08:00
ADDITIONAL_WC_ARR += ( 'autodiscover' 'autoconfig' )
2018-04-04 20:06:41 +08:00
2019-02-05 05:36:17 +08:00
# Start IP detection
2020-09-29 01:58:30 +08:00
log_f "Detecting IP addresses..."
2018-01-01 00:17:46 +08:00
IPV4 = $( get_ipv4)
2018-06-27 05:10:24 +08:00
IPV6 = $( get_ipv6)
2020-09-29 01:58:30 +08:00
log_f " OK: ${ IPV4 } , ${ IPV6 :- "0000:0000:0000:0000:0000:0000:0000:0000" } "
2018-06-27 05:10:24 +08:00
2018-08-06 04:35:02 +08:00
# Hard-fail on CAA errors for MAILCOW_HOSTNAME
MH_PARENT_DOMAIN = $( echo ${ MAILCOW_HOSTNAME } | cut -d. -f2-)
MH_CAAS = ( $( dig CAA ${ MH_PARENT_DOMAIN } +short | sed -n 's/\d issue "\(.*\)"/\1/p' ) )
if [ [ ! -z ${ MH_CAAS } ] ] ; then
if [ [ ${ MH_CAAS [@] } = ~ "letsencrypt.org" ] ] ; then
2019-10-19 18:48:56 +08:00
log_f " Validated CAA for parent domain ${ MH_PARENT_DOMAIN } "
2018-08-06 04:35:02 +08:00
else
2019-10-19 18:48:56 +08:00
log_f " Skipping ACME validation: Lets Encrypt disallowed for ${ MAILCOW_HOSTNAME } by CAA record, retrying in 1h... "
2018-08-06 04:35:02 +08:00
sleep 1h
exec $( readlink -f " $0 " )
fi
fi
2019-02-05 05:36:17 +08:00
#########################################
# IP and webroot challenge verification #
2021-03-03 14:59:11 +08:00
SQL_DOMAINS = $( mysql --socket= /var/run/mysqld/mysqld.sock -u ${ DBUSER } -p${ DBPASS } ${ DBNAME } -e "SELECT domain FROM domain WHERE backupmx=0 and active=1" -Bs)
2019-10-19 18:48:56 +08:00
if [ [ ! $? -eq 0 ] ] ; then
log_f "Failed to read SQL domains, retrying in 1 minute..."
sleep 1m
exec $( readlink -f " $0 " )
fi
2017-10-21 16:08:14 +08:00
while read domains; do
2019-10-20 00:23:59 +08:00
if [ [ -z " ${ domains } " ] ] ; then
# ignore empty lines
continue
fi
2017-10-21 16:08:14 +08:00
SQL_DOMAIN_ARR += ( " ${ domains } " )
2019-10-19 18:48:56 +08:00
done <<< " ${ SQL_DOMAINS } "
2017-10-21 16:08:14 +08:00
2019-04-27 03:15:46 +08:00
if [ [ ${ ONLY_MAILCOW_HOSTNAME } != "y" ] ] ; then
2018-10-19 16:03:05 +08:00
for SQL_DOMAIN in " ${ SQL_DOMAIN_ARR [@] } " ; do
2019-10-19 18:48:56 +08:00
unset VALIDATED_CONFIG_DOMAINS_SUBDOMAINS
declare -a VALIDATED_CONFIG_DOMAINS_SUBDOMAINS
2018-04-04 20:06:41 +08:00
for SUBDOMAIN in " ${ ADDITIONAL_WC_ARR [@] } " ; do
2019-10-19 18:48:56 +08:00
if [ [ " ${ SUBDOMAIN } . ${ SQL_DOMAIN } " != " ${ MAILCOW_HOSTNAME } " ] ] ; then
if check_domain " ${ SUBDOMAIN } . ${ SQL_DOMAIN } " ; then
VALIDATED_CONFIG_DOMAINS_SUBDOMAINS += ( " ${ SUBDOMAIN } . ${ SQL_DOMAIN } " )
2018-04-04 20:06:41 +08:00
fi
2017-10-21 16:08:14 +08:00
fi
2018-04-04 20:06:41 +08:00
done
2019-10-19 18:48:56 +08:00
VALIDATED_CONFIG_DOMAINS += ( " ${ VALIDATED_CONFIG_DOMAINS_SUBDOMAINS [*] } " )
2017-10-21 16:08:14 +08:00
done
2019-04-27 03:15:46 +08:00
fi
2017-06-12 16:45:12 +08:00
2019-10-19 18:48:56 +08:00
if check_domain ${ MAILCOW_HOSTNAME } ; then
VALIDATED_MAILCOW_HOSTNAME = " ${ MAILCOW_HOSTNAME } "
2017-10-21 16:08:14 +08:00
fi
2017-06-29 05:22:51 +08:00
2019-04-27 03:15:46 +08:00
if [ [ ${ ONLY_MAILCOW_HOSTNAME } != "y" ] ] ; then
2017-10-21 16:08:14 +08:00
for SAN in " ${ ADDITIONAL_SAN_ARR [@] } " ; do
2018-08-06 04:35:02 +08:00
# Skip on CAA errors for SAN
SAN_PARENT_DOMAIN = $( echo ${ SAN } | cut -d. -f2-)
SAN_CAAS = ( $( dig CAA ${ SAN_PARENT_DOMAIN } +short | sed -n 's/\d issue "\(.*\)"/\1/p' ) )
if [ [ ! -z ${ SAN_CAAS } ] ] ; then
if [ [ ${ SAN_CAAS [@] } = ~ "letsencrypt.org" ] ] ; then
2019-10-19 18:48:56 +08:00
log_f " Validated CAA for parent domain ${ SAN_PARENT_DOMAIN } of ${ SAN } "
2018-08-06 04:35:02 +08:00
else
2019-10-19 18:48:56 +08:00
log_f " Skipping ACME validation for ${ SAN } : Lets Encrypt disallowed for ${ SAN } by CAA record "
2018-08-06 04:35:02 +08:00
continue
fi
fi
2017-10-21 16:08:14 +08:00
if [ [ ${ SAN } = = ${ MAILCOW_HOSTNAME } ] ] ; then
continue
fi
2019-10-19 18:48:56 +08:00
if check_domain ${ SAN } ; then
ADDITIONAL_VALIDATED_SAN += ( " ${ SAN } " )
2018-06-29 02:41:44 +08:00
fi
2019-10-19 18:48:56 +08:00
done
fi
# Unique domains for server certificate
if [ [ ${ ENABLE_SSL_SNI } = = "y" ] ] ; then
# create certificate for server name and fqdn SANs only
SERVER_SAN_VALIDATED = ( ${ VALIDATED_MAILCOW_HOSTNAME } $( echo ${ ADDITIONAL_VALIDATED_SAN [*] } | xargs -n1 | sort -u | xargs) )
else
# create certificate for all domains, including all subdomains from other domains [*]
SERVER_SAN_VALIDATED = ( ${ VALIDATED_MAILCOW_HOSTNAME } $( echo ${ VALIDATED_CONFIG_DOMAINS [*] } ${ ADDITIONAL_VALIDATED_SAN [*] } | xargs -n1 | sort -u | xargs) )
fi
if [ [ ! -z ${ SERVER_SAN_VALIDATED [*] } ] ] ; then
CERT_NAME = ${ SERVER_SAN_VALIDATED [0] }
VALIDATED_CERTIFICATES += ( " ${ CERT_NAME } " )
# obtain server certificate if required
DOMAINS = ${ SERVER_SAN_VALIDATED [@] } /srv/obtain-certificate.sh rsa
RETURN = " $? "
if [ [ " $RETURN " = = "0" ] ] ; then # 0 = cert created successfully
CERT_AMOUNT_CHANGED = 1
CERT_CHANGED = 1
elif [ [ " $RETURN " = = "1" ] ] ; then # 1 = cert renewed successfully
CERT_CHANGED = 1
elif [ [ " $RETURN " = = "2" ] ] ; then # 2 = cert not due for renewal
:
else
CERT_ERRORS = 1
fi
# copy hostname certificate to default/server certificate
2020-09-29 01:58:30 +08:00
# do not a key when cert is missing, this can lead to a mismatch of cert/key
if [ [ -f ${ ACME_BASE } /${ CERT_NAME } /cert.pem ] ] ; then
cp ${ ACME_BASE } /${ CERT_NAME } /cert.pem ${ ACME_BASE } /cert.pem
cp ${ ACME_BASE } /${ CERT_NAME } /key.pem ${ ACME_BASE } /key.pem
fi
2019-10-19 18:48:56 +08:00
fi
# individual certificates for SNI [@]
if [ [ ${ ENABLE_SSL_SNI } = = "y" ] ] ; then
for VALIDATED_DOMAINS in " ${ VALIDATED_CONFIG_DOMAINS [@] } " ; do
VALIDATED_DOMAINS_ARR = ( ${ VALIDATED_DOMAINS } )
unset VALIDATED_DOMAINS_SORTED
declare -a VALIDATED_DOMAINS_SORTED
VALIDATED_DOMAINS_SORTED = ( ${ VALIDATED_DOMAINS_ARR [0] } $( echo ${ VALIDATED_DOMAINS_ARR [@] : 1 } | xargs -n1 | sort -u | xargs) )
2019-10-20 20:44:39 +08:00
# remove all domain names that are already inside the server certificate (SERVER_SAN_VALIDATED)
for domain in " ${ SERVER_SAN_VALIDATED [@] } " ; do
for i in " ${ !VALIDATED_DOMAINS_SORTED[@] } " ; do
if [ [ ${ VALIDATED_DOMAINS_SORTED [i] } = $domain ] ] ; then
unset 'VALIDATED_DOMAINS_SORTED[i]'
fi
done
done
2019-10-19 18:48:56 +08:00
if [ [ ! -z ${ VALIDATED_DOMAINS_SORTED [*] } ] ] ; then
CERT_NAME = ${ VALIDATED_DOMAINS_SORTED [0] }
VALIDATED_CERTIFICATES += ( " ${ CERT_NAME } " )
# obtain certificate if required
DOMAINS = ${ VALIDATED_DOMAINS_SORTED [@] } /srv/obtain-certificate.sh rsa
RETURN = " $? "
if [ [ " $RETURN " = = "0" ] ] ; then # 0 = cert created successfully
CERT_AMOUNT_CHANGED = 1
CERT_CHANGED = 1
elif [ [ " $RETURN " = = "1" ] ] ; then # 1 = cert renewed successfully
CERT_CHANGED = 1
elif [ [ " $RETURN " = = "2" ] ] ; then # 2 = cert not due for renewal
:
2017-10-21 16:08:14 +08:00
else
2019-10-19 18:48:56 +08:00
CERT_ERRORS = 1
2017-10-21 16:08:14 +08:00
fi
fi
done
2019-04-27 03:15:46 +08:00
fi
2017-06-14 13:24:32 +08:00
2019-10-19 18:48:56 +08:00
if [ [ -z ${ VALIDATED_CERTIFICATES [*] } ] ] ; then
log_f "Cannot validate any hostnames, skipping Let's Encrypt for 1 hour."
2017-10-21 16:08:14 +08:00
log_f "Use SKIP_LETS_ENCRYPT=y in mailcow.conf to skip it permanently."
2020-02-05 17:53:23 +08:00
${ REDIS_CMDLINE } SET ACME_FAIL_TIME " $( date +%s) "
2017-10-21 16:08:14 +08:00
sleep 1h
exec $( readlink -f " $0 " )
fi
2017-06-29 05:22:51 +08:00
2019-10-19 18:48:56 +08:00
# find orphaned certificates if no errors occurred
if [ [ " ${ CERT_ERRORS } " = = "0" ] ] ; then
for EXISTING_CERT in " ${ EXISTING_CERTS [@] } " ; do
if [ [ ! "`printf '_%s_\n' " ${ VALIDATED_CERTIFICATES [@] } "`" = = *" _ ${ EXISTING_CERT } _ " * ] ] ; then
DATE = $( date +%Y-%m-%d_%H_%M_%S)
log_f " Found orphaned certificate: ${ EXISTING_CERT } - archiving it at ${ ACME_BASE } /backups/ ${ EXISTING_CERT } / "
BACKUP_DIR = ${ ACME_BASE } /backups/${ EXISTING_CERT } /${ DATE }
# archive rsa cert and any other files
2020-01-18 05:36:04 +08:00
mkdir -p ${ ACME_BASE } /backups/${ EXISTING_CERT }
2019-10-19 18:48:56 +08:00
mv ${ ACME_BASE } /${ EXISTING_CERT } ${ BACKUP_DIR }
CERT_CHANGED = 1
CERT_AMOUNT_CHANGED = 1
fi
done
2019-02-05 05:36:17 +08:00
fi
2019-10-19 18:48:56 +08:00
# reload on new or changed certificates
if [ [ " ${ CERT_CHANGED } " = = "1" ] ] ; then
2020-03-03 21:59:24 +08:00
rm -f " ${ ACME_BASE } /force_renew " 2> /dev/null
2020-09-27 05:33:28 +08:00
RELOAD_LOOP_C = 1
while [ [ " ${ POSTFIX_CERT_SERIAL } " = = " ${ POSTFIX_CERT_SERIAL_NEW } " ] ] || [ [ " ${ DOVECOT_CERT_SERIAL } " = = " ${ DOVECOT_CERT_SERIAL_NEW } " ] ] || [ [ ${# POSTFIX_CERT_SERIAL_NEW } -ne 36 ] ] || [ [ ${# DOVECOT_CERT_SERIAL_NEW } -ne 36 ] ] ; do
log_f " Reloading or restarting services... ( ${ RELOAD_LOOP_C } ) "
RELOAD_LOOP_C = $(( RELOAD_LOOP_C + 1 ))
CERT_AMOUNT_CHANGED = ${ CERT_AMOUNT_CHANGED } /srv/reload-configurations.sh
log_f "Waiting for containers to settle..."
sleep 10
until nc -z dovecot 143; do
sleep 1
done
until nc -z postfix 25; do
sleep 1
done
POSTFIX_CERT_SERIAL_NEW = " $( echo | openssl s_client -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2) "
DOVECOT_CERT_SERIAL_NEW = " $( echo | openssl s_client -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2) "
if [ [ ${ RELOAD_LOOP_C } -gt 3 ] ] ; then
log_f "Some services do return old end dates, something went wrong!"
${ REDIS_CMDLINE } SET ACME_FAIL_TIME " $( date +%s) "
break;
fi
done
2018-10-25 02:14:59 +08:00
fi
2019-10-19 18:48:56 +08:00
case " $CERT_ERRORS " in
0) # all successful
if [ [ " ${ CERT_CHANGED } " = = "1" ] ] ; then
if [ [ " ${ CERT_AMOUNT_CHANGED } " = = "1" ] ] ; then
log_f "Certificates successfully requested and renewed where required, sleeping one day"
else
log_f "Certificates were successfully renewed where required, sleeping for another day."
fi
2019-02-05 05:36:17 +08:00
else
2019-10-19 18:48:56 +08:00
log_f "Certificates were successfully validated, no changes or renewals required, sleeping for another day."
2017-10-21 16:08:14 +08:00
fi
2019-10-19 18:48:56 +08:00
sleep 1d
2017-10-21 16:08:14 +08:00
; ;
2019-10-19 18:48:56 +08:00
*) # non-zero
log_f "Some errors occurred, retrying in 30 minutes..."
2020-02-05 17:53:23 +08:00
${ REDIS_CMDLINE } SET ACME_FAIL_TIME " $( date +%s) "
2017-10-21 16:08:14 +08:00
sleep 30m
exec $( readlink -f " $0 " )
; ;
esac
2017-06-12 16:45:12 +08:00
done