mirror of
https://github.com/zulip/docker-zulip.git
synced 2025-10-23 04:51:58 +00:00
The task is to generate a self-signed cert so Zulip can be started, then to wait until Zulip is up before using certbot to generate new certs. Zulip needs to be up so it can meet certbot's challenge. Using a deploy hook, certs are persisted in the data directory. The same applies to renewal. Tweaked by tabbott mostly to edit comments remove an unnecessary setting before merging. Fixes #120.
599 lines
21 KiB
Bash
Executable File
599 lines
21 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
if [ "$DEBUG" = "true" ] || [ "$DEBUG" = "True" ]; then
|
|
set -x
|
|
set -o functrace
|
|
fi
|
|
set -e
|
|
|
|
# DB aka Database
|
|
DB_HOST="${DB_HOST:-127.0.0.1}"
|
|
DB_HOST_PORT="${DB_HOST_PORT:-5432}"
|
|
DB_NAME="${DB_NAME:-zulip}"
|
|
DB_USER="${DB_USER:-zulip}"
|
|
REMOTE_POSTGRES_SSLMODE="${REMOTE_POSTGRES_SSLMODE:-prefer}"
|
|
# RabbitMQ
|
|
IGNORE_RABBITMQ_ERRORS="${IGNORE_RABBITMQ_ERRORS:-true}"
|
|
SETTING_RABBITMQ_HOST="${SETTING_RABBITMQ_HOST:-127.0.0.1}"
|
|
SETTING_RABBITMQ_USER="${SETTING_RABBITMQ_USER:-zulip}"
|
|
SETTING_RABBITMQ_PASSWORD="${SETTING_RABBITMQ_PASSWORD:-zulip}"
|
|
SECRETS_rabbitmq_password="${SECRETS_rabbitmq_password:-$(echo $SETTING_RABBITMQ_PASSWORD)}"
|
|
unset SETTING_RABBITMQ_PASSWORD
|
|
export RABBITMQ_NODE="$SETTING_RABBITMQ_HOST"
|
|
# Redis
|
|
SETTING_RATE_LIMITING="${SETTING_RATE_LIMITING:-True}"
|
|
SETTING_REDIS_HOST="${SETTING_REDIS_HOST:-127.0.0.1}"
|
|
SETTING_REDIS_PORT="${SETTING_REDIS_PORT:-6379}"
|
|
# Memcached
|
|
if [ -z "$SETTING_MEMCACHED_LOCATION" ]; then
|
|
SETTING_MEMCACHED_LOCATION="127.0.0.1:11211"
|
|
fi
|
|
# Nginx settings
|
|
DISABLE_HTTPS="${DISABLE_HTTPS:-false}"
|
|
NGINX_WORKERS="${NGINX_WORKERS:-2}"
|
|
NGINX_PROXY_BUFFERING="${NGINX_PROXY_BUFFERING:-off}"
|
|
NGINX_MAX_UPLOAD_SIZE="${NGINX_MAX_UPLOAD_SIZE:-24m}"
|
|
# Zulip certifcate parameters
|
|
SSL_CERTIFICATE_GENERATION="${SSL_CERTIFICATE_GENERATION:self-signed}"
|
|
# Zulip related settings
|
|
ZULIP_AUTH_BACKENDS="${ZULIP_AUTH_BACKENDS:-EmailAuthBackend}"
|
|
ZULIP_RUN_POST_SETUP_SCRIPTS="${ZULIP_RUN_POST_SETUP_SCRIPTS:-True}"
|
|
# Zulip user setup
|
|
FORCE_FIRST_START_INIT="${FORCE_FIRST_START_INIT:-False}"
|
|
# Auto backup settings
|
|
AUTO_BACKUP_ENABLED="${AUTO_BACKUP_ENABLED:-True}"
|
|
AUTO_BACKUP_INTERVAL="${AUTO_BACKUP_INTERVAL:-30 3 * * *}"
|
|
# Zulip configuration function specific variable(s)
|
|
SPECIAL_SETTING_DETECTION_MODE="${SPECIAL_SETTING_DETECTION_MODE:-}"
|
|
MANUAL_CONFIGURATION="${MANUAL_CONFIGURATION:-false}"
|
|
LINK_SETTINGS_TO_DATA="${LINK_SETTINGS_TO_DATA:-false}"
|
|
# entrypoint.sh specific variable(s)
|
|
SETTINGS_PY="/etc/zulip/settings.py"
|
|
|
|
# BEGIN appRun functions
|
|
# === initialConfiguration ===
|
|
prepareDirectories() {
|
|
if [ ! -d "$DATA_DIR" ]; then
|
|
mkdir -p "$DATA_DIR"
|
|
fi
|
|
if [ ! -d "$DATA_DIR/backups" ]; then
|
|
echo "Creating backups folder ..."
|
|
mkdir -p "$DATA_DIR/backups"
|
|
echo "Created backups folder."
|
|
fi
|
|
if [ ! -d "$DATA_DIR/certs" ]; then
|
|
echo "Creating certs folder ..."
|
|
mkdir -p "$DATA_DIR/certs"
|
|
echo "Created certs folder."
|
|
fi
|
|
if [ ! -d "$DATA_DIR/uploads" ]; then
|
|
echo "Creating uploads folder ..."
|
|
mkdir -p "$DATA_DIR/uploads"
|
|
echo "Created uploads folder."
|
|
fi
|
|
echo "Preparing and linking the uploads folder ..."
|
|
rm -rf /home/zulip/uploads
|
|
ln -sfT "$DATA_DIR/uploads" /home/zulip/uploads
|
|
chown zulip:zulip -R "$DATA_DIR/uploads"
|
|
# Link settings folder
|
|
if [ "$LINK_SETTINGS_TO_DATA" = "True" ] || [ "$LINK_SETTINGS_TO_DATA" = "true" ]; then
|
|
# Create settings directories
|
|
if [ ! -d "$DATA_DIR/settings" ]; then
|
|
mkdir -p "$DATA_DIR/settings"
|
|
fi
|
|
if [ ! -d "$DATA_DIR/settings/etc-zulip" ]; then
|
|
cp -rf /etc/zulip "$DATA_DIR/settings/etc-zulip"
|
|
fi
|
|
# Link /etc/zulip/ settings folder
|
|
rm -rf /etc/zulip
|
|
ln -sfT "$DATA_DIR/settings/etc-zulip" /etc/zulip
|
|
fi
|
|
echo "Prepared and linked the uploads directory."
|
|
}
|
|
setConfigurationValue() {
|
|
if [ -z "$1" ]; then
|
|
echo "No KEY given for setConfigurationValue."
|
|
return 1
|
|
fi
|
|
if [ -z "$3" ]; then
|
|
echo "No FILE given for setConfigurationValue."
|
|
return 1
|
|
fi
|
|
local KEY="$1"
|
|
local VALUE
|
|
local FILE="$3"
|
|
local TYPE="$4"
|
|
if [ -z "$TYPE" ]; then
|
|
case "$2" in
|
|
[Tt][Rr][Uu][Ee]|[Ff][Aa][Ll][Ss][Ee]|[Nn]one)
|
|
TYPE="bool"
|
|
;;
|
|
[0-9]*)
|
|
TYPE="integer"
|
|
;;
|
|
[\[\(]*[\]\)])
|
|
TYPE="array"
|
|
;;
|
|
*)
|
|
TYPE="string"
|
|
;;
|
|
esac
|
|
fi
|
|
case "$TYPE" in
|
|
emptyreturn)
|
|
if [ -z "$2" ]; then
|
|
return 0
|
|
fi
|
|
;;
|
|
literal)
|
|
VALUE="$1"
|
|
;;
|
|
bool|boolean|int|integer|array)
|
|
VALUE="$KEY = $2"
|
|
;;
|
|
string|*)
|
|
VALUE="$KEY = '${2//\'/\'}'"
|
|
;;
|
|
esac
|
|
echo "$VALUE" >> "$FILE"
|
|
echo "Setting key \"$KEY\", type \"$TYPE\" in file \"$FILE\"."
|
|
}
|
|
nginxConfiguration() {
|
|
echo "Executing nginx configuration ..."
|
|
if [ "$DISABLE_HTTPS" == "True" ] || [ "$DISABLE_HTTPS" == "true" ]; then
|
|
echo "Disabling https in nginx."
|
|
crudini --set /etc/zulip/zulip.conf application_server http_only true
|
|
/home/zulip/deployments/current/scripts/zulip-puppet-apply -f
|
|
fi
|
|
sed -i "s/worker_processes .*/worker_processes $NGINX_WORKERS;/g" /etc/nginx/nginx.conf
|
|
sed -i "s/client_max_body_size .*/client_max_body_size $NGINX_MAX_UPLOAD_SIZE;/g" /etc/nginx/nginx.conf
|
|
sed -i "s/proxy_buffering .*/proxy_buffering $NGINX_PROXY_BUFFERING;/g" /etc/nginx/zulip-include/proxy_longpolling
|
|
echo "Nginx configuration succeeded."
|
|
}
|
|
configureCerts() {
|
|
case "$SSL_CERTIFICATE_GENERATION" in
|
|
self-signed)
|
|
GENERATE_SELF_SIGNED_CERT="True"
|
|
GENERATE_CERTBOT_CERT="False"
|
|
;;
|
|
|
|
certbot)
|
|
GENERATE_SELF_SIGNED_CERT="False"
|
|
GENERATE_CERTBOT_CERT="True"
|
|
;;
|
|
*)
|
|
echo "Not requesting auto-generated self-signed certs."
|
|
GENERATE_CERTBOT_CERT="False"
|
|
GENERATE_SELF_SIGNED_CERT="False"
|
|
;;
|
|
esac
|
|
if [ ! -e "$DATA_DIR/certs/zulip.key" ] && [ ! -e "$DATA_DIR/certs/zulip.combined-chain.crt" ]; then
|
|
|
|
if [ "$GENERATE_CERTBOT_CERT" = "True" ]; then
|
|
# Zulip isn't yet running, so the certbot's challenge can't be met.
|
|
# We'll schedule this for later.
|
|
echo "Scheduling LetsEncrypt cert generation ..."
|
|
GENERATE_CERTBOT_CERT_SCHEDULED=True
|
|
|
|
# Generate self-signed certs just to get Zulip going.
|
|
GENERATE_SELF_SIGNED_CERT=True
|
|
fi
|
|
|
|
if [ "$GENERATE_SELF_SIGNED_CERT" = "True" ]; then
|
|
echo "Generating self-signed certificates ..."
|
|
mkdir -p "$DATA_DIR/certs"
|
|
/home/zulip/deployments/current/scripts/setup/generate-self-signed-cert "$SETTING_EXTERNAL_HOST"
|
|
mv /etc/ssl/private/zulip.key "$DATA_DIR/certs/zulip.key"
|
|
mv /etc/ssl/certs/zulip.combined-chain.crt "$DATA_DIR/certs/zulip.combined-chain.crt"
|
|
echo "Self-signed certificate generation succeeded."
|
|
else
|
|
echo "Certificates already exist. No need to generate them. Continuing."
|
|
fi
|
|
fi
|
|
if [ ! -e "$DATA_DIR/certs/zulip.key" ]; then
|
|
echo "SSL private key zulip.key is not present in $DATA_DIR."
|
|
echo "Certificates configuration failed."
|
|
echo "Consider setting ZULIP_AUTO_GENERATE_CERTS=True in the environment to auto-generate"
|
|
exit 1
|
|
fi
|
|
if [ ! -e "$DATA_DIR/certs/zulip.combined-chain.crt" ]; then
|
|
echo "SSL public key zulip.combined-chain.crt is not present in $DATA_DIR."
|
|
echo "Certificates configuration failed."
|
|
echo "Consider setting ZULIP_AUTO_GENERATE_CERTS=True in the environment to auto-generate"
|
|
exit 1
|
|
fi
|
|
ln -sfT "$DATA_DIR/certs/zulip.key" /etc/ssl/private/zulip.key
|
|
ln -sfT "$DATA_DIR/certs/zulip.combined-chain.crt" /etc/ssl/certs/zulip.combined-chain.crt
|
|
echo "Certificates configuration succeeded."
|
|
}
|
|
secretsConfiguration() {
|
|
echo "Setting Zulip secrets ..."
|
|
if [ ! -e "$DATA_DIR/zulip-secrets.conf" ]; then
|
|
echo "Generating Zulip secrets ..."
|
|
/root/zulip/scripts/setup/generate_secrets.py --production
|
|
mv "/etc/zulip/zulip-secrets.conf" "$DATA_DIR/zulip-secrets.conf" || {
|
|
echo "Couldn't move the generate zulip secrets to the data dir."; exit 1;
|
|
}
|
|
echo "Secrets generation succeeded."
|
|
else
|
|
echo "Secrets already generated/existing."
|
|
fi
|
|
set +e
|
|
local SECRETS=($(env | sed -nr "s/SECRETS_([0-9A-Z_a-z-]*).*/\1/p"))
|
|
for SECRET_KEY in "${SECRETS[@]}"; do
|
|
local key="SECRETS_$SECRET_KEY"
|
|
local SECRET_VAR="${!key}"
|
|
if [ -z "$SECRET_VAR" ]; then
|
|
echo "Empty secret for key \"$SECRET_KEY\"."
|
|
fi
|
|
grep -q "$SECRET_KEY" "$DATA_DIR/zulip-secrets.conf"
|
|
if (($? > 0)); then
|
|
echo "$SECRET_KEY = $SECRET_VAR" >> "$DATA_DIR/zulip-secrets.conf"
|
|
echo "Secret added for \"$SECRET_KEY\"."
|
|
else
|
|
sed -i -r "s~#?$SECRET_KEY[ ]*=.*~$SECRET_KEY = $SECRET_VAR~g" "$DATA_DIR/zulip-secrets.conf"
|
|
echo "Secret found for \"$SECRET_KEY\"."
|
|
fi
|
|
done
|
|
set -e
|
|
unset SECRET_KEY SECRET_VAR key
|
|
if [ -e "/etc/zulip/zulip-secrets.conf" ]; then
|
|
rm "/etc/zulip/zulip-secrets.conf"
|
|
fi
|
|
echo "Linking secrets from data dir to etc zulip ..."
|
|
ln -s "$DATA_DIR/zulip-secrets.conf" "/etc/zulip/zulip-secrets.conf" || {
|
|
echo "Couldn't link existing zulip secrets to etc zulip.";
|
|
exit 1;
|
|
}
|
|
echo "Linked existing secrets from data dir to etc zulip."
|
|
echo "Zulip secrets configuration succeeded."
|
|
}
|
|
databaseConfiguration() {
|
|
echo "Setting database configuration ..."
|
|
setConfigurationValue "REMOTE_POSTGRES_HOST" "$DB_HOST" "$SETTINGS_PY" "string"
|
|
setConfigurationValue "REMOTE_POSTGRES_SSLMODE" "$REMOTE_POSTGRES_SSLMODE" "$SETTINGS_PY" "string"
|
|
# The password will be set in secretsConfiguration
|
|
echo "Database configuration succeeded."
|
|
}
|
|
authenticationBackends() {
|
|
echo "Activating authentication backends ..."
|
|
local FIRST=true
|
|
echo "$ZULIP_AUTH_BACKENDS" | sed -n 1'p' | tr ',' '\n' | while read AUTH_BACKEND; do
|
|
if [ "$FIRST" = true ]; then
|
|
setConfigurationValue "AUTHENTICATION_BACKENDS" "('zproject.backends.${AUTH_BACKEND//\'/\'}',)" "$SETTINGS_PY" "array"
|
|
FIRST=false
|
|
else
|
|
setConfigurationValue "AUTHENTICATION_BACKENDS += ('zproject.backends.${AUTH_BACKEND//\'/\'}',)" "" "$SETTINGS_PY" "literal"
|
|
fi
|
|
echo "Adding authentication backend \"$AUTH_BACKEND\"."
|
|
done
|
|
echo "Authentication backend activation succeeded."
|
|
}
|
|
zulipConfiguration() {
|
|
echo "Executing Zulip configuration ..."
|
|
if [ ! -z "$ZULIP_CUSTOM_SETTINGS" ]; then
|
|
echo -e "\n$ZULIP_CUSTOM_SETTINGS" >> "$SETTINGS_PY"
|
|
fi
|
|
local given_settings=($(env | sed -n -r "s/SETTING_([0-9A-Za-z_]*).*/\1/p"))
|
|
for setting_key in "${given_settings[@]}"; do
|
|
local key="SETTING_$setting_key"
|
|
local setting_var="${!key}"
|
|
local type="string"
|
|
if [ -z "$setting_var" ]; then
|
|
echo "Empty var for key \"$setting_key\"."
|
|
continue
|
|
fi
|
|
# Zulip settings.py / zproject specific overrides here
|
|
if [ "$setting_key" = "AUTH_LDAP_CONNECTION_OPTIONS" ] || \
|
|
[ "$setting_key" = "AUTH_LDAP_USER_SEARCH" ] || \
|
|
[ "$setting_key" = "AUTH_LDAP_USER_ATTR_MAP" ] || \
|
|
([ "$setting_key" = "LDAP_APPEND_DOMAIN" ] && [ "$setting_var" = "None" ]) || \
|
|
[ "$setting_key" = "SECURE_PROXY_SSL_HEADER" ] || \
|
|
[[ "$setting_key" = "CSRF_"* ]] || \
|
|
[ "$setting_key" = "ALLOWED_HOSTS" ]; then
|
|
type="array"
|
|
fi
|
|
if ([ "$SPECIAL_SETTING_DETECTION_MODE" = "True" ] || [ "$SPECIAL_SETTING_DETECTION_MODE" = "true" ]) || \
|
|
[ "$type" = "string" ]; then
|
|
type=""
|
|
fi
|
|
if [ "$setting_key" = "EMAIL_HOST_USER" ] || \
|
|
[ "$setting_key" = "EMAIL_HOST_PASSWORD" ] || \
|
|
[ "$setting_key" = "EXTERNAL_HOST" ]; then
|
|
type="string"
|
|
fi
|
|
setConfigurationValue "$setting_key" "$setting_var" "$SETTINGS_PY" "$type"
|
|
done
|
|
unset setting_key setting_var
|
|
su zulip -c "/home/zulip/deployments/current/manage.py checkconfig"
|
|
if [[ $? != 0 ]]; then
|
|
echo "Error in the Zulip configuration. Exiting."
|
|
exit 1
|
|
fi
|
|
echo "Zulip configuration succeeded."
|
|
}
|
|
autoBackupConfiguration() {
|
|
if ([ "$AUTO_BACKUP_ENABLED" != "True" ] && [ "$AUTO_BACKUP_ENABLED" != "true" ]); then
|
|
rm -f /etc/cron.d/autobackup
|
|
echo "Auto backup is disabled. Continuing."
|
|
return 0
|
|
fi
|
|
echo "MAILTO=""\n$AUTO_BACKUP_INTERVAL cd /;/entrypoint.sh app:backup" > /etc/cron.d/autobackup
|
|
echo "Auto backup enabled."
|
|
}
|
|
initialConfiguration() {
|
|
echo "=== Begin Initial Configuration Phase ==="
|
|
prepareDirectories
|
|
nginxConfiguration
|
|
configureCerts
|
|
if [ "$MANUAL_CONFIGURATION" = "False" ] || [ "$MANUAL_CONFIGURATION" = "false" ]; then
|
|
databaseConfiguration
|
|
secretsConfiguration
|
|
authenticationBackends
|
|
zulipConfiguration
|
|
fi
|
|
autoBackupConfiguration
|
|
echo "=== End Initial Configuration Phase ==="
|
|
}
|
|
# === bootstrappingEnvironment ===
|
|
waitingForDatabase() {
|
|
export PGPASSWORD="$SECRETS_postgres_password"
|
|
local TIMEOUT=60
|
|
echo "Waiting for database server to allow connections ..."
|
|
while ! /usr/bin/pg_isready -h "$DB_HOST" -p "$DB_HOST_PORT" -U "$DB_USER" -t 1 >/dev/null 2>&1
|
|
do
|
|
TIMEOUT=$(expr $TIMEOUT - 1)
|
|
if [[ $TIMEOUT -eq 0 ]]; then
|
|
echo "Could not connect to database server. Exiting."
|
|
unset PGPASSWORD
|
|
exit 1
|
|
fi
|
|
echo -n "."
|
|
sleep 1
|
|
done
|
|
unset PGPASSWORD
|
|
}
|
|
zulipFirstStartInit() {
|
|
echo "Executing Zulip first start init ..."
|
|
if [ -e "$DATA_DIR/.initiated" ] && ([ "$FORCE_FIRST_START_INIT" != "True" ] && [ "$FORCE_FIRST_START_INIT" != "true" ]); then
|
|
echo "First Start Init not needed. Continuing."
|
|
return 0
|
|
fi
|
|
local RETURN_CODE=0
|
|
set +e
|
|
su zulip -c /home/zulip/deployments/current/scripts/setup/initialize-database
|
|
RETURN_CODE=$?
|
|
if [[ $RETURN_CODE != 0 ]]; then
|
|
echo "Zulip first start database initi failed in \"initialize-database\" exit code $RETURN_CODE. Exiting."
|
|
exit $RETURN_CODE
|
|
fi
|
|
set -e
|
|
touch "$DATA_DIR/.initiated"
|
|
echo "Zulip first start init sucessful."
|
|
}
|
|
zulipMigration() {
|
|
echo "Migrating Zulip to new version ..."
|
|
set +e
|
|
su zulip -c "/home/zulip/deployments/current/manage.py migrate --noinput"
|
|
local RETURN_CODE=$?
|
|
if [[ $RETURN_CODE != 0 ]]; then
|
|
echo "Zulip migration failed with exit code $RETURN_CODE. Exiting."
|
|
exit $RETURN_CODE
|
|
fi
|
|
set -e
|
|
rm -rf "$DATA_DIR/.zulip-*"
|
|
touch "$DATA_DIR/.zulip-$ZULIP_VERSION"
|
|
echo "Zulip migration succeeded."
|
|
}
|
|
runPostSetupScripts() {
|
|
echo "Post setup scripts execution ..."
|
|
if ([ "$ZULIP_RUN_POST_SETUP_SCRIPTS" != "True" ] && [ "$ZULIP_RUN_POST_SETUP_SCRIPTS" != "true" ]); then
|
|
echo "Not running post setup scripts. ZULIP_RUN_POST_SETUP_SCRIPTS isn't true."
|
|
return 0
|
|
fi
|
|
if [ ! -d "$DATA_DIR/post-setup.d/" ]; then
|
|
echo "No post-setup.d folder found. Continuing."
|
|
return 0
|
|
fi
|
|
if [ ! "$(ls "$DATA_DIR/post-setup.d/")" ]; then
|
|
echo "No post setup scripts found in \"$DATA_DIR/post-setup.d/\"."
|
|
return 0
|
|
fi
|
|
set +e
|
|
for file in $DATA_DIR/post-setup.d/*; do
|
|
if [ -x "$file" ]; then
|
|
echo "Executing \"$file\" ..."
|
|
bash -c "$file"
|
|
echo "Executed \"$file\". Return code $?."
|
|
else
|
|
echo "Permissions denied for \"$file\". Please check the permissions. Exiting."
|
|
exit 1
|
|
fi
|
|
done
|
|
set -e
|
|
echo "Post setup scripts execution succeeded."
|
|
}
|
|
function runCertbotAsNeeded() {
|
|
if [ ! "$GENERATE_CERTBOT_CERT_SCHEDULED" = "True" ]; then
|
|
echo "Certbot is not scheduled to run."
|
|
return
|
|
fi
|
|
|
|
echo "Waiting for nginx to come online before generating certbot certificate ..."
|
|
while ! curl -sk "$SETTING_EXTERNAL_HOST" >/dev/null 2>&1; do
|
|
sleep 1;
|
|
done
|
|
|
|
echo "Generating LetsEncrypt/certbot certificate ..."
|
|
|
|
# Remove the self-signed certs which were only needed to get Zulip going.
|
|
rm -f "$DATA_DIR"/certs/zulip.key "$DATA_DIR"/certs/zulip.combined-chain.crt
|
|
|
|
ZULIP_CERTBOT_DEPLOY_HOOK="/sbin/certbot-deploy-hook"
|
|
|
|
# Accept the terms of service automatically.
|
|
/home/zulip/deployments/current/scripts/setup/setup-certbot \
|
|
--agree-tos \
|
|
--hostname="$SETTING_EXTERNAL_HOST" \
|
|
--email="$SETTING_ZULIP_ADMINISTRATOR" \
|
|
--deploy-hook "$ZULIP_CERTBOT_DEPLOY_HOOK"
|
|
|
|
echo "LetsEncrypt cert generated."
|
|
}
|
|
bootstrappingEnvironment() {
|
|
echo "=== Begin Bootstrap Phase ==="
|
|
waitingForDatabase
|
|
zulipFirstStartInit
|
|
zulipMigration
|
|
runPostSetupScripts
|
|
# Hack: We run this in the background, since we need nginx to be
|
|
# started before we can create the certificate. See #142 for
|
|
# details on how we can clean this up.
|
|
runCertbotAsNeeded &
|
|
echo "=== End Bootstrap Phase ==="
|
|
}
|
|
# END appRun functions
|
|
# BEGIN app functions
|
|
appRun() {
|
|
initialConfiguration
|
|
bootstrappingEnvironment
|
|
echo "=== Begin Run Phase ==="
|
|
echo "Starting Zulip using supervisor with \"/etc/supervisor/supervisord.conf\" config ..."
|
|
echo ""
|
|
exec supervisord -n -c "/etc/supervisor/supervisord.conf"
|
|
}
|
|
appManagePy() {
|
|
COMMAND="$1"
|
|
shift 1
|
|
if [ -z "$COMMAND" ]; then
|
|
echo "No command given for manage.py. Defaulting to \"shell\"."
|
|
COMMAND="shell"
|
|
fi
|
|
echo "Running manage.py ..."
|
|
set +e
|
|
exec su zulip -c "/home/zulip/deployments/current/manage.py $COMMAND $*"
|
|
}
|
|
appBackup() {
|
|
echo "Starting backup process ..."
|
|
if [ -d "/tmp/backup-$(date "%D-%H-%M-%S")" ]; then
|
|
echo "Temporary backup folder for \"$(date "%D-%H-%M-%S")\" already exists. Aborting."
|
|
echo "Backup process failed. Exiting."
|
|
exit 1
|
|
fi
|
|
local BACKUP_FOLDER
|
|
BACKUP_FOLDER="/tmp/backup-$(date "%D-%H-%M-%S")"
|
|
mkdir -p "$BACKUP_FOLDER"
|
|
waitingForDatabase
|
|
pg_dump -h "$DB_HOST" -p "$DB_HOST_PORT" -U "$DB_USER" "$DB_NAME" > "$BACKUP_FOLDER/database-postgres.sql"
|
|
tar -zcvf "$DATA_DIR/backups/backup-$(date "%D-%H-%M-%S").tar.gz" "$BACKUP_FOLDER/"
|
|
rm -r "${BACKUP_FOLDER:?}/"
|
|
echo "Backup process succeeded."
|
|
exit 0
|
|
}
|
|
appRestore() {
|
|
echo "Starting restore process ..."
|
|
if [ "$(ls -A "$DATA_DIR/backups/")" ]; then
|
|
echo "No backups to restore found in \"$DATA_DIR/backups/\"."
|
|
echo "Restore process failed. Exiting."
|
|
exit 1
|
|
fi
|
|
while true; do
|
|
ls "$DATA_DIR/backups/" | awk '{print "|-> " $1}'
|
|
echo "Please enter backup filename (full filename with extension): "
|
|
read BACKUP_FILE
|
|
if [ -z "$BACKUP_FILE" ]; then
|
|
echo "Empty filename given. Please try again."
|
|
echo ""
|
|
continue
|
|
fi
|
|
if [ ! -e "$DATA_DIR/backups/$BACKUP_FILE" ]; then
|
|
echo "File \"$BACKUP_FILE\" not found. Please try again."
|
|
echo ""
|
|
fi
|
|
break
|
|
done
|
|
echo "File \"$BACKUP_FILE\" found."
|
|
echo ""
|
|
echo "==============================================================="
|
|
echo "!! WARNING !! Your current data will be deleted!"
|
|
echo "!! WARNING !! YOU HAVE BEEN WARNED! You can abort with \"CTRL+C\"."
|
|
echo "!! WARNING !! Waiting 10 seconds before continuing ..."
|
|
echo "==============================================================="
|
|
echo ""
|
|
local TIMEOUT=11
|
|
while true; do
|
|
TIMEOUT=$(expr $TIMEOUT - 1)
|
|
if [[ $TIMEOUT -eq 0 ]]; then
|
|
break
|
|
fi
|
|
echo "$TIMEOUT"
|
|
sleep 1
|
|
done
|
|
echo "!! WARNING !! Starting restore process ... !! WARNING !!"
|
|
waitingForDatabase
|
|
tar -zxvf "$DATA_DIR/backups/$BACKUP_FILE" -C /tmp
|
|
psql -h "$DB_HOST" -p "$DB_HOST_PORT" -U "$DB_USER" "$DB_NAME" < "/tmp/$(basename "$BACKUP_FILE" | cut -d. -f1)/database-postgres.sql"
|
|
rm -r "/tmp/$(basename | cut -d. -f1)/"
|
|
echo "Restore process succeeded. Exiting."
|
|
exit 0
|
|
}
|
|
appCerts() {
|
|
configureCerts
|
|
}
|
|
appHelp() {
|
|
echo "Available commands:"
|
|
echo "> app:help - Show this help menu and exit"
|
|
echo "> app:version - Container Zulip server version"
|
|
echo "> app:managepy - Run Zulip's manage.py script (defaults to \"shell\")"
|
|
echo "> app:backup - Create backups of Zulip instances"
|
|
echo "> app:restore - Restore backups of Zulip instances"
|
|
echo "> app:certs - Create self-signed certificates"
|
|
echo "> app:run - Run the Zulip server"
|
|
echo "> [COMMAND] - Run given command with arguments in shell"
|
|
}
|
|
appVersion() {
|
|
echo "This container contains:"
|
|
echo "> Zulip server $ZULIP_VERSION"
|
|
echo "> Checksum: $ZULIP_CHECKSUM"
|
|
exit 0
|
|
}
|
|
# END app functions
|
|
|
|
case "$1" in
|
|
app:run)
|
|
appRun
|
|
;;
|
|
app:managepy)
|
|
shift 1
|
|
appManagePy "$@"
|
|
;;
|
|
app:backup)
|
|
appBackup
|
|
;;
|
|
app:restore)
|
|
appRestore
|
|
;;
|
|
app:certs)
|
|
appCerts
|
|
;;
|
|
app:help)
|
|
appHelp
|
|
;;
|
|
app:version)
|
|
appVersion
|
|
;;
|
|
*)
|
|
if [[ -x $1 ]]; then
|
|
$1
|
|
else
|
|
COMMAND="$1"
|
|
if [[ -n $(which $COMMAND) ]] ; then
|
|
shift 1
|
|
exec "$(which $COMMAND)" "$@"
|
|
else
|
|
appHelp
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|