snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
790
scripts/lib/install
Executable file
790
scripts/lib/install
Executable file
@@ -0,0 +1,790 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
usage() {
|
||||
# A subset of this documentation also appears in docs/production/install.md
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
install --hostname=zulip.example.com --email=zulip-admin@example.com [options...]
|
||||
install --help
|
||||
|
||||
Options:
|
||||
--hostname=zulip.example.com
|
||||
The user-accessible domain name for this Zulip server, i.e.,
|
||||
what users will type in their web browser. Required, unless
|
||||
--no-init-db or --puppet-classes is set, and --certbot is not.
|
||||
Use Punycode for non-ASCII domains.
|
||||
|
||||
--email=zulip-admin@example.com
|
||||
The email address of the person or team who should get support
|
||||
and error emails from this Zulip server. Required, unless
|
||||
--no-init-db or --puppet-classes is set and --certbot is not.
|
||||
|
||||
--certbot
|
||||
Obtains a free SSL certificate for the server using Certbot,
|
||||
https://certbot.eff.org/ Recommended. Conflicts with --self-signed-cert.
|
||||
--self-signed-cert
|
||||
Generate a self-signed SSL certificate for the server. This isn’t suitable for
|
||||
production use, but may be convenient for testing. Conflicts with --certbot.
|
||||
|
||||
--postgresql-database-name=zulip
|
||||
Sets the PostgreSQL database name.
|
||||
--postgresql-database-user=zulip
|
||||
Sets the PostgreSQL database user.
|
||||
--postgresql-version=18
|
||||
Sets the version of PostgreSQL that will be installed.
|
||||
|
||||
--no-init-db
|
||||
Does not do any database initialization; use when you already have a Zulip
|
||||
database.
|
||||
--puppet-classes
|
||||
Comma-separated list of Puppet classes to install; defaults to
|
||||
'zulip:::profile::standalone'. Implies --no-init-db.
|
||||
|
||||
--no-overwrite-settings
|
||||
Preserve existing `/etc/zulip` configuration files.
|
||||
--no-dist-upgrade
|
||||
Skip the initial `apt-get dist-upgrade`.
|
||||
|
||||
--push-notifications
|
||||
With this option, the Zulip installer registers your server for the Mobile
|
||||
Push Notification Service, and sets up the initial default configuration.
|
||||
You will be immediately prompted to agree to the Terms of Service, and your
|
||||
server will be registered at the end of the installation process.
|
||||
--no-push-notifications
|
||||
Disable push notifications registration (the default if neither
|
||||
flag is provided).
|
||||
|
||||
--no-submit-usage-statistics
|
||||
If you enable push notifications, by default your server
|
||||
will submit basic metadata (required for billing and for
|
||||
determining free plan eligibility), as well as aggregate usage
|
||||
statistics. You can disable submitting usage statistics by passing
|
||||
this flag.
|
||||
If push notifications are not enabled, data won't be submitted, so
|
||||
this flag is redundant.
|
||||
|
||||
--agree-to-terms-of-service
|
||||
If you enable push notifications, you can pass this flag to indicate
|
||||
that you have read and agree to the Zulip Terms of Service:
|
||||
<https://zulip.com/policies/terms>.
|
||||
This skips the Terms of Service prompt, allowing for running the installer
|
||||
with --push-notifications in scripts without requiring user input.
|
||||
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
system_requirements_failure() {
|
||||
set +x
|
||||
echo >&2
|
||||
cat >&2
|
||||
cat <<EOF >&2
|
||||
|
||||
For more information, see:
|
||||
https://zulip.readthedocs.io/en/latest/production/requirements.html
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Shell option parsing. Over time, we'll want to move some of the
|
||||
# environment variables below into this self-documenting system.
|
||||
args="$(getopt -o '' --long help,hostname:,email:,certbot,self-signed-cert,cacert:,postgresql-database-name:,postgresql-database-user:,postgresql-version:,no-init-db,puppet-classes:,no-overwrite-settings,no-dist-upgrade,push-notifications,no-push-notifications,no-submit-usage-statistics,agree-to-terms-of-service -n "$0" -- "$@")"
|
||||
|
||||
eval "set -- $args"
|
||||
while true; do
|
||||
case "$1" in
|
||||
--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
|
||||
--hostname)
|
||||
EXTERNAL_HOST="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--email)
|
||||
ZULIP_ADMINISTRATOR="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
|
||||
--certbot)
|
||||
USE_CERTBOT=1
|
||||
shift
|
||||
;;
|
||||
--self-signed-cert)
|
||||
SELF_SIGNED_CERT=1
|
||||
shift
|
||||
;;
|
||||
--postgresql-database-name)
|
||||
POSTGRESQL_DATABASE_NAME="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--postgresql-database-user)
|
||||
POSTGRESQL_DATABASE_USER="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--postgresql-version)
|
||||
POSTGRESQL_VERSION="$2"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
--no-init-db)
|
||||
NO_INIT_DB=1
|
||||
shift
|
||||
;;
|
||||
--puppet-classes)
|
||||
PUPPET_CLASSES="$2"
|
||||
NO_INIT_DB=1
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
|
||||
--no-overwrite-settings)
|
||||
NO_OVERWRITE_SETTINGS=1
|
||||
shift
|
||||
;;
|
||||
--no-dist-upgrade)
|
||||
NO_DIST_UPGRADE=1
|
||||
shift
|
||||
;;
|
||||
--push-notifications)
|
||||
if [ -n "$NO_PUSH_NOTIFICATIONS" ]; then
|
||||
echo "error: --push-notifications and --no-push-notifications are incompatible." >&2
|
||||
exit 1
|
||||
fi
|
||||
PUSH_NOTIFICATIONS=1
|
||||
shift
|
||||
;;
|
||||
--no-push-notifications)
|
||||
if [ -n "$PUSH_NOTIFICATIONS" ]; then
|
||||
echo "error: --push-notifications and --no-push-notifications are incompatible." >&2
|
||||
exit 1
|
||||
fi
|
||||
NO_PUSH_NOTIFICATIONS=1
|
||||
shift
|
||||
;;
|
||||
--no-submit-usage-statistics)
|
||||
NO_SUBMIT_USAGE_STATISTICS=1
|
||||
shift
|
||||
;;
|
||||
--agree-to-terms-of-service)
|
||||
AGREE_TO_TERMS_OF_SERVICE_FLAG=1
|
||||
shift
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## Options from environment variables.
|
||||
#
|
||||
# Specify options for apt.
|
||||
read -r -a APT_OPTIONS <<<"${APT_OPTIONS:-}"
|
||||
# Install additional packages.
|
||||
read -r -a ADDITIONAL_PACKAGES <<<"${ADDITIONAL_PACKAGES:-}"
|
||||
# Comma-separated list of Puppet manifests to install. The default is
|
||||
# zulip::profile::standalone for an all-in-one system or
|
||||
# zulip::profile::docker for Docker. Use
|
||||
# e.g. zulip::profile::app_frontend for a Zulip frontend server.
|
||||
PUPPET_CLASSES="${PUPPET_CLASSES:-zulip::profile::standalone}"
|
||||
POSTGRESQL_VERSION="${POSTGRESQL_VERSION:-18}"
|
||||
|
||||
if [ -n "$SELF_SIGNED_CERT" ] && [ -n "$USE_CERTBOT" ]; then
|
||||
set +x
|
||||
echo "error: --self-signed-cert and --certbot are incompatible" >&2
|
||||
echo >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$EXTERNAL_HOST" ] || [ -z "$ZULIP_ADMINISTRATOR" ]; then
|
||||
if [ -n "$USE_CERTBOT" ] || [ -z "$NO_INIT_DB" ]; then
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$EXTERNAL_HOST" = zulip.example.com ] \
|
||||
|| [ "$ZULIP_ADMINISTRATOR" = zulip-admin@example.com ]; then
|
||||
# These example values are specifically checked for and would fail
|
||||
# later; see zerver/checks.py
|
||||
echo 'error: The example hostname and email must be replaced with real values.' >&2
|
||||
echo >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$EXTERNAL_HOST" in
|
||||
*[![:ascii:]]*)
|
||||
# Non-ASCII hostnames are specifically checked for and would
|
||||
# fail later; see zerver/checks.py
|
||||
echo "error: The hostname ($EXTERNAL_HOST) contains non-ASCII characters." >&2
|
||||
echo 'Internationalized domain names must be specified in punycode ("xn--") form:' >&2
|
||||
# python3 is not installed until later, so it may not be
|
||||
# available to compute the suggested encoding.
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
suggestion="$(python3 -c '
|
||||
import sys
|
||||
|
||||
hostname, sep, port = sys.argv[1].partition(":")
|
||||
print(
|
||||
".".join(
|
||||
"xn--" + label.encode("punycode").decode() if not label.isascii() else label
|
||||
for label in hostname.split(".")
|
||||
)
|
||||
+ sep
|
||||
+ port
|
||||
)' "$EXTERNAL_HOST")"
|
||||
echo " --hostname=$suggestion" >&2
|
||||
fi
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$POSTGRESQL_VERSION" in
|
||||
[0-9] | [0-9].* | 1[0-3] | 1[0-3].*)
|
||||
echo "error: PostgreSQL 14 or newer is required." >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$PUSH_NOTIFICATIONS" ] && [ -z "$NO_PUSH_NOTIFICATIONS" ]; then
|
||||
# Unless specified, we default to --no-push-notifications
|
||||
NO_PUSH_NOTIFICATIONS=1
|
||||
fi
|
||||
|
||||
# We set these to Python-style True/False string values, for easy
|
||||
# insertion into the settings.py file.
|
||||
if [ -n "$PUSH_NOTIFICATIONS" ]; then
|
||||
SERVICE_MOBILE_PUSH="True"
|
||||
|
||||
# --push-notifications also enables SUBMIT_USAGE_STATISTICS, unless the user
|
||||
# explicitly opted out by passing --no-submit-usage-statistics.
|
||||
if [ -n "$NO_SUBMIT_USAGE_STATISTICS" ]; then
|
||||
SERVICE_SUBMIT_USAGE_STATISTICS="False"
|
||||
else
|
||||
SERVICE_SUBMIT_USAGE_STATISTICS="True"
|
||||
fi
|
||||
else
|
||||
SERVICE_MOBILE_PUSH="False"
|
||||
# SUBMIT_USAGE_STATISTICS without PUSH_NOTIFICATIONS is an unusual
|
||||
# configuration that we don't need to offer in the installer.
|
||||
SERVICE_SUBMIT_USAGE_STATISTICS="False"
|
||||
fi
|
||||
|
||||
# ToS acceptance needs to be ensured if --push-notifications is passed.
|
||||
if [ -n "$PUSH_NOTIFICATIONS" ]; then
|
||||
# If the user provided the --agree-to-terms-of-service flag, we can just proceed.
|
||||
if [ -n "$AGREE_TO_TERMS_OF_SERVICE_FLAG" ]; then
|
||||
PUSH_NOTIFICATIONS_SERVICE_TOS_AGREED=1
|
||||
echo "Push notifications will be enabled, as you agreed to the Zulip Terms of Service"
|
||||
echo "by passing the --agree-to-terms-of-service flag."
|
||||
sleep 2
|
||||
else
|
||||
# If user asked for push notifications, prompt for ToS acceptance.
|
||||
echo
|
||||
echo "You chose to register your server for the Mobile Push Notifications Service."
|
||||
echo "Doing so will share basic metadata with the service's maintainers, including:"
|
||||
echo
|
||||
echo "* The server's configured hostname: $EXTERNAL_HOST"
|
||||
echo "* The server's configured contact email address: $ZULIP_ADMINISTRATOR"
|
||||
echo "* Basic metadata about each organization hosted by the server; see:"
|
||||
echo " <https://zulip.com/doc-permalinks/basic-metadata>"
|
||||
if [ -z "$NO_SUBMIT_USAGE_STATISTICS" ]; then
|
||||
echo "* The server's usage statistics; see:"
|
||||
echo " <https://zulip.com/doc-permalinks/usage-statistics>"
|
||||
fi
|
||||
echo
|
||||
echo "For details on why a centralized push notification service is necessary, see:"
|
||||
echo " <https://zulip.com/doc-permalinks/why-service>"
|
||||
echo
|
||||
echo "Use of this service is governed by the Zulip Terms of Service:"
|
||||
echo " <https://zulip.com/policies/terms>"
|
||||
echo
|
||||
read -r -p "Do you want to agree to the Zulip Terms of Service and proceed? [Y/n] " tos_prompt
|
||||
echo
|
||||
|
||||
# Normalize the user’s response to lowercase.
|
||||
case "${tos_prompt,,}" in
|
||||
"" | y | yes)
|
||||
echo "Great! Push notifications will be enabled; continuing with installation..."
|
||||
PUSH_NOTIFICATIONS_SERVICE_TOS_AGREED=1
|
||||
sleep 2
|
||||
;;
|
||||
*)
|
||||
echo "In order to enable push notifications, you must agree to the Terms of Service."
|
||||
echo "If you do not want to enable push notifications, run the command without the --push-notifications flag."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# Do set -x after option parsing is complete
|
||||
set -x
|
||||
|
||||
ZULIP_PATH="$(readlink -f "$(dirname "$0")"/../..)"
|
||||
|
||||
# Force a known locale. Some packages on PyPI fail to install in some locales.
|
||||
export LC_ALL="C.UTF-8"
|
||||
export LANG="C.UTF-8"
|
||||
export LANGUAGE="C.UTF-8"
|
||||
|
||||
# Force a known path; this fixes problems on Debian where `su` from
|
||||
# non-root may not adjust `$PATH` to root's.
|
||||
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
||||
|
||||
# Check for a supported OS release.
|
||||
if [ -f /etc/os-release ]; then
|
||||
os_info="$(
|
||||
. /etc/os-release
|
||||
printf '%s\n' "$ID" "$ID_LIKE" "$VERSION_ID" "$VERSION_CODENAME"
|
||||
)"
|
||||
{
|
||||
read -r os_id
|
||||
read -r os_id_like
|
||||
read -r os_version_id
|
||||
read -r os_version_codename || true
|
||||
} <<<"$os_info"
|
||||
case " $os_id $os_id_like " in
|
||||
*' debian '*)
|
||||
package_system="apt"
|
||||
;;
|
||||
*' rhel '*)
|
||||
package_system="yum"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if ! "$ZULIP_PATH/scripts/lib/supported-os"; then
|
||||
system_requirements_failure <<EOF
|
||||
Unsupported OS release: $os_id $os_version_id
|
||||
|
||||
Zulip in production is supported only on:
|
||||
- Debian 12
|
||||
- Debian 13
|
||||
- Ubuntu 22.04 LTS
|
||||
- Ubuntu 24.04 LTS
|
||||
- Ubuntu 26.04 LTS
|
||||
EOF
|
||||
fi
|
||||
|
||||
machine="$(uname -m)"
|
||||
if [ "$machine" != x86_64 ] && [ "$machine" != aarch64 ]; then
|
||||
system_requirements_failure <<EOF
|
||||
Unsupported CPU architecture: $machine (expected x86_64 or aarch64).
|
||||
EOF
|
||||
fi
|
||||
|
||||
dpkg_architecture="$(dpkg --print-architecture)"
|
||||
if [ "$dpkg_architecture" != amd64 ] && [ "$dpkg_architecture" != arm64 ]; then
|
||||
system_requirements_failure <<EOF
|
||||
Unsupported OS architecture: $dpkg_architecture (expected amd64 or arm64).
|
||||
EOF
|
||||
fi
|
||||
|
||||
has_universe() {
|
||||
apt-cache policy \
|
||||
| grep -q "^ release v=$os_version_id,o=Ubuntu,a=$os_version_codename,n=$os_version_codename,l=Ubuntu,c=universe"
|
||||
}
|
||||
|
||||
if [ "$os_id" = ubuntu ] && ! has_universe && ! { apt-get update && has_universe; }; then
|
||||
system_requirements_failure <<EOF
|
||||
You must enable the Ubuntu Universe repository before installing
|
||||
Zulip. You can do this with:
|
||||
|
||||
sudo add-apt-repository universe
|
||||
sudo apt update
|
||||
EOF
|
||||
fi
|
||||
|
||||
case ",$PUPPET_CLASSES," in
|
||||
*,zulip::profile::standalone,* | *,zulip::profile::postgresql,*)
|
||||
if [ "$package_system" = apt ]; then
|
||||
# We're going to install PostgreSQL from the PostgreSQL apt
|
||||
# repository; this may conflict with the existing PostgreSQL.
|
||||
OTHER_PG="$(dpkg --get-selections \
|
||||
| grep -E '^postgresql-[0-9]+\s+install$' \
|
||||
| grep -v "^postgresql-$POSTGRESQL_VERSION\b" \
|
||||
| cut -f 1)" || true
|
||||
if [ -n "$OTHER_PG" ]; then
|
||||
INDENTED="${OTHER_PG//$'\n'/$'\n' }"
|
||||
SPACED="${OTHER_PG//$'\n'/ }"
|
||||
cat <<EOF
|
||||
|
||||
The following PostgreSQL servers were found to already be installed:
|
||||
|
||||
$INDENTED
|
||||
|
||||
Zulip needs to install PostgreSQL $POSTGRESQL_VERSION, but does not wish
|
||||
to uninstall existing databases in order to do so. Remove all other
|
||||
PostgreSQL servers manually before running the installer:
|
||||
|
||||
sudo apt-get remove $SPACED
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for at least ~1.86GB of RAM before starting installation;
|
||||
# otherwise users will find out about insufficient RAM via weird
|
||||
# errors like a segfault running `pip install`.
|
||||
# Additionally, some AWS images that are advertised to be 2 GB
|
||||
# are actually 1880000B in size.
|
||||
mem_kb=$(head -n1 /proc/meminfo | awk '{print $2}')
|
||||
if [ "$mem_kb" -lt 1860000 ]; then
|
||||
set +x
|
||||
echo -e '\033[0;31m' >&2
|
||||
echo "Insufficient RAM. Zulip requires at least 2GB of RAM." >&2
|
||||
echo >&2
|
||||
echo -e '\033[0m' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Anything under 5GB, we recommended allocating 2GB of swap. Error
|
||||
# out if there's no swap.
|
||||
swap_kb=$(grep SwapTotal /proc/meminfo | awk '{print $2}')
|
||||
if [ "$mem_kb" -lt 5000000 ] && [ "$swap_kb" -eq 0 ]; then
|
||||
set +x
|
||||
echo -e '\033[0;31m' >&2
|
||||
echo "No swap allocated; when running with < 5GB of RAM, we recommend at least 2GB of swap." >&2
|
||||
echo "https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-22-04" >&2
|
||||
echo >&2
|
||||
echo -e '\033[0m' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Do package update, e.g. do `apt-get update` on Debian
|
||||
if [ "$package_system" = apt ]; then
|
||||
# setup-apt-repo does an `apt-get update`
|
||||
"$ZULIP_PATH"/scripts/lib/setup-apt-repo
|
||||
elif [ "$package_system" = yum ]; then
|
||||
"$ZULIP_PATH"/scripts/lib/setup-yum-repo
|
||||
fi
|
||||
|
||||
# Check early for missing SSL certificates
|
||||
if [ "$PUPPET_CLASSES" = "zulip::profile::standalone" ] && [ -z "$USE_CERTBOT""$SELF_SIGNED_CERT" ] && { ! [ -e "/etc/ssl/private/zulip.key" ] || ! [ -e "/etc/ssl/certs/zulip.combined-chain.crt" ]; }; then
|
||||
set +x
|
||||
cat <<EOF
|
||||
|
||||
No SSL certificate found. One or both required files is missing:
|
||||
/etc/ssl/private/zulip.key
|
||||
/etc/ssl/certs/zulip.combined-chain.crt
|
||||
|
||||
Suggested solutions:
|
||||
* For most sites, the --certbot option is recommended.
|
||||
* If you have your own key and cert, see docs linked below
|
||||
for how to install them.
|
||||
* For non-production testing, try the --self-signed-cert option.
|
||||
|
||||
For help and more details, see our SSL documentation:
|
||||
https://zulip.readthedocs.io/en/latest/production/ssl-certificates.html
|
||||
|
||||
Once fixed, just rerun scripts/setup/install; it'll pick up from here!
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# don't run dist-upgrade in one click apps to make the
|
||||
# installation process more seamless.
|
||||
if [ -z "$NO_DIST_UPGRADE" ]; then
|
||||
if [ "$package_system" = apt ]; then
|
||||
apt-get -y dist-upgrade "${APT_OPTIONS[@]}"
|
||||
elif [ "$package_system" = yum ]; then
|
||||
# On CentOS, there is no need to do `yum -y upgrade` because `yum -y
|
||||
# update` already does the same thing.
|
||||
:
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$package_system" = apt ]; then
|
||||
# Note that any additions to these lists must also be added to
|
||||
# `zulip::profile::base` such that the new dependency is seen by
|
||||
# upgrades, as well as new installs.
|
||||
if ! apt-get install -y --no-install-recommends \
|
||||
python3 python3-yaml puppet git curl jq crudini \
|
||||
"${ADDITIONAL_PACKAGES[@]}"; then
|
||||
set +x
|
||||
echo -e '\033[0;31m' >&2
|
||||
echo "Installing packages failed; is network working and (on Ubuntu) the universe repository enabled?" >&2
|
||||
echo >&2
|
||||
echo -e '\033[0m' >&2
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$package_system" = yum ]; then
|
||||
if ! yum install -y \
|
||||
python3 python3-pyyaml puppet git curl jq crudini \
|
||||
"${ADDITIONAL_PACKAGES[@]}"; then
|
||||
set +x
|
||||
echo -e '\033[0;31m' >&2
|
||||
echo "Installing packages failed; is network working?" >&2
|
||||
echo >&2
|
||||
echo -e '\033[0m' >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# We generate a self-signed cert even with certbot, so we can use the
|
||||
# webroot authenticator, which requires nginx be set up with a
|
||||
# certificate.
|
||||
if [ -n "$SELF_SIGNED_CERT" ] || [ -n "$USE_CERTBOT" ]; then
|
||||
"$ZULIP_PATH"/scripts/setup/generate-self-signed-cert \
|
||||
--exists-ok "${EXTERNAL_HOST:-$(hostname)}"
|
||||
fi
|
||||
|
||||
# Generate /etc/zulip/zulip.conf .
|
||||
mkdir -p /etc/zulip
|
||||
has_class() {
|
||||
grep -qx "$1" /var/lib/puppet/classes.txt
|
||||
}
|
||||
|
||||
# puppet apply --noop fails unless the user that it _would_ chown
|
||||
# files to exists; https://tickets.puppetlabs.com/browse/PUP-3907
|
||||
#
|
||||
# The home directory here should match what's declared in base.pp.
|
||||
id -u zulip &>/dev/null || useradd -m zulip --home-dir /home/zulip
|
||||
if [ -n "$NO_OVERWRITE_SETTINGS" ] && [ -e "/etc/zulip/zulip.conf" ]; then
|
||||
"$ZULIP_PATH"/scripts/zulip-puppet-apply --noop \
|
||||
--write-catalog-summary \
|
||||
--classfile=/var/lib/puppet/classes.txt
|
||||
else
|
||||
# Write out more than we need, and remove sections that are not
|
||||
# applicable to the classes that are actually necessary.
|
||||
cat <<EOF >/etc/zulip/zulip.conf
|
||||
[machine]
|
||||
puppet_classes = $PUPPET_CLASSES
|
||||
deploy_type = production
|
||||
|
||||
[postgresql]
|
||||
version = $POSTGRESQL_VERSION
|
||||
EOF
|
||||
|
||||
"$ZULIP_PATH"/scripts/zulip-puppet-apply --noop \
|
||||
--write-catalog-summary \
|
||||
--classfile=/var/lib/puppet/classes.txt
|
||||
|
||||
# We only need the PostgreSQL version setting on database hosts,
|
||||
# or hosts which talk directly to the database (e.g. application
|
||||
# hosts); but we don't know if this is a database host until we
|
||||
# have the catalog summary.
|
||||
if (! has_class "zulip::postgresql_common" && ! has_class "zulip::postgresql_client") || [ "$package_system" != apt ]; then
|
||||
crudini --del /etc/zulip/zulip.conf postgresql
|
||||
fi
|
||||
|
||||
if [ -n "$POSTGRESQL_DATABASE_NAME" ]; then
|
||||
crudini --set /etc/zulip/zulip.conf postgresql database_name "$POSTGRESQL_DATABASE_NAME"
|
||||
fi
|
||||
|
||||
if [ -n "$POSTGRESQL_DATABASE_USER" ]; then
|
||||
crudini --set /etc/zulip/zulip.conf postgresql database_user "$POSTGRESQL_DATABASE_USER"
|
||||
fi
|
||||
fi
|
||||
|
||||
if has_class "zulip::app_frontend_base"; then
|
||||
# Frontend deploys use /home/zulip/deployments; without this, the
|
||||
# install directory is also only readable by root.
|
||||
mkdir -p /home/zulip/deployments
|
||||
deploy_path=$("$ZULIP_PATH"/scripts/lib/zulip_tools.py make_deploy_path)
|
||||
mv "$ZULIP_PATH" "$deploy_path"
|
||||
ln -nsf /home/zulip/deployments/next "$ZULIP_PATH"
|
||||
ln -nsf "$deploy_path" /home/zulip/deployments/next
|
||||
|
||||
# Create and activate a virtualenv
|
||||
"$deploy_path"/scripts/lib/create-production-venv "$deploy_path"
|
||||
|
||||
"$deploy_path"/scripts/lib/install-node
|
||||
|
||||
if [ -z "$NO_OVERWRITE_SETTINGS" ] || ! [ -e "/etc/zulip/settings.py" ]; then
|
||||
cp -a "$deploy_path"/zproject/prod_settings_template.py /etc/zulip/settings.py
|
||||
if [ -n "$EXTERNAL_HOST" ]; then
|
||||
sed -i "s/^EXTERNAL_HOST =.*/EXTERNAL_HOST = '$EXTERNAL_HOST'/" /etc/zulip/settings.py
|
||||
fi
|
||||
if [ -n "$ZULIP_ADMINISTRATOR" ]; then
|
||||
sed -i "s/^ZULIP_ADMINISTRATOR =.*/ZULIP_ADMINISTRATOR = '$ZULIP_ADMINISTRATOR'/" /etc/zulip/settings.py
|
||||
fi
|
||||
|
||||
# Set SERVICE settings based on what the user provided.
|
||||
if grep -q -E "^#?\s*ZULIP_SERVICE_PUSH_NOTIFICATIONS = " /etc/zulip/settings.py; then
|
||||
sed -i -E "s/^#?\s*ZULIP_SERVICE_PUSH_NOTIFICATIONS = .*/ZULIP_SERVICE_PUSH_NOTIFICATIONS = $SERVICE_MOBILE_PUSH/" /etc/zulip/settings.py
|
||||
else
|
||||
echo "ZULIP_SERVICE_PUSH_NOTIFICATIONS = $SERVICE_MOBILE_PUSH" >>/etc/zulip/settings.py
|
||||
fi
|
||||
|
||||
if grep -q -E "^#?\s*ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS = " /etc/zulip/settings.py; then
|
||||
sed -i -E "s/^#?\s*ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS = .*/ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS = $SERVICE_SUBMIT_USAGE_STATISTICS/" /etc/zulip/settings.py
|
||||
else
|
||||
echo "ZULIP_SERVICE_SUBMIT_USAGE_STATISTICS = $SERVICE_SUBMIT_USAGE_STATISTICS" >>/etc/zulip/settings.py
|
||||
fi
|
||||
fi
|
||||
ln -nsf /etc/zulip/settings.py "$deploy_path"/zproject/prod_settings.py
|
||||
"$deploy_path"/scripts/setup/generate_secrets.py --production
|
||||
else
|
||||
deploy_path="$ZULIP_PATH"
|
||||
fi
|
||||
|
||||
"$deploy_path"/scripts/zulip-puppet-apply -f
|
||||
|
||||
if [ "$package_system" = apt ]; then
|
||||
apt-get -y --with-new-pkgs upgrade
|
||||
elif [ "$package_system" = yum ]; then
|
||||
# No action is required because `yum update` already does upgrade.
|
||||
:
|
||||
fi
|
||||
|
||||
if [ -n "$USE_CERTBOT" ]; then
|
||||
"$deploy_path"/scripts/setup/setup-certbot \
|
||||
"$EXTERNAL_HOST" --email "$ZULIP_ADMINISTRATOR"
|
||||
fi
|
||||
|
||||
if has_class "zulip::nginx" && ! has_class "zulip::profile::docker"; then
|
||||
# Check nginx was configured properly now that we've installed it.
|
||||
# Most common failure mode is certs not having been installed.
|
||||
if ! nginx -t; then
|
||||
(
|
||||
set +x
|
||||
cat <<EOF
|
||||
|
||||
Verifying the Zulip nginx configuration failed!
|
||||
|
||||
This is almost always a problem with your SSL certificates. See:
|
||||
https://zulip.readthedocs.io/en/latest/production/ssl-certificates.html
|
||||
|
||||
Once fixed, just rerun scripts/setup/install; it'll pick up from here!
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
)
|
||||
fi
|
||||
fi
|
||||
|
||||
if has_class "zulip::profile::rabbitmq"; then
|
||||
if ! rabbitmqctl status >/dev/null; then
|
||||
set +x
|
||||
cat <<EOF
|
||||
|
||||
RabbitMQ seems to not have started properly after the installation process.
|
||||
Often this is caused by misconfigured /etc/hosts in virtualized environments.
|
||||
For more information, see:
|
||||
https://github.com/zulip/zulip/issues/53#issuecomment-143805121
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set up a basic .gitconfig for the 'zulip' user
|
||||
if [ -n "$ZULIP_ADMINISTRATOR" ]; then
|
||||
(
|
||||
cd / # Make sure the current working directory is readable by zulip
|
||||
su zulip -c "git config --global user.email $ZULIP_ADMINISTRATOR"
|
||||
su zulip -c "git config --global user.name 'Zulip Server ($EXTERNAL_HOST)'"
|
||||
)
|
||||
fi
|
||||
|
||||
if ! has_class "zulip::app_frontend_base"; then
|
||||
set +x
|
||||
cat <<EOF
|
||||
|
||||
Success!
|
||||
|
||||
Not configuring PostgreSQL, or /home/zulip/deployments, because this
|
||||
is not a front-end install.
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
ln -nsf "$deploy_path" /home/zulip/deployments/current
|
||||
ln -nsf /etc/zulip/settings.py "$deploy_path"/zproject/prod_settings.py
|
||||
mkdir -p "$deploy_path"/prod-static/serve
|
||||
cp -rT "$deploy_path"/prod-static/serve /home/zulip/prod-static
|
||||
chown -R zulip:zulip /home/zulip /var/log/zulip /etc/zulip/settings.py
|
||||
|
||||
if ! [ -e /home/zulip/deployments/current/zulip-git-version ]; then
|
||||
mkdir /srv/zulip.git
|
||||
chown zulip:zulip /srv/zulip.git
|
||||
su zulip -c 'git clone --bare --mirror /home/zulip/deployments/current /srv/zulip.git'
|
||||
su zulip -c 'cd /home/zulip/deployments/current && ./scripts/lib/update-git-upstream && ./tools/cache-zulip-git-version'
|
||||
fi
|
||||
|
||||
if ! [ -e "/home/zulip/prod-static/generated" ]; then
|
||||
# If we're installing from a Git checkout, we need to run
|
||||
# `tools/update-prod-static` in order to build the static
|
||||
# assets.
|
||||
su zulip -c '/home/zulip/deployments/current/tools/update-prod-static'
|
||||
fi
|
||||
|
||||
if [ -n "$NO_INIT_DB" ]; then
|
||||
set +x
|
||||
cat <<EOF
|
||||
|
||||
Success!
|
||||
|
||||
Stopping because --no-init-db was passed. To complete the
|
||||
installation, configure PostgreSQL by creating the database and
|
||||
database user, and then run:
|
||||
|
||||
su zulip -c '/home/zulip/deployments/current/scripts/setup/initialize-database'
|
||||
su zulip -c '/home/zulip/deployments/current/manage.py generate_realm_creation_link'
|
||||
EOF
|
||||
|
||||
if [ -n "$PUSH_NOTIFICATIONS" ]; then
|
||||
echo
|
||||
echo "Since you specified you want to enable the push notification service, you'll also need to "
|
||||
echo "manually register your server by running:"
|
||||
echo
|
||||
echo " su zulip -c '/home/zulip/deployments/current/manage.py register_server'"
|
||||
echo
|
||||
fi
|
||||
exit 0
|
||||
else
|
||||
/home/zulip/deployments/current/scripts/setup/create-database
|
||||
su zulip -c '/home/zulip/deployments/current/scripts/setup/initialize-database --quiet'
|
||||
|
||||
if [ -n "$PUSH_NOTIFICATIONS" ]; then
|
||||
if [ -z "$PUSH_NOTIFICATIONS_SERVICE_TOS_AGREED" ]; then
|
||||
# This should be impossible as the installation should have aborted early if the user
|
||||
# passed --push-notifications without accepting the ToS. But we include this as a precaution
|
||||
# to not allow future bugs to cause ToS acceptance to be skipped.
|
||||
SKIP_TOS_AGREEMENT_OPTION=""
|
||||
else
|
||||
SKIP_TOS_AGREEMENT_OPTION="--agree-to-terms-of-service"
|
||||
fi
|
||||
set +x
|
||||
echo "Services enabled, attempting to register server..."
|
||||
set -x
|
||||
|
||||
# Without PYTHONUNBUFFERED=1, stdout/stderr might end up displayed not in chronological order, resulting
|
||||
# in confusing output to the user.
|
||||
su zulip -c "PYTHONUNBUFFERED=1 /home/zulip/deployments/current/manage.py register_server ${SKIP_TOS_AGREEMENT_OPTION}" \
|
||||
|| {
|
||||
set +x
|
||||
echo
|
||||
echo "WARNING: Server registration for push notifications failed."
|
||||
echo "This does not affect the rest of your Zulip installation."
|
||||
echo
|
||||
echo "To enable push notifications after resolving the issue, run:"
|
||||
echo " su zulip -c '/home/zulip/deployments/current/manage.py register_server'"
|
||||
echo
|
||||
set -x
|
||||
}
|
||||
fi
|
||||
|
||||
su zulip -c '/home/zulip/deployments/current/manage.py generate_realm_creation_link'
|
||||
fi
|
||||
Reference in New Issue
Block a user