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

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 [[ -z "$1" ]]; then
BRANCH="master"
if [ $install_pg_redis == "no" ] else
then BRANCH="$1"
echo "***** Skipping pg and redis installation. ****"
fi fi
apt update && apt upgrade -y function get_domain_info() {
apt install -y curl read -rp 'Enter the domain/subdomain for Chatwoot (e.g., chatwoot.domain.com) :' domain_name
curl -sL https://deb.nodesource.com/setup_12.x | bash - read -rp 'Enter an email address for LetsEncrypt to send reminders when your SSL certificate is up for renewal :' le_email
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - cat << EOF
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
apt update
apt install -y \ 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 \ git software-properties-common imagemagick libpq-dev \
libxml2-dev libxslt1-dev file g++ gcc autoconf build-essential \ libxml2-dev libxslt1-dev file g++ gcc autoconf build-essential \
libssl-dev libyaml-dev libreadline-dev gnupg2 \ libssl-dev libyaml-dev libreadline-dev gnupg2 \
postgresql-client redis-tools \ postgresql-client redis-tools \
nodejs yarn patch ruby-dev zlib1g-dev liblzma-dev \ nodejs yarn patch ruby-dev zlib1g-dev liblzma-dev \
libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev sudo libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev sudo
}
if [ $install_pg_redis != "no" ] function install_databases() {
then apt install -y postgresql postgresql-contrib redis-server
apt install -y postgresql postgresql-contrib redis-server }
fi
if [ $configure_webserver == "yes" ] function install_webserver() {
then apt install -y nginx nginx-full certbot python3-certbot-nginx
apt install -y nginx nginx-full certbot python3-certbot-nginx }
fi
adduser --disabled-login --gecos "" chatwoot function configure_rvm() {
adduser --disabled-login --gecos "" chatwoot
gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
gpg2 --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 curl -sSL https://get.rvm.io | bash -s stable
adduser chatwoot rvm adduser chatwoot rvm
}
if [ $install_pg_redis != "no" ] function configure_db() {
then pg_pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 15 ; echo '')
pg_pass=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 15 ; echo '') sudo -i -u postgres psql << EOF
sudo -i -u postgres psql << EOF \set pass `echo $pg_pass`
\set pass `echo $pg_pass` CREATE USER chatwoot CREATEDB;
CREATE USER chatwoot CREATEDB; ALTER USER chatwoot PASSWORD :'pass';
ALTER USER chatwoot PASSWORD :'pass'; ALTER ROLE chatwoot SUPERUSER;
ALTER ROLE chatwoot SUPERUSER; UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';
UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1'; DROP DATABASE template1;
DROP DATABASE template1; CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE';
CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE'; UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';
UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1'; \c template1
\c template1 VACUUM FREEZE;
VACUUM FREEZE;
EOF EOF
systemctl enable redis-server.service systemctl enable redis-server.service
systemctl enable postgresql 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 function setup_chatwoot() {
rvm --version secret=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo '')
rvm autolibs disable RAILS_ENV=production
rvm install "ruby-3.0.2"
rvm use 3.0.2 --default
git clone https://github.com/chatwoot/chatwoot.git sudo -i -u chatwoot << EOF
cd chatwoot rvm --version
if [[ -z "$1" ]]; then rvm autolibs disable
git checkout master; rvm install "ruby-3.0.2"
else rvm use 3.0.2 --default
git checkout $1;
fi
bundle
yarn
cp .env.example .env git clone https://github.com/chatwoot/chatwoot.git
sed -i -e "/SECRET_KEY_BASE/ s/=.*/=$secret/" .env cd chatwoot
sed -i -e '/REDIS_URL/ s/=.*/=redis:\/\/localhost:6379/' .env git checkout "$BRANCH"
sed -i -e '/POSTGRES_HOST/ s/=.*/=localhost/' .env bundle
sed -i -e '/POSTGRES_USERNAME/ s/=.*/=chatwoot/' .env yarn
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 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
if [ $install_pg_redis != "no" ] }
then
sudo -i -u chatwoot << EOF
cd chatwoot function run_db_migrations(){
RAILS_ENV=production bundle exec rake db:create sudo -i -u chatwoot << EOF
RAILS_ENV=production bundle exec rake db:reset cd chatwoot
RAILS_ENV=production bundle exec rake db:create
RAILS_ENV=production bundle exec rake db:reset
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 configure_systemd_services() {
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
if [ $configure_webserver != "yes" ] systemctl enable chatwoot.target
then systemctl start chatwoot.target
echo -en "\n\n***************************************************************************\n" }
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" function setup_ssl() {
echo "***************************************************************************" echo "debug: setting up ssl"
else echo "debug: domain: $domain_name"
curl https://ssl-config.mozilla.org/ffdhe4096.txt >> /etc/ssl/dhparam echo "debug: letsencrypt email: $le_email"
wget https://raw.githubusercontent.com/chatwoot/chatwoot/develop/deployment/nginx_chatwoot.conf curl https://ssl-config.mozilla.org/ffdhe4096.txt >> /etc/ssl/dhparam
cp nginx_chatwoot.conf /etc/nginx/sites-available/nginx_chatwoot.conf wget https://raw.githubusercontent.com/chatwoot/chatwoot/develop/deployment/nginx_chatwoot.conf
certbot certonly --non-interactive --agree-tos --nginx -m $le_email -d $domain_name cp nginx_chatwoot.conf /etc/nginx/sites-available/nginx_chatwoot.conf
sed -i "s/chatwoot.domain.com/$domain_name/g" /etc/nginx/sites-available/nginx_chatwoot.conf certbot certonly --non-interactive --agree-tos --nginx -m "$le_email" -d "$domain_name"
ln -s /etc/nginx/sites-available/nginx_chatwoot.conf /etc/nginx/sites-enabled/nginx_chatwoot.conf sed -i "s/chatwoot.domain.com/$domain_name/g" /etc/nginx/sites-available/nginx_chatwoot.conf
systemctl restart nginx ln -s /etc/nginx/sites-available/nginx_chatwoot.conf /etc/nginx/sites-enabled/nginx_chatwoot.conf
sudo -i -u chatwoot << EOF systemctl restart nginx
cd chatwoot sudo -i -u chatwoot << EOF
sed -i "s/http:\/\/0.0.0.0:3000/https:\/\/$domain_name/g" .env cd chatwoot
sed -i "s/http:\/\/0.0.0.0:3000/https:\/\/$domain_name/g" .env
EOF EOF
systemctl restart chatwoot.target 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
function setup_logging() {
touch /var/log/chatwoot-setup.log
LOG_FILE="/var/log/chatwoot-setup.log"
}
if [ $install_pg_redis == "no" ] function main() {
then
echo -en "\n\n***************************************************************************\n" setup_logging
echo "DB migrations are not run as pg and redis is not installed." cat << EOF
echo "After modifying .env with your external db creds, run db migrations !!!"
echo "***************************************************************************" ***************************************************************************
fi 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 "$@"