feat: Improve Linux installation experience (#4713)

* feat: improve linux install script

* feat: setup logging and reduce verboseness

- redirect output/error to logfile
- reduce verboseness in main script exection
- trap non-zero exit

* chore: remove debug logging

* feat: fix exit handler

* improve legibility

* Apply suggestions from code review

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>

* chore: improve formatting

Co-authored-by: Pranav Raj S <pranav@chatwoot.com>
This commit is contained in:
Vishnu Narayanan 2022-05-25 12:30:00 +05:30 committed by GitHub
parent baa3efaf0e
commit 22d22cf4c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,164 +1,285 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Description: Chatwoot installation script # Description: Chatwoot installation script
# OS: Ubuntu 20.04 LTS / Ubuntu 20.10 # OS: Ubuntu 20.04 LTS
# Script Version: 0.8 # Script Version: 1.0
# Run this script as root # Run this script as root
read -p 'Would you like to configure a domain and SSL for Chatwoot?(yes or no): ' configure_webserver set -eu -o pipefail
trap exit_handler EXIT
if [ $configure_webserver == "yes" ] function exit_handler() {
then if [ "$?" -ne 0 ]; then
read -p 'Enter your sub-domain to be used for Chatwoot (chatwoot.domain.com for example) : ' domain_name echo -en "\nSome error has occured. Check '/var/log/chatwoot-setup.log' for details.\n"
echo -e "\nThis script will try to generate SSL certificates via LetsEncrypt and serve chatwoot at exit 1
"https://$domain_name". Proceed further once you have pointed your DNS to the IP of the instance.\n" fi
read -p 'Enter the email LetsEncrypt can use to send reminders when your SSL certificate is up for renewal: ' le_email }
read -p 'Do you wish to proceed? (yes or no): ' exit_true
if [ $exit_true == "no" ] if [ "$(id -u)" -ne 0 ]; then
then echo 'This script should be run as root.' >&2
exit 1 exit 1
fi
fi fi
read -p 'Would you like to install postgres and redis?(Answer no if you plan to use external services): ' install_pg_redis
if [ $install_pg_redis == "no" ]
then
echo "***** Skipping pg and redis installation. ****"
fi
apt update && apt upgrade -y
apt install -y curl
curl -sL https://deb.nodesource.com/setup_12.x | bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt update
apt install -y \
git software-properties-common imagemagick libpq-dev \
libxml2-dev libxslt1-dev file g++ gcc autoconf build-essential \
libssl-dev libyaml-dev libreadline-dev gnupg2 \
postgresql-client redis-tools \
nodejs yarn patch ruby-dev zlib1g-dev liblzma-dev \
libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev sudo
if [ $install_pg_redis != "no" ]
then
apt install -y postgresql postgresql-contrib redis-server
fi
if [ $configure_webserver == "yes" ]
then
apt install -y nginx nginx-full certbot python3-certbot-nginx
fi
adduser --disabled-login --gecos "" chatwoot
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable
adduser chatwoot rvm
if [ $install_pg_redis != "no" ]
then
pg_pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 15 ; echo '')
sudo -i -u postgres psql << EOF
\set pass `echo $pg_pass`
CREATE USER chatwoot CREATEDB;
ALTER USER chatwoot PASSWORD :'pass';
ALTER ROLE chatwoot SUPERUSER;
UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';
DROP DATABASE template1;
CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE';
UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';
\c template1
VACUUM FREEZE;
EOF
systemctl enable redis-server.service
systemctl enable postgresql
fi
secret=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo '')
RAILS_ENV=production
sudo -i -u chatwoot << EOF
rvm --version
rvm autolibs disable
rvm install "ruby-3.0.2"
rvm use 3.0.2 --default
git clone https://github.com/chatwoot/chatwoot.git
cd chatwoot
if [[ -z "$1" ]]; then if [[ -z "$1" ]]; then
git checkout master; BRANCH="master"
else else
git checkout $1; BRANCH="$1"
fi fi
bundle
yarn
cp .env.example .env function get_domain_info() {
sed -i -e "/SECRET_KEY_BASE/ s/=.*/=$secret/" .env read -rp 'Enter the domain/subdomain for Chatwoot (e.g., chatwoot.domain.com) :' domain_name
sed -i -e '/REDIS_URL/ s/=.*/=redis:\/\/localhost:6379/' .env read -rp 'Enter an email address for LetsEncrypt to send reminders when your SSL certificate is up for renewal :' le_email
sed -i -e '/POSTGRES_HOST/ s/=.*/=localhost/' .env cat << EOF
sed -i -e '/POSTGRES_USERNAME/ s/=.*/=chatwoot/' .env
sed -i -e "/POSTGRES_PASSWORD/ s/=.*/=$pg_pass/" .env
sed -i -e '/RAILS_ENV/ s/=.*/=$RAILS_ENV/' .env
echo -en "\nINSTALLATION_ENV=linux_script" >> ".env"
rake assets:precompile RAILS_ENV=production This script will generate SSL certificates via LetsEncrypt and serve Chatwoot at
https://$domain_name. Proceed further once you have pointed your DNS to the IP of the instance.
EOF
read -rp 'Do you wish to proceed? (yes or no): ' exit_true
if [ "$exit_true" == "no" ]
then
exit 1
fi
}
function install_dependencies() {
apt update && apt upgrade -y
apt install -y curl
curl -sL https://deb.nodesource.com/setup_12.x | bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt update
apt install -y \
git software-properties-common imagemagick libpq-dev \
libxml2-dev libxslt1-dev file g++ gcc autoconf build-essential \
libssl-dev libyaml-dev libreadline-dev gnupg2 \
postgresql-client redis-tools \
nodejs yarn patch ruby-dev zlib1g-dev liblzma-dev \
libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev sudo
}
function install_databases() {
apt install -y postgresql postgresql-contrib redis-server
}
function install_webserver() {
apt install -y nginx nginx-full certbot python3-certbot-nginx
}
function configure_rvm() {
adduser --disabled-login --gecos "" chatwoot
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable
adduser chatwoot rvm
}
function configure_db() {
pg_pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 15 ; echo '')
sudo -i -u postgres psql << EOF
\set pass `echo $pg_pass`
CREATE USER chatwoot CREATEDB;
ALTER USER chatwoot PASSWORD :'pass';
ALTER ROLE chatwoot SUPERUSER;
UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';
DROP DATABASE template1;
CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE';
UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';
\c template1
VACUUM FREEZE;
EOF EOF
if [ $install_pg_redis != "no" ] systemctl enable redis-server.service
then systemctl enable postgresql
sudo -i -u chatwoot << EOF
cd chatwoot }
RAILS_ENV=production bundle exec rake db:create
RAILS_ENV=production bundle exec rake db:reset function setup_chatwoot() {
secret=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo '')
RAILS_ENV=production
sudo -i -u chatwoot << EOF
rvm --version
rvm autolibs disable
rvm install "ruby-3.0.2"
rvm use 3.0.2 --default
git clone https://github.com/chatwoot/chatwoot.git
cd chatwoot
git checkout "$BRANCH"
bundle
yarn
cp .env.example .env
sed -i -e "/SECRET_KEY_BASE/ s/=.*/=$secret/" .env
sed -i -e '/REDIS_URL/ s/=.*/=redis:\/\/localhost:6379/' .env
sed -i -e '/POSTGRES_HOST/ s/=.*/=localhost/' .env
sed -i -e '/POSTGRES_USERNAME/ s/=.*/=chatwoot/' .env
sed -i -e "/POSTGRES_PASSWORD/ s/=.*/=$pg_pass/" .env
sed -i -e '/RAILS_ENV/ s/=.*/=$RAILS_ENV/' .env
echo -en "\nINSTALLATION_ENV=linux_script" >> ".env"
rake assets:precompile RAILS_ENV=production
EOF EOF
fi
cp /home/chatwoot/chatwoot/deployment/chatwoot-web.1.service /etc/systemd/system/chatwoot-web.1.service }
cp /home/chatwoot/chatwoot/deployment/chatwoot-worker.1.service /etc/systemd/system/chatwoot-worker.1.service
cp /home/chatwoot/chatwoot/deployment/chatwoot.target /etc/systemd/system/chatwoot.target
systemctl enable chatwoot.target
systemctl start chatwoot.target
public_ip=$(curl http://checkip.amazonaws.com -s) function run_db_migrations(){
sudo -i -u chatwoot << EOF
if [ $configure_webserver != "yes" ] cd chatwoot
then RAILS_ENV=production bundle exec rake db:create
echo -en "\n\n***************************************************************************\n" RAILS_ENV=production bundle exec rake db:reset
echo "Woot! Woot!! Chatwoot server installation is complete"
echo "The server will be accessible at http://$public_ip:3000"
echo "To configure a domain and SSL certificate, follow the guide at https://www.chatwoot.com/docs/deployment/deploy-chatwoot-in-linux-vm"
echo "***************************************************************************"
else
curl https://ssl-config.mozilla.org/ffdhe4096.txt >> /etc/ssl/dhparam
wget https://raw.githubusercontent.com/chatwoot/chatwoot/develop/deployment/nginx_chatwoot.conf
cp nginx_chatwoot.conf /etc/nginx/sites-available/nginx_chatwoot.conf
certbot certonly --non-interactive --agree-tos --nginx -m $le_email -d $domain_name
sed -i "s/chatwoot.domain.com/$domain_name/g" /etc/nginx/sites-available/nginx_chatwoot.conf
ln -s /etc/nginx/sites-available/nginx_chatwoot.conf /etc/nginx/sites-enabled/nginx_chatwoot.conf
systemctl restart nginx
sudo -i -u chatwoot << EOF
cd chatwoot
sed -i "s/http:\/\/0.0.0.0:3000/https:\/\/$domain_name/g" .env
EOF EOF
systemctl restart chatwoot.target
echo -en "\n\n***************************************************************************\n" }
echo "Woot! Woot!! Chatwoot server installation is complete"
echo "The server will be accessible at https://$domain_name"
echo "***************************************************************************"
fi
if [ $install_pg_redis == "no" ] function configure_systemd_services() {
then cp /home/chatwoot/chatwoot/deployment/chatwoot-web.1.service /etc/systemd/system/chatwoot-web.1.service
echo -en "\n\n***************************************************************************\n" cp /home/chatwoot/chatwoot/deployment/chatwoot-worker.1.service /etc/systemd/system/chatwoot-worker.1.service
echo "DB migrations are not run as pg and redis is not installed." cp /home/chatwoot/chatwoot/deployment/chatwoot.target /etc/systemd/system/chatwoot.target
echo "After modifying .env with your external db creds, run db migrations !!!"
echo "***************************************************************************" systemctl enable chatwoot.target
fi systemctl start chatwoot.target
}
function setup_ssl() {
echo "debug: setting up ssl"
echo "debug: domain: $domain_name"
echo "debug: letsencrypt email: $le_email"
curl https://ssl-config.mozilla.org/ffdhe4096.txt >> /etc/ssl/dhparam
wget https://raw.githubusercontent.com/chatwoot/chatwoot/develop/deployment/nginx_chatwoot.conf
cp nginx_chatwoot.conf /etc/nginx/sites-available/nginx_chatwoot.conf
certbot certonly --non-interactive --agree-tos --nginx -m "$le_email" -d "$domain_name"
sed -i "s/chatwoot.domain.com/$domain_name/g" /etc/nginx/sites-available/nginx_chatwoot.conf
ln -s /etc/nginx/sites-available/nginx_chatwoot.conf /etc/nginx/sites-enabled/nginx_chatwoot.conf
systemctl restart nginx
sudo -i -u chatwoot << EOF
cd chatwoot
sed -i "s/http:\/\/0.0.0.0:3000/https:\/\/$domain_name/g" .env
EOF
systemctl restart chatwoot.target
}
function setup_logging() {
touch /var/log/chatwoot-setup.log
LOG_FILE="/var/log/chatwoot-setup.log"
}
function main() {
setup_logging
cat << EOF
***************************************************************************
Chatwoot Installation (latest)
***************************************************************************
For more verbose logs, open up a second terminal and follow along using, `tail -f /var/log/chatwoot`.
EOF
sleep 3
read -rp 'Would you like to configure a domain and SSL for Chatwoot?(yes or no): ' configure_webserver
if [ "$configure_webserver" == "yes" ]
then
get_domain_info
fi
echo -en "\n"
read -rp 'Would you like to install Postgres and Redis? (Answer no if you plan to use external services): ' install_pg_redis
if [ "$install_pg_redis" == "no" ]
then
echo "***** Skipping Postgres and Redis installation. ****"
fi
echo -en "\n➥ 1/9 Installing dependencies. This takes a while."
install_dependencies &>> "${LOG_FILE}"
if [ "$install_pg_redis" != "no" ]
then
echo "➥ 2/9 Installing databases"
install_databases &>> "${LOG_FILE}"
fi
if [ "$configure_webserver" == "yes" ]
then
echo "➥ 3/9 Installing webserver"
install_webserver &>> "${LOG_FILE}"
fi
echo "➥ 4/9 Setting up Ruby"
configure_rvm &>> "${LOG_FILE}"
if [ "$install_pg_redis" != "no" ]
then
echo "➥ 5/9 Setting up the database"
configure_db &>> "${LOG_FILE}"
fi
echo "➥ 6/9 Installing Chatwoot. This takes a while."
setup_chatwoot &>> "${LOG_FILE}"
if [ "$install_pg_redis" != "no" ]
then
echo "➥ 7/9 Running migrations"
run_db_migrations &>> "${LOG_FILE}"
fi
echo "➥ 8/9 Setting up systemd services"
configure_systemd_services &>> "${LOG_FILE}"
public_ip=$(curl http://checkip.amazonaws.com -s)
if [ "$configure_webserver" != "yes" ]
then
cat << EOF
***************************************************************************
Woot! Woot!! Chatwoot server installation is complete.
The server will be accessible at http://$public_ip:3000
To configure a domain and SSL certificate, follow the guide at
https://www.chatwoot.com/docs/deployment/deploy-chatwoot-in-linux-vm
Join the community at https://chatwoot.com/community
***************************************************************************
EOF
else
echo "➥ 9/9 Setting up SSL/TLS"
setup_ssl &>> "${LOG_FILE}"
cat << EOF
***************************************************************************
Woot! Woot!! Chatwoot server installation is complete.
The server will be accessible at https://$domain_name
Join the community at https://chatwoot.com/community
***************************************************************************
EOF
fi
if [ "$install_pg_redis" == "no" ]
then
cat <<EOF
***************************************************************************
The database migrations had not run as Postgres and Redis were not installed
as part of the installation process. After modifying the environment
variables (in the .env file) with your external database credentials, run
the database migrations using the below command.
`RAILS_ENV=production bundle exec rails db:chatwoot_prepare`.
***************************************************************************
EOF
fi
exit 0
}
main "$@"