mirror of
https://github.com/zulip/zulip.git
synced 2026-06-30 21:11:04 +08:00
The certbot package installs its own systemd timer (and cron job, which disabled itself if systemd is enabled) which updates certificates. This process races with the cron job which Zulip installs -- the only difference being that Zulip respects the `certbot.auto_renew` setting, and that it passes the deploy hook. This means that occasionally nginx would not be reloaded, when the systemd timer caught the expiration first. Remove the custom cron job and `certbot-maybe-renew` script, and reconfigure certbot to always reload nginx after deploying, using certbot directory hooks. Since `certbot.auto_renew` can't have an effect, remove the setting. In turn, this removes the need for `--no-zulip-conf` to `setup-certbot`. `--deploy-hook` is similarly removed, as running deploy hooks to restart nginx is now the default; pass `--no-directory-hooks` in standalone mode to not attempt to reload nginx. The other property of `--deploy-hook`, of skipping symlinking into place, is given its own flog.
129 lines
2.8 KiB
Bash
Executable File
129 lines
2.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -e
|
|
|
|
usage() {
|
|
cat <<EOF >&2
|
|
Usage: $0 --email=admin@example.com [--method={webroot|standalone}] \
|
|
hostname.example.com [another.example.com]
|
|
EOF
|
|
exit 1
|
|
}
|
|
|
|
if [ "$EUID" -ne 0 ]; then
|
|
echo "Error: This script must be run as root" >&2
|
|
exit 1
|
|
fi
|
|
|
|
method=webroot
|
|
args="$(getopt -o '' --long help,email:,method:,skip-symlink,agree-tos -n "$0" -- "$@")"
|
|
eval "set -- $args"
|
|
while true; do
|
|
case "$1" in
|
|
--email)
|
|
EMAIL="$2"
|
|
shift
|
|
shift
|
|
;;
|
|
--method)
|
|
method="$2"
|
|
shift
|
|
shift
|
|
;;
|
|
--skip-symlink)
|
|
skip_symlink=1
|
|
shift
|
|
;;
|
|
--agree-tos)
|
|
agree_tos=--agree-tos
|
|
shift
|
|
;;
|
|
--help)
|
|
show_help=1
|
|
shift
|
|
;;
|
|
--)
|
|
shift
|
|
break
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Parse the remaining arguments as Subject Alternative Names to pass to certbot
|
|
HOSTNAMES=()
|
|
for arg; do
|
|
HOSTNAMES+=(-d "$arg")
|
|
done
|
|
DOMAIN=$1
|
|
|
|
if [ -n "$show_help" ]; then
|
|
usage
|
|
fi
|
|
|
|
if [ -z "$DOMAIN" ] || [ -z "$EMAIL" ]; then
|
|
usage
|
|
fi
|
|
|
|
case "$method" in
|
|
standalone)
|
|
method_args=(--standalone --no-directory-hooks)
|
|
;;
|
|
webroot)
|
|
method_args=(--webroot '--webroot-path=/var/lib/zulip/certbot-webroot/')
|
|
;;
|
|
*)
|
|
usage
|
|
;;
|
|
esac
|
|
|
|
# Check for a supported OS release.
|
|
if [ -f /etc/os-release ]; then
|
|
os_info="$(
|
|
. /etc/os-release
|
|
printf '%s\n' "$ID" "$ID_LIKE"
|
|
)"
|
|
{
|
|
read -r os_id
|
|
read -r os_id_like || true
|
|
} <<<"$os_info"
|
|
fi
|
|
|
|
set -x
|
|
|
|
case " $os_id $os_id_like " in
|
|
*' debian '*)
|
|
apt-get update
|
|
apt-get install -y certbot
|
|
;;
|
|
*' rhel '*)
|
|
yum install -y certbot
|
|
;;
|
|
esac
|
|
|
|
# We don't use --no-interactive, because certbot needs to ask the user
|
|
# to agree to the Let's Encrypt Subscriber Agreement (aka ToS).
|
|
# Passing --force-interactive suppresses a warning, but also brings up
|
|
# an annoying prompt we stifle with --no-eff-email.
|
|
certbot certonly "${method_args[@]}" \
|
|
"${HOSTNAMES[@]}" -m "$EMAIL" \
|
|
$agree_tos \
|
|
--force-interactive --no-eff-email
|
|
|
|
symlink_with_backup() {
|
|
if [ -e "$2" ]; then
|
|
# If the user is setting up our automatic certbot-management on a
|
|
# system that already has certs for Zulip, use some extra caution
|
|
# to keep the old certs available.
|
|
mv -f --backup=numbered "$2" "$2".setup-certbot || true
|
|
fi
|
|
ln -nsf "$1" "$2"
|
|
}
|
|
|
|
if [ -z "$skip_symlink" ]; then
|
|
CERT_DIR=/etc/letsencrypt/live/"$DOMAIN"
|
|
symlink_with_backup "$CERT_DIR"/privkey.pem /etc/ssl/private/zulip.key
|
|
symlink_with_backup "$CERT_DIR"/fullchain.pem /etc/ssl/certs/zulip.combined-chain.crt
|
|
fi
|
|
|
|
echo "Certbot SSL certificate configuration succeeded."
|