/
githubmirror
/
zulip
Обзор
Документация
Войти
/
githubmirror
/
zulip
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
8.5
scripts/lib/install
596 строк
19 KB
Alex Vandiver
install: Check for a supported version of the OS in shell.
07 май 2024, 23:26
07 май 2024, 23:26
82e3b33
Код
Авторство
О чём код?
#!/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. --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. --cacert=/path/to/ca.pem Set the CA which used to establish TLS to all public internet sites during the install process; used when this command is run once in a highly-controlled environment to produce an image which is used elsewhere. Uncommon. --postgresql-database-name=zulip Sets the PostgreSQL database name. --postgresql-database-user=zulip Sets the PostgreSQL database user. --postgresql-version=16 Sets the version of PostgreSQL that will be installed. --postgresql-missing-dictionaries Set postgresql.missing_dictionaries, which alters the initial database. Use with cloud managed databases like RDS. Conflicts with --no-overwrite-settings. --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`. 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:,postgresql-missing-dictionaries,no-init-db,puppet-classes:,no-overwrite-settings,no-dist-upgrade -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 ;; --cacert) export CUSTOM_CA_CERTIFICATES="$2" shift 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 ;; --postgresql-missing-dictionaries) POSTGRESQL_MISSING_DICTIONARIES=1 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 ;; --) 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:-16}" 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 [ -n "$POSTGRESQL_MISSING_DICTIONARIES" ] && [ -n "$NO_OVERWRITE_SETTINGS" ]; then set +x echo "error: --postgresql-missing-dictionaries and --no-overwrite-settings 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 check_config in zerver/lib/management.py. echo 'error: The example hostname and email must be replaced with real values.' >&2 echo >&2 usage >&2 exit 1 fi case "$POSTGRESQL_VERSION" in [0-9] | [0-9].* | 1[01] | 1[01].*) echo "error: PostgreSQL 12 or newer is required." >&2 exit 1 ;; esac # 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 11 - Debian 12 - Ubuntu 20.04 LTS - Ubuntu 22.04 LTS - Ubuntu 24.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 # 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 \ 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 if [ -n "$POSTGRESQL_MISSING_DICTIONARIES" ]; then crudini --set /etc/zulip/zulip.conf postgresql missing_dictionaries true fi "$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; but # we don't know if this is a database host until we have the catalog summary. if ! has_class "zulip::postgresql_common" || [ "$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 # Create and activate a virtualenv "$ZULIP_PATH"/scripts/lib/create-production-venv "$ZULIP_PATH" "$ZULIP_PATH"/scripts/lib/install-node if [ -z "$NO_OVERWRITE_SETTINGS" ] || ! [ -e "/etc/zulip/settings.py" ]; then cp -a "$ZULIP_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 fi ln -nsf /etc/zulip/settings.py "$ZULIP_PATH"/zproject/prod_settings.py "$ZULIP_PATH"/scripts/setup/generate_secrets.py --production fi "$ZULIP_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 "$ZULIP_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 # Frontend deploys use /home/zulip/deployments; without this, the # install directory is also only readable by root. 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 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 exit 0 else /home/zulip/deployments/current/scripts/setup/create-database su zulip -c '/home/zulip/deployments/current/scripts/setup/initialize-database --quiet' su zulip -c '/home/zulip/deployments/current/manage.py generate_realm_creation_link' fi