feat: add chatwoot ctl(cwctl) cli tool (#4836)
* chore: Add log messages for stages skipped during installation * feat: allow chatwoot user to start/stop/restart chatwoot service * feat: init options support * feat: add option support to linux install script [c|h|i|l|s|u|wi] Install/Update/Configure/Manage your Chatwoot installation Example: cwctl -i master Example: cwctl -l web Example: cwctl --logs worker Example: cwctl --upgrade Example: cwctl -c Installation/Upgrade: -i, --install install Chatwoot with the git branch specified -u, --upgrade upgrade Chatwoot to latest version -s, --ssl fetch and install ssl certificates using LetsEncrypt -w, --webserver install and configure Nginx webserver Management: -c, --console open ruby console -l, --logs tail logs from Chatwoot. Supported values include web/worker. Miscellaneous: -h, --help display this help text and exit * feat: add cwctl to PATH * feat: add -v to cwctl * chore: switch db migration to db:chatwoot_prepare * fix: reload systemd files after update * fix: improve -s -w cwctl options * chore: throw error if run without options Signed-off-by: Vishnu Narayanan <vishnu@chatwoot.com> * feat: add -d/--debug option to cwctl * fix: remove hardcoded ruby version in cwctl --upgrade * chore: improve cwctl -v function * fix: disable cwctl selfupdate * chore: cleanup * feat: allow chatwoot user to run cwctl * chore: cwctl improve formatting for log messages * fix: variable expansion inside heredoc * feat: save pg_pass to file to support idempotency One of the things preventing idempotency was the postgres password generated at run-time to setup postgres initally. This commit saves the password to the file if postgres setup function is executed and reloads on future re-runs if needed. * chore: formatting * chore: add cwctl promotion message at the end of installation * feat: add comments * chore: add chatwoot and cwctl version files * feat: add func to get latest chatwoot version * chore: formatting * feat: add --restart option to cwctl * chore: update --help with restart option details * chore: minor improvements to --restart
This commit is contained in:
parent
ffd102cdfe
commit
f2dd88223f
4 changed files with 631 additions and 82 deletions
1
VERSION_CW
Normal file
1
VERSION_CW
Normal file
|
@ -0,0 +1 @@
|
||||||
|
2.6.0
|
1
VERSION_CWCTL
Normal file
1
VERSION_CWCTL
Normal file
|
@ -0,0 +1 @@
|
||||||
|
2.0.7
|
6
deployment/chatwoot
Normal file
6
deployment/chatwoot
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# give chatwoot user permission to start/stop/restart chatwoot systemd service
|
||||||
|
|
||||||
|
%chatwoot ALL=NOPASSWD: /bin/systemctl start chatwoot.target
|
||||||
|
%chatwoot ALL=NOPASSWD: /bin/systemctl stop chatwoot.target
|
||||||
|
%chatwoot ALL=NOPASSWD: /bin/systemctl restart chatwoot.target
|
||||||
|
%chatwoot ALL=NOPASSWD: /usr/local/bin/cwctl
|
|
@ -1,14 +1,127 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Description: Chatwoot installation script
|
# Description: Install and manage a Chatwoot installation.
|
||||||
# OS: Ubuntu 20.04 LTS
|
# OS: Ubuntu 20.04 LTS
|
||||||
# Script Version: 1.0
|
# Script Version: 2.0.7
|
||||||
# Run this script as root
|
# Run this script as root
|
||||||
|
|
||||||
set -eu -o pipefail
|
set -eu -o errexit -o pipefail -o noclobber -o nounset
|
||||||
trap exit_handler EXIT
|
|
||||||
|
# -allow a command to fail with !’s side effect on errexit
|
||||||
|
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
|
||||||
|
! getopt --test > /dev/null
|
||||||
|
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
|
||||||
|
echo '`getopt --test` failed in this environment.'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Global variables
|
||||||
|
# option --output/-o requires 1 argument
|
||||||
|
LONGOPTS=console,debug,help,install:,logs:,restart,ssl,upgrade,webserver,version
|
||||||
|
OPTIONS=cdhi:l:rsuwv
|
||||||
|
CWCTL_VERSION="2.0.7"
|
||||||
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 '')
|
||||||
|
|
||||||
|
# if user does not specify an option
|
||||||
|
if [ -z "$1" ]; then
|
||||||
|
echo "No options specified. Use --help to learn more."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# -regarding ! and PIPESTATUS see above
|
||||||
|
# -temporarily store output to be able to check for errors
|
||||||
|
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
|
||||||
|
# -pass arguments only via -- "$@" to separate them correctly
|
||||||
|
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
|
||||||
|
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
|
||||||
|
# e.g. return value is 1
|
||||||
|
# then getopt has complained about wrong arguments to stdout
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
# read getopt’s output this way to handle the quoting right:
|
||||||
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
|
c=n d=n h=n i=n l=n r=n s=n u=n w=n v=n BRANCH=master SERVICE=web
|
||||||
|
# Iterate options in order and nicely split until we see --
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-c|--console)
|
||||||
|
c=y
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-d|--debug)
|
||||||
|
d=y
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
h=y
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-i|--install)
|
||||||
|
i=y
|
||||||
|
BRANCH="$2"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-l|--logs)
|
||||||
|
l=y
|
||||||
|
SERVICE="$2"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-r|--restart)
|
||||||
|
r=y
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-s|--ssl)
|
||||||
|
s=y
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-u|--upgrade)
|
||||||
|
u=y
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-w|--webserver)
|
||||||
|
w=y
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-v|--version)
|
||||||
|
v=y
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Invalid option(s) specified. Use help(-h) to learn more."
|
||||||
|
exit 3
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# log if debug flag set
|
||||||
|
if [ "$d" == "y" ]; then
|
||||||
|
echo "console: $c, debug: $d, help: $h, install: $i, BRANCH: $BRANCH, \
|
||||||
|
logs: $l, SERVICE: $SERVICE, ssl: $s, upgrade: $u, webserver: $w"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# exit if script is not run as root
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
echo 'This needs to be run as root.' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap exit_handler EXIT
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Invoked upon EXIT signal from bash
|
||||||
|
# Upon non-zero exit, notifies the user to check log file.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function exit_handler() {
|
function exit_handler() {
|
||||||
if [ "$?" -ne 0 ]; then
|
if [ "$?" -ne 0 ]; then
|
||||||
echo -en "\nSome error has occured. Check '/var/log/chatwoot-setup.log' for details.\n"
|
echo -en "\nSome error has occured. Check '/var/log/chatwoot-setup.log' for details.\n"
|
||||||
|
@ -16,33 +129,41 @@ function exit_handler() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$(id -u)" -ne 0 ]; then
|
##############################################################################
|
||||||
echo 'This script should be run as root.' >&2
|
# Read user input related to domain setup
|
||||||
exit 1
|
# Globals:
|
||||||
fi
|
# domain_name
|
||||||
|
# le_email
|
||||||
if [[ -z "$1" ]]; then
|
# Arguments:
|
||||||
BRANCH="master"
|
# None
|
||||||
else
|
# Outputs:
|
||||||
BRANCH="$1"
|
# None
|
||||||
fi
|
##############################################################################
|
||||||
|
|
||||||
function get_domain_info() {
|
function get_domain_info() {
|
||||||
read -rp 'Enter the domain/subdomain for Chatwoot (e.g., chatwoot.domain.com) :' domain_name
|
read -rp 'Enter the domain/subdomain for Chatwoot (e.g., chatwoot.domain.com): ' domain_name
|
||||||
read -rp 'Enter an email address for LetsEncrypt to send reminders when your SSL certificate is up for renewal :' le_email
|
read -rp 'Enter an email address for LetsEncrypt to send reminders when your SSL certificate is up for renewal: ' le_email
|
||||||
cat << EOF
|
cat << EOF
|
||||||
|
|
||||||
This script will generate SSL certificates via LetsEncrypt and serve Chatwoot at
|
This script will generate SSL certificates via LetsEncrypt and
|
||||||
https://$domain_name. Proceed further once you have pointed your DNS to the IP of the instance.
|
serve Chatwoot at https://$domain_name.
|
||||||
|
Proceed further once you have pointed your DNS to the IP of the instance.
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
read -rp 'Do you wish to proceed? (yes or no): ' exit_true
|
read -rp 'Do you wish to proceed? (yes or no): ' exit_true
|
||||||
if [ "$exit_true" == "no" ]
|
if [ "$exit_true" == "no" ]; then
|
||||||
then
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Install common dependencies
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function install_dependencies() {
|
function install_dependencies() {
|
||||||
apt update && apt upgrade -y
|
apt update && apt upgrade -y
|
||||||
apt install -y curl
|
apt install -y curl
|
||||||
|
@ -60,16 +181,58 @@ function install_dependencies() {
|
||||||
libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev sudo
|
libgmp-dev libncurses5-dev libffi-dev libgdbm6 libgdbm-dev sudo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Install postgres and redis
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function install_databases() {
|
function install_databases() {
|
||||||
apt install -y postgresql postgresql-contrib redis-server
|
apt install -y postgresql postgresql-contrib redis-server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Install nginx and cerbot for LetsEncrypt
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function install_webserver() {
|
function install_webserver() {
|
||||||
apt install -y nginx nginx-full certbot python3-certbot-nginx
|
apt install -y nginx nginx-full certbot python3-certbot-nginx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Create chatwoot linux user
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function create_cw_user() {
|
||||||
|
if ! id -u "chatwoot"; then
|
||||||
|
adduser --disabled-login --gecos "" chatwoot
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Install rvm(ruby version manager)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function configure_rvm() {
|
function configure_rvm() {
|
||||||
adduser --disabled-login --gecos "" chatwoot
|
create_cw_user
|
||||||
|
|
||||||
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
|
||||||
|
@ -77,28 +240,85 @@ function configure_rvm() {
|
||||||
adduser chatwoot rvm
|
adduser chatwoot rvm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Save the pgpass used to setup postgres
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function save_pgpass() {
|
||||||
|
mkdir -p /opt/chatwoot/config
|
||||||
|
file="/opt/chatwoot/config/.pg_pass"
|
||||||
|
if ! test -f "$file"; then
|
||||||
|
echo $pg_pass > /opt/chatwoot/config/.pg_pass
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Get the pgpass used to setup postgres if installation fails midway
|
||||||
|
# and needs to be re-run
|
||||||
|
# Globals:
|
||||||
|
# pg_pass
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function get_pgpass() {
|
||||||
|
file="/opt/chatwoot/config/.pg_pass"
|
||||||
|
if test -f "$file"; then
|
||||||
|
pg_pass=$(cat $file)
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Configure postgres to create chatwoot db user.
|
||||||
|
# Enable postgres and redis systemd services.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function configure_db() {
|
function configure_db() {
|
||||||
sudo -i -u postgres psql << EOF
|
save_pgpass
|
||||||
\set pass `echo $pg_pass`
|
get_pgpass
|
||||||
CREATE USER chatwoot CREATEDB;
|
sudo -i -u postgres psql << EOF
|
||||||
ALTER USER chatwoot PASSWORD :'pass';
|
\set pass `echo $pg_pass`
|
||||||
ALTER ROLE chatwoot SUPERUSER;
|
CREATE USER chatwoot CREATEDB;
|
||||||
UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';
|
ALTER USER chatwoot PASSWORD :'pass';
|
||||||
DROP DATABASE template1;
|
ALTER ROLE chatwoot SUPERUSER;
|
||||||
CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE';
|
UPDATE pg_database SET datistemplate = FALSE WHERE datname = 'template1';
|
||||||
UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';
|
DROP DATABASE template1;
|
||||||
\c template1
|
CREATE DATABASE template1 WITH TEMPLATE = template0 ENCODING = 'UNICODE';
|
||||||
VACUUM FREEZE;
|
UPDATE pg_database SET datistemplate = TRUE WHERE datname = 'template1';
|
||||||
|
\c template1
|
||||||
|
VACUUM FREEZE;
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
systemctl enable redis-server.service
|
systemctl enable redis-server.service
|
||||||
systemctl enable postgresql
|
systemctl enable postgresql
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Install Chatwoot
|
||||||
|
# This includes setting up ruby, cloning repo and installing dependencies.
|
||||||
|
# Globals:
|
||||||
|
# pg_pass
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function setup_chatwoot() {
|
function setup_chatwoot() {
|
||||||
secret=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo '')
|
local secret=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 63 ; echo '')
|
||||||
RAILS_ENV=production
|
local RAILS_ENV=production
|
||||||
|
get_pgpass
|
||||||
|
|
||||||
sudo -i -u chatwoot << EOF
|
sudo -i -u chatwoot << EOF
|
||||||
rvm --version
|
rvm --version
|
||||||
|
@ -123,34 +343,64 @@ function setup_chatwoot() {
|
||||||
|
|
||||||
rake assets:precompile RAILS_ENV=production
|
rake assets:precompile RAILS_ENV=production
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Run database migrations.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function run_db_migrations(){
|
function run_db_migrations(){
|
||||||
sudo -i -u chatwoot << EOF
|
sudo -i -u chatwoot << EOF
|
||||||
cd chatwoot
|
cd chatwoot
|
||||||
RAILS_ENV=production bundle exec rake db:create
|
RAILS_ENV=production bundle exec rails db:chatwoot_prepare
|
||||||
RAILS_ENV=production bundle exec rake db:reset
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Setup Chatwoot systemd services and cwctl CLI
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function configure_systemd_services() {
|
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-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-worker.1.service /etc/systemd/system/chatwoot-worker.1.service
|
||||||
cp /home/chatwoot/chatwoot/deployment/chatwoot.target /etc/systemd/system/chatwoot.target
|
cp /home/chatwoot/chatwoot/deployment/chatwoot.target /etc/systemd/system/chatwoot.target
|
||||||
|
|
||||||
|
cp /home/chatwoot/chatwoot/deployment/chatwoot /etc/sudoers.d/chatwoot
|
||||||
|
cp /home/chatwoot/chatwoot/deployment/setup_20.04.sh /usr/local/bin/cwctl
|
||||||
|
chmod +x /usr/local/bin/cwctl
|
||||||
|
|
||||||
systemctl enable chatwoot.target
|
systemctl enable chatwoot.target
|
||||||
systemctl start chatwoot.target
|
systemctl start chatwoot.target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Fetch and install SSL certificates from LetsEncrypt
|
||||||
|
# Modify the nginx config and restart nginx.
|
||||||
|
# Also modifies FRONTEND_URL in .env file.
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# domain_name
|
||||||
|
# le_email
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function setup_ssl() {
|
function setup_ssl() {
|
||||||
echo "debug: setting up ssl"
|
if [ "$d" == "y" ]; then
|
||||||
echo "debug: domain: $domain_name"
|
echo "debug: setting up ssl"
|
||||||
echo "debug: letsencrypt email: $le_email"
|
echo "debug: domain: $domain_name"
|
||||||
|
echo "debug: letsencrypt email: $le_email"
|
||||||
|
fi
|
||||||
curl https://ssl-config.mozilla.org/ffdhe4096.txt >> /etc/ssl/dhparam
|
curl https://ssl-config.mozilla.org/ffdhe4096.txt >> /etc/ssl/dhparam
|
||||||
wget https://raw.githubusercontent.com/chatwoot/chatwoot/develop/deployment/nginx_chatwoot.conf
|
wget https://raw.githubusercontent.com/chatwoot/chatwoot/develop/deployment/nginx_chatwoot.conf
|
||||||
cp nginx_chatwoot.conf /etc/nginx/sites-available/nginx_chatwoot.conf
|
cp nginx_chatwoot.conf /etc/nginx/sites-available/nginx_chatwoot.conf
|
||||||
|
@ -165,75 +415,123 @@ EOF
|
||||||
systemctl restart chatwoot.target
|
systemctl restart chatwoot.target
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Setup logging
|
||||||
|
# Globals:
|
||||||
|
# LOG_FILE
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
function setup_logging() {
|
function setup_logging() {
|
||||||
touch /var/log/chatwoot-setup.log
|
touch /var/log/chatwoot-setup.log
|
||||||
LOG_FILE="/var/log/chatwoot-setup.log"
|
LOG_FILE="/var/log/chatwoot-setup.log"
|
||||||
}
|
}
|
||||||
|
|
||||||
function main() {
|
function ssl_success_message() {
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
setup_logging
|
***************************************************************************
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
function cwctl_message() {
|
||||||
|
echo $'\U0001F680 Try out the all new Chatwoot CLI tool to manage your installation.'
|
||||||
|
echo $'\U0001F680 Type "cwctl --help" to learn more.'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# This function handles the installation(-i/--install)
|
||||||
|
# Globals:
|
||||||
|
# CW_VERSION
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function get_cw_version() {
|
||||||
|
CW_VERSION=$(curl -s https://app.chatwoot.com/api | python3 -c 'import sys,json;data=json.loads(sys.stdin.read()); print(data["version"])')
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# This function handles the installation(-i/--install)
|
||||||
|
# Globals:
|
||||||
|
# configure_webserver
|
||||||
|
# install_pg_redis
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function install() {
|
||||||
|
get_cw_version
|
||||||
cat << EOF
|
cat << EOF
|
||||||
|
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
Chatwoot Installation (latest)
|
Chatwoot Installation (v$CW_VERSION)
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
|
|
||||||
For more verbose logs, open up a second terminal and follow along using,
|
For more verbose logs, open up a second terminal and follow along using,
|
||||||
'tail -f /var/log/chatwoot'.
|
'tail -f /var/log/chatwoot-setup.log'.
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
sleep 3
|
sleep 3
|
||||||
read -rp 'Would you like to configure a domain and SSL for Chatwoot?(yes or no): ' configure_webserver
|
read -rp 'Would you like to configure a domain and SSL for Chatwoot?(yes or no): ' configure_webserver
|
||||||
|
|
||||||
if [ "$configure_webserver" == "yes" ]
|
if [ "$configure_webserver" == "yes" ]; then
|
||||||
then
|
|
||||||
get_domain_info
|
get_domain_info
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -en "\n"
|
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
|
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.\n"
|
echo -en "\n➥ 1/9 Installing dependencies. This takes a while.\n"
|
||||||
install_dependencies &>> "${LOG_FILE}"
|
install_dependencies &>> "${LOG_FILE}"
|
||||||
|
|
||||||
if [ "$install_pg_redis" != "no" ]
|
if [ "$install_pg_redis" != "no" ]; then
|
||||||
then
|
echo "➥ 2/9 Installing databases."
|
||||||
echo "➥ 2/9 Installing databases"
|
|
||||||
install_databases &>> "${LOG_FILE}"
|
install_databases &>> "${LOG_FILE}"
|
||||||
|
else
|
||||||
|
echo "➥ 2/9 Skipping Postgres and Redis installation."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$configure_webserver" == "yes" ]
|
if [ "$configure_webserver" == "yes" ]; then
|
||||||
then
|
echo "➥ 3/9 Installing webserver."
|
||||||
echo "➥ 3/9 Installing webserver"
|
|
||||||
install_webserver &>> "${LOG_FILE}"
|
install_webserver &>> "${LOG_FILE}"
|
||||||
|
else
|
||||||
|
echo "➥ 3/9 Skipping webserver installation."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "➥ 4/9 Setting up Ruby"
|
echo "➥ 4/9 Setting up Ruby"
|
||||||
configure_rvm &>> "${LOG_FILE}"
|
configure_rvm &>> "${LOG_FILE}"
|
||||||
|
|
||||||
if [ "$install_pg_redis" != "no" ]
|
if [ "$install_pg_redis" != "no" ]; then
|
||||||
then
|
echo "➥ 5/9 Setting up the database."
|
||||||
echo "➥ 5/9 Setting up the database"
|
|
||||||
configure_db &>> "${LOG_FILE}"
|
configure_db &>> "${LOG_FILE}"
|
||||||
|
else
|
||||||
|
echo "➥ 5/9 Skipping database setup."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "➥ 6/9 Installing Chatwoot. This takes a while."
|
echo "➥ 6/9 Installing Chatwoot. This takes a long while."
|
||||||
setup_chatwoot &>> "${LOG_FILE}"
|
setup_chatwoot &>> "${LOG_FILE}"
|
||||||
|
|
||||||
if [ "$install_pg_redis" != "no" ]
|
if [ "$install_pg_redis" != "no" ]; then
|
||||||
then
|
echo "➥ 7/9 Running database migrations."
|
||||||
echo "➥ 7/9 Running migrations"
|
|
||||||
run_db_migrations &>> "${LOG_FILE}"
|
run_db_migrations &>> "${LOG_FILE}"
|
||||||
|
else
|
||||||
|
echo "➥ 7/9 Skipping database migrations."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "➥ 8/9 Setting up systemd services"
|
echo "➥ 8/9 Setting up systemd services."
|
||||||
configure_systemd_services &>> "${LOG_FILE}"
|
configure_systemd_services &>> "${LOG_FILE}"
|
||||||
|
|
||||||
public_ip=$(curl http://checkip.amazonaws.com -s)
|
public_ip=$(curl http://checkip.amazonaws.com -s)
|
||||||
|
@ -241,6 +539,7 @@ EOF
|
||||||
if [ "$configure_webserver" != "yes" ]
|
if [ "$configure_webserver" != "yes" ]
|
||||||
then
|
then
|
||||||
cat << EOF
|
cat << EOF
|
||||||
|
➥ 9/9 Skipping SSL/TLS setup.
|
||||||
|
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
Woot! Woot!! Chatwoot server installation is complete.
|
Woot! Woot!! Chatwoot server installation is complete.
|
||||||
|
@ -251,24 +550,20 @@ https://www.chatwoot.com/docs/deployment/deploy-chatwoot-in-linux-vm
|
||||||
|
|
||||||
Join the community at https://chatwoot.com/community
|
Join the community at https://chatwoot.com/community
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
cwctl_message
|
||||||
else
|
else
|
||||||
echo "➥ 9/9 Setting up SSL/TLS"
|
echo "➥ 9/9 Setting up SSL/TLS."
|
||||||
setup_ssl &>> "${LOG_FILE}"
|
setup_ssl &>> "${LOG_FILE}"
|
||||||
cat << EOF
|
ssl_success_message
|
||||||
|
cwctl_message
|
||||||
***************************************************************************
|
|
||||||
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
|
fi
|
||||||
|
|
||||||
if [ "$install_pg_redis" == "no" ]
|
if [ "$install_pg_redis" == "no" ]
|
||||||
then
|
then
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
The database migrations had not run as Postgres and Redis were not installed
|
The database migrations had not run as Postgres and Redis were not installed
|
||||||
as part of the installation process. After modifying the environment
|
as part of the installation process. After modifying the environment
|
||||||
|
@ -276,11 +571,257 @@ variables (in the .env file) with your external database credentials, run
|
||||||
the database migrations using the below command.
|
the database migrations using the below command.
|
||||||
'RAILS_ENV=production bundle exec rails db:chatwoot_prepare'.
|
'RAILS_ENV=production bundle exec rails db:chatwoot_prepare'.
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
cwctl_message
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Access ruby console (-c/--console)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function get_console() {
|
||||||
|
sudo -i -u chatwoot bash -c " cd chatwoot && RAILS_ENV=production bundle exec rails c"
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Prints the help message (-c/--console)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function help() {
|
||||||
|
|
||||||
|
cat <<EOF
|
||||||
|
Usage: cwctl [OPTION]...
|
||||||
|
Install and manage your Chatwoot installation.
|
||||||
|
|
||||||
|
Example: cwctl -i master
|
||||||
|
Example: cwctl -l web
|
||||||
|
Example: cwctl --logs worker
|
||||||
|
Example: cwctl --upgrade
|
||||||
|
Example: cwctl -c
|
||||||
|
|
||||||
|
Installation/Upgrade:
|
||||||
|
-i, --install install Chatwoot with the git branch specified
|
||||||
|
-u, --upgrade upgrade Chatwoot to latest version
|
||||||
|
-s, --ssl fetch and install ssl certificates using LetsEncrypt
|
||||||
|
-w, --webserver install and configure Nginx webserver with SSL
|
||||||
|
|
||||||
|
Management:
|
||||||
|
-c, --console open ruby console
|
||||||
|
-l, --logs view logs from Chatwoot. Supported values include web/worker.
|
||||||
|
-r, --restart restart Chatwoot server
|
||||||
|
|
||||||
|
Miscellaneous:
|
||||||
|
-d, --debug show debug messages
|
||||||
|
-v, --version display version information and exit
|
||||||
|
-h, --help display this help text and exit
|
||||||
|
|
||||||
|
Exit status:
|
||||||
|
Returns 0 if successful; non-zero otherwise.
|
||||||
|
|
||||||
|
Report bugs at https://github.com/chatwoot/chatwoot/issues
|
||||||
|
Get help, https://chatwoot.com/community
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Get Chatwoot web/worker logs (-l/--logs)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function get_logs() {
|
||||||
|
if [ "$SERVICE" == "worker" ]; then
|
||||||
|
journalctl -u chatwoot-worker.1.service -f
|
||||||
|
else
|
||||||
|
journalctl -u chatwoot-web.1.service -f
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Setup SSL (-s/--ssl)
|
||||||
|
# Installs nginx if not available.
|
||||||
|
# Globals:
|
||||||
|
# domain_name
|
||||||
|
# le_email
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function ssl() {
|
||||||
|
echo "Setting up ssl"
|
||||||
|
get_domain_info
|
||||||
|
if ! systemctl -q is-active nginx; then
|
||||||
|
install_webserver
|
||||||
|
fi
|
||||||
|
setup_ssl
|
||||||
|
ssl_success_message
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Upgrade an existing installation to latest stable version(-u/--upgrade)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function upgrade() {
|
||||||
|
get_cw_version
|
||||||
|
echo "Upgrading Chatwoot to v$CW_VERSION"
|
||||||
|
|
||||||
|
sudo -i -u chatwoot << "EOF"
|
||||||
|
|
||||||
|
# Navigate to the Chatwoot directory
|
||||||
|
cd chatwoot
|
||||||
|
|
||||||
|
# Pull the latest version of the master branch
|
||||||
|
git checkout master && git pull
|
||||||
|
|
||||||
|
# Ensure the ruby version is upto date
|
||||||
|
# Parse the latest ruby version
|
||||||
|
latest_ruby_version="$(cat '.ruby-version')"
|
||||||
|
rvm install "ruby-$latest_ruby_version"
|
||||||
|
rvm use "$latest_ruby_version" --default
|
||||||
|
|
||||||
|
# Update dependencies
|
||||||
|
bundle
|
||||||
|
yarn
|
||||||
|
|
||||||
|
# Recompile the assets
|
||||||
|
rake assets:precompile RAILS_ENV=production
|
||||||
|
|
||||||
|
# Migrate the database schema
|
||||||
|
RAILS_ENV=production bundle exec rake db:migrate
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Copy the updated targets
|
||||||
|
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
|
||||||
|
|
||||||
|
cp /home/chatwoot/chatwoot/deployment/chatwoot /etc/sudoers.d/chatwoot
|
||||||
|
# TODO:(@vn) handle cwctl updates
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# Restart the chatwoot server
|
||||||
|
systemctl restart chatwoot.target
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Restart Chatwoot server (-r/--restart)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function restart() {
|
||||||
|
systemctl restart chatwoot.target
|
||||||
|
systemctl status chatwoot.target
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Install nginx and setup SSL (-w/--webserver)
|
||||||
|
# Globals:
|
||||||
|
# domain_name
|
||||||
|
# le_email
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function webserver() {
|
||||||
|
echo "Installing nginx"
|
||||||
|
ssl
|
||||||
|
#TODO(@vn): allow installing nginx only without SSL
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# Print cwctl version (-v/--version)
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function version() {
|
||||||
|
echo "cwctl v$CWCTL_VERSION alpha build"
|
||||||
|
}
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
# main function that handles the control flow
|
||||||
|
# Globals:
|
||||||
|
# None
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
# Outputs:
|
||||||
|
# None
|
||||||
|
##############################################################################
|
||||||
|
function main() {
|
||||||
|
setup_logging
|
||||||
|
|
||||||
|
if [ "$c" == "y" ]; then
|
||||||
|
get_console
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$h" == "y" ]; then
|
||||||
|
help
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$i" == "y" ]; then
|
||||||
|
install
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$l" == "y" ]; then
|
||||||
|
get_logs
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$r" == "y" ]; then
|
||||||
|
restart
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$s" == "y" ]; then
|
||||||
|
ssl
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$u" == "y" ]; then
|
||||||
|
upgrade
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$w" == "y" ]; then
|
||||||
|
webserver
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$v" == "y" ]; then
|
||||||
|
version
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
Loading…
Reference in a new issue