1008 lines
28 KiB
Bash
Executable file
1008 lines
28 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
export LC_ALL=C # lscpu output is localized.
|
|
|
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
cd $DIR
|
|
|
|
if [ "$1" == "2container" ]
|
|
then
|
|
TWO_CONTAINER="1"
|
|
echo "2container argument is deprecated. Use --two-container"
|
|
shift 1
|
|
fi
|
|
|
|
while [ ${#} -gt 0 ]; do
|
|
case "${1}" in
|
|
--debug)
|
|
DEBUG="1"
|
|
SKIP_REBUILD="1"
|
|
;;
|
|
--skip-rebuild)
|
|
SKIP_REBUILD="1"
|
|
;;
|
|
--two-container)
|
|
TWO_CONTAINER="1"
|
|
;;
|
|
--skip-connection-test)
|
|
SKIP_CONNECTION_TEST="1"
|
|
echo "skipping connection test"
|
|
;;
|
|
esac
|
|
|
|
shift 1
|
|
done
|
|
|
|
##
|
|
## Make sure only root can run our script
|
|
##
|
|
check_root() {
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root. Please sudo or log in as root first." 1>&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
##
|
|
## Check whether a connection to HOSTNAME ($1) on PORT ($2) is possible
|
|
##
|
|
connect_to_port () {
|
|
HOST="$1"
|
|
PORT="$2"
|
|
VERIFY=$(date +%s | sha256sum | base64 | head -c 20)
|
|
if ! [ -x "$(command -v nc)" ]; then
|
|
echo "In order to check the connection to $HOST:$PORT we need to open a socket using netcat."
|
|
echo However netcat is not installed on your system. You can continue without this check
|
|
echo or abort the setup, install netcat and try again.
|
|
while true; do
|
|
read -p "Would you like to continue without this check? [yn] " yn
|
|
case $yn in
|
|
[Yy]*) return 2 ;;
|
|
[Nn]*) exit ;;
|
|
*) echo "Please answer y or n." ;;
|
|
esac
|
|
done
|
|
else
|
|
echo -e "HTTP/1.1 200 OK\n\n $VERIFY" | nc -w 4 -l -p $PORT >/dev/null 2>&1 &
|
|
if curl --proto =http -s $HOST:$PORT --connect-timeout 3 | grep $VERIFY >/dev/null 2>&1; then
|
|
return 0
|
|
else
|
|
curl --proto =http -s localhost:$PORT >/dev/null 2>&1
|
|
return 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
check_IP_match() {
|
|
HOST="$1"
|
|
echo
|
|
if [ "$SKIP_CONNECTION_TEST" == 1 ]
|
|
then
|
|
echo "Setting EC to 2"
|
|
ec=2
|
|
else
|
|
echo Checking your domain name . . .
|
|
connect_to_port $HOST 443; ec=$?
|
|
fi
|
|
case $ec in
|
|
0)
|
|
echo "Connection to $HOST succeeded."
|
|
;;
|
|
1)
|
|
echo "WARNING: Port 443 of computer does not appear to be accessible using hostname: $HOST."
|
|
if connect_to_port $HOST 80; then
|
|
echo
|
|
echo SUCCESS: A connection to port 80 succeeds!
|
|
echo This suggests that your DNS settings are correct,
|
|
echo but something is keeping traffic to port 443 from getting to your server.
|
|
echo Check your networking configuration to see that connections to port 443 are allowed.
|
|
else
|
|
echo "WARNING: Connection to http://$HOST (port 80) also fails."
|
|
echo
|
|
echo "This suggests that $HOST resolves to some IP address that does not reach this "
|
|
echo machine where you are installing discourse.
|
|
fi
|
|
echo
|
|
echo "The first thing to do is confirm that $HOST resolves to the IP address of this server."
|
|
echo You usually do this at the same place you purchased the domain.
|
|
echo
|
|
echo If you are sure that the IP address resolves correctly, it could be a firewall issue.
|
|
echo A web search for \"open ports YOUR CLOUD SERVICE\" might help.
|
|
echo
|
|
echo This tool is designed only for the most standard installations. If you cannot resolve
|
|
echo the issue above, you will need to edit containers/app.yml yourself and then type
|
|
echo
|
|
echo ./launcher rebuild app
|
|
echo
|
|
exit 1
|
|
;;
|
|
2)
|
|
echo "Skipping port check."
|
|
;;
|
|
esac
|
|
}
|
|
|
|
##
|
|
## Do we have docker?
|
|
##
|
|
|
|
check_docker() {
|
|
(which docker || which docker.io) &>/dev/null
|
|
}
|
|
|
|
check_and_install_docker() {
|
|
if ! check_docker; then
|
|
echo Failed to find docker or docker.io on your PATH.
|
|
read -p "Enter to install Docker from https://get.docker.com/ or Ctrl+C to exit"
|
|
curl https://get.docker.com/ | sh
|
|
|
|
if ! check_docker; then
|
|
echo Still failed to find docker or docker.io on your PATH.
|
|
echo Docker install failed. Quitting.
|
|
exit
|
|
fi
|
|
fi
|
|
}
|
|
|
|
##
|
|
## What are we running on
|
|
##
|
|
check_OS() {
|
|
echo `uname -s`
|
|
}
|
|
|
|
##
|
|
## macOS available memory
|
|
##
|
|
check_macos_memory() {
|
|
echo $(($(memory_pressure | head -n 1 | awk '{ print $4 }') / 1024 / 1024 / 1024))
|
|
}
|
|
|
|
##
|
|
## Linux available memory
|
|
##
|
|
check_linux_memory() {
|
|
## some VMs report just under 1GB of RAM, so
|
|
## make an exception and allow those with more
|
|
## than 989MB
|
|
mem=`free -m --si | awk ' /Mem:/ {print $2}'`
|
|
if [ "$mem" -ge 990 -a "$mem" -lt 1000 ]; then
|
|
echo 1
|
|
else
|
|
echo `free -g --si | awk ' /Mem:/ {print $2} '`
|
|
fi
|
|
}
|
|
|
|
##
|
|
## Do we have enough memory and disk space for Discourse?
|
|
##
|
|
check_disk_and_memory() {
|
|
os_type=$(check_OS)
|
|
avail_mem=0
|
|
if [ "$os_type" == "Darwin" ]; then
|
|
avail_mem=$(check_macos_memory)
|
|
else
|
|
avail_mem=$(check_linux_memory)
|
|
fi
|
|
|
|
if [ "$avail_mem" -lt 1 ]; then
|
|
echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
|
|
echo "to have sufficient memory."
|
|
echo
|
|
echo "Your site may not work properly, or future upgrades of Discourse may not"
|
|
echo "complete successfully."
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$avail_mem" -le 2 ]; then
|
|
total_swap=`free -g --si | awk ' /Swap:/ {print $2} '`
|
|
|
|
if [ "$total_swap" -lt 2 ]; then
|
|
echo "WARNING: Discourse requires at least 2GB of swap when running with 2GB of RAM"
|
|
echo "or less. This system does not appear to have sufficient swap space."
|
|
echo
|
|
echo "Without sufficient swap space, your site may not work properly, and future"
|
|
echo "upgrades of Discourse may not complete successfully."
|
|
echo
|
|
echo "Ctrl+C to exit or wait 5 seconds to have a 2GB swapfile created."
|
|
sleep 5
|
|
|
|
##
|
|
## derived from https://meta.discourse.org/t/13880
|
|
##
|
|
install -o root -g root -m 0600 /dev/null /swapfile
|
|
fallocate -l 2G /swapfile
|
|
mkswap /swapfile
|
|
swapon /swapfile
|
|
echo "/swapfile swap swap auto 0 0" | tee -a /etc/fstab
|
|
sysctl -w vm.swappiness=10
|
|
echo 'vm.swappiness = 10' > /etc/sysctl.d/30-discourse-swap.conf
|
|
|
|
total_swap=`free -g --si | awk ' /Swap:/ {print $2} '`
|
|
if [ "$total_swap" -lt 2 ]; then
|
|
echo "Failed to create swap: are you root? Are you running on real hardware, or a fully virtualized server?"
|
|
exit 1
|
|
fi
|
|
|
|
fi
|
|
fi
|
|
|
|
free_disk="$(df /var | tail -n 1 | awk '{print $4}')"
|
|
if [ "$free_disk" -lt 5000 ]; then
|
|
echo "WARNING: Discourse requires at least 5GB free disk space. This system"
|
|
echo "does not appear to have sufficient disk space."
|
|
echo
|
|
echo "Insufficient disk space may result in problems running your site, and"
|
|
echo "may not even allow Discourse installation to complete successfully."
|
|
echo
|
|
echo "Please free up some space, or expand your disk, before continuing."
|
|
echo
|
|
echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
|
|
echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
|
|
exit 1
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
##
|
|
## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
|
|
##
|
|
scale_ram_and_cpu() {
|
|
|
|
local changelog=/tmp/changelog.$PPID
|
|
# grab info about total system ram and physical (NOT LOGICAL!) CPU cores
|
|
avail_gb=0
|
|
avail_cores=0
|
|
os_type=$(check_OS)
|
|
if [ "$os_type" == "Darwin" ]; then
|
|
avail_gb=$(check_macos_memory)
|
|
avail_cores=`sysctl hw.ncpu | awk '/hw.ncpu:/ {print $2}'`
|
|
else
|
|
avail_gb=$(check_linux_memory)
|
|
threads_per_core=$(lscpu | awk 'BEGIN {FS=":"} /Thread\(s\) per core/ {print $2}')
|
|
avail_cores=$((`lscpu | awk '/^CPU\(s\):[[:blank:]]+[0-9]+[[:blank:]]*$/ {print $2; exit}'`*${threads_per_core}))
|
|
fi
|
|
echo "Found ${avail_gb}GB of memory and $avail_cores physical CPU cores"
|
|
|
|
# db_shared_buffers: 128MB for 1GB, 256MB for 2GB, or 256MB * GB, max 4096MB
|
|
if [ "$avail_gb" -eq "1" ]
|
|
then
|
|
db_shared_buffers=128
|
|
else
|
|
if [ "$avail_gb" -eq "2" ]
|
|
then
|
|
db_shared_buffers=256
|
|
else
|
|
db_shared_buffers=$(( 256 * $avail_gb ))
|
|
fi
|
|
fi
|
|
db_shared_buffers=$(( db_shared_buffers < 4096 ? db_shared_buffers : 4096 ))
|
|
|
|
sed -i -e "s/^ #\?db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}MB\"/w $changelog" $data_file
|
|
if [ -s $changelog ]
|
|
then
|
|
echo "setting db_shared_buffers = ${db_shared_buffers}MB"
|
|
rm $changelog
|
|
fi
|
|
|
|
# UNICORN_WORKERS: 2 * GB for 2GB or less, or 2 * CPU, max 8
|
|
if [ "$avail_gb" -le "2" ]
|
|
then
|
|
unicorn_workers=$(( 2 * $avail_gb ))
|
|
else
|
|
unicorn_workers=$(( 2 * $avail_cores ))
|
|
fi
|
|
unicorn_workers=$(( unicorn_workers < 8 ? unicorn_workers : 8 ))
|
|
|
|
sed -i -e "s/^ #\?UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
echo "setting UNICORN_WORKERS = ${unicorn_workers}"
|
|
rm $changelog
|
|
fi
|
|
|
|
echo $data_file memory parameters updated.
|
|
}
|
|
|
|
|
|
##
|
|
## standard http / https ports must not be occupied
|
|
##
|
|
check_ports() {
|
|
check_port "80"
|
|
check_port "443"
|
|
echo "Ports 80 and 443 are free for use"
|
|
}
|
|
|
|
|
|
##
|
|
## check a port to see if it is already in use
|
|
##
|
|
check_port() {
|
|
|
|
local valid=$(lsof -i:${1} | grep "LISTEN")
|
|
|
|
if [ -n "$valid" ]; then
|
|
echo "Port ${1} appears to already be in use."
|
|
echo
|
|
echo "This will show you what command is using port ${1}"
|
|
lsof -i tcp:${1} -s tcp:listen
|
|
echo
|
|
echo "If you are trying to run Discourse simultaneously with another web"
|
|
echo "server like Apache or nginx, you will need to bind to a different port"
|
|
echo
|
|
echo "See https://meta.discourse.org/t/17247"
|
|
echo
|
|
echo "If you are reconfiguring an already-configured Discourse, use "
|
|
echo
|
|
echo "./launcher stop app"
|
|
echo
|
|
echo "to stop Discourse before you reconfigure it and try again."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
##
|
|
## read a variable from the config file
|
|
##
|
|
read_config() {
|
|
config_line=`grep -E "^ #?$1:" $web_file`
|
|
read_config_result=`echo $config_line | awk -F":" '{print $2}'`
|
|
read_config_result=`echo $read_config_result | sed "s/^\([\"']\)\(.*\)\1\$/\2/g"`
|
|
}
|
|
|
|
read_default() {
|
|
config_line=`grep -E "^ #?$1:" samples/standalone.yml`
|
|
read_default_result=`echo $config_line | awk -F":" '{print $2}'`
|
|
read_default_result=`echo $read_config_result | sed "s/^\([\"']\)\(.*\)\1\$/\2/g"`
|
|
}
|
|
|
|
assert_maxmind_envs() {
|
|
if ! grep DISCOURSE_MAXMIND_LICENSE_KEY $web_file >/dev/null 2>&1
|
|
then
|
|
echo "Adding MAXMIND_LICENSE_KEY placeholder to $web_file"
|
|
sed -i '/^.*LETSENCRYPT_ACCOUNT_EMAIL.*/a \ \ #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456' $web_file
|
|
fi
|
|
|
|
if ! grep DISCOURSE_MAXMIND_ACCOUNT_ID $web_file >/dev/null 2>&1
|
|
then
|
|
echo "Adding MAXMIND_ACCOUNT_ID placeholder to $web_file"
|
|
sed -i '/^.*LETSENCRYPT_ACCOUNT_EMAIL.*/a \ \ #DISCOURSE_MAXMIND_ACCOUNT_ID: 123456' $web_file
|
|
fi
|
|
|
|
|
|
if ! grep -e DISCOURSE_MAXMIND_LICENSE_KEY -e DISCOURSE_MAXMIND_ACCOUNT_ID $web_file >/dev/null 2>&1
|
|
then
|
|
cat <<EOF
|
|
|
|
Adding DISCOURSE_MAXMIND_ACCOUNT_ID and DISCOURSE_MAXMIND_LICENSE_KEY to
|
|
$web_file has failed! This indicates either that your $web_file is very
|
|
old or otherwise not what the script expects or that there is a bug in
|
|
this script. The best solution for a novice is to delete $web_file and
|
|
start over. An expert might prefer to edit $web_file by hand.
|
|
|
|
EOF
|
|
read -p "Press return to continue or control-c to quit..."
|
|
fi
|
|
}
|
|
|
|
assert_smtp_domain() {
|
|
if ! grep DISCOURSE_SMTP_DOMAIN $web_file >/dev/null 2>&1
|
|
then
|
|
echo "Adding SMTP_DOMAIN placeholder to $web_file"
|
|
sed -i '/^.*DISCOURSE_SMTP_PASSWORD.*/a \ \ #DISCOURSE_SMTP_DOMAIN: discourse.example.com # (required by some providers)' $web_file
|
|
fi
|
|
if ! grep DISCOURSE_SMTP_DOMAIN $web_file >/dev/null 2>&1
|
|
then
|
|
cat <<EOF
|
|
|
|
Adding DISCOURSE_SMTP_DOMAIN to $web_file has failed! This
|
|
indicates either that your $web_file is very old or otherwise not
|
|
what the script expects or that there is a bug in this script. The
|
|
best solution for a novice is to delete $web_file and start over.
|
|
An expert might prefer to edit $web_file by hand.
|
|
|
|
EOF
|
|
read -p "Press return to continue or control-c to quit..."
|
|
fi
|
|
}
|
|
|
|
|
|
assert_notification_email() {
|
|
if ! grep DISCOURSE_NOTIFICATION_EMAIL $web_file >/dev/null 2>&1
|
|
then
|
|
echo "Adding DISCOURSE_NOTIFICATION_EMAIL placeholder to $web_file"
|
|
sed -i '/^.*DISCOURSE_SMTP_PASSWORD.*/a \ \ #DISCOURSE_NOTIFICATION_EMAIL: nobody@discourse.example.com # (address to send notifications from)' $web_file
|
|
fi
|
|
if ! grep DISCOURSE_NOTIFICATION_EMAIL $web_file >/dev/null 2>&1
|
|
then
|
|
cat <<EOF
|
|
|
|
Adding DISCOURSE_NOTIFICATION_EMAIL to $web_file has failed! This
|
|
indicates either that your $web_file is very old or otherwise not
|
|
what the script expects or that there is a bug in this script. The
|
|
best solution for a novice is to delete $web_file and start over.
|
|
An expert might prefer to edit $web_file by hand.
|
|
|
|
EOF
|
|
read -p "Press return to continue or control-c to quit..."
|
|
fi
|
|
}
|
|
|
|
|
|
##
|
|
## prompt user for typical Discourse config file values
|
|
##
|
|
ask_user_for_config() {
|
|
|
|
# NOTE: Defaults now come from standalone.yml
|
|
|
|
read_config "DISCOURSE_HOSTNAME"
|
|
hostname=$read_config_result
|
|
local changelog=/tmp/changelog.$PPID
|
|
read_config "DISCOURSE_SMTP_ADDRESS"
|
|
local smtp_address=$read_config_result
|
|
# NOTE: if there are spaces between emails, this breaks, but a human should be paying attention
|
|
read_config "DISCOURSE_DEVELOPER_EMAILS"
|
|
local developer_emails=$read_config_result
|
|
read_config "DISCOURSE_SMTP_PASSWORD"
|
|
local smtp_password=$read_config_result
|
|
read_config "DISCOURSE_SMTP_PORT"
|
|
local smtp_port=$read_config_result
|
|
read_config "DISCOURSE_SMTP_USER_NAME"
|
|
local smtp_user_name=$read_config_result
|
|
if [ "$smtp_password" = "pa\$\$word" ]
|
|
then
|
|
smtp_password=""
|
|
fi
|
|
read_config "DISCOURSE_NOTIFICATION_EMAIL"
|
|
local notification_email=$read_config_result
|
|
read_config "DISCOURSE_SMTP_DOMAIN"
|
|
local discourse_smtp_domain=$read_config_result
|
|
|
|
read_config "LETSENCRYPT_ACCOUNT_EMAIL"
|
|
local letsencrypt_account_email=$read_config_result
|
|
if [ -z $letsencrypt_account_email ]
|
|
then
|
|
letsencrypt_account_email="me@example.com"
|
|
fi
|
|
if [ "$letsencrypt_account_email" = "me@example.com" ]
|
|
then
|
|
local letsencrypt_status="ENTER to skip"
|
|
else
|
|
local letsencrypt_status="Enter 'OFF' to disable."
|
|
fi
|
|
|
|
read_config "DISCOURSE_MAXMIND_ACCOUNT_ID"
|
|
local maxmind_account_id=$read_config_result
|
|
if [ -z $maxmind_account_id ]
|
|
then
|
|
maxmind_account_id="123456"
|
|
fi
|
|
|
|
if [ "$maxmind_account_id" == "123456" ]
|
|
then
|
|
local maxmind_status="ENTER to continue without MAXMIND GeoLite2 geolocation database"
|
|
fi
|
|
|
|
read_config "DISCOURSE_MAXMIND_LICENSE_KEY"
|
|
local maxmind_license_key=$read_config_result
|
|
if [ -z $maxmind_license_key ]
|
|
then
|
|
maxmind_license_key="1234567890123456"
|
|
fi
|
|
|
|
local new_value=""
|
|
local config_ok="n"
|
|
local update_ok="y"
|
|
|
|
echo ""
|
|
|
|
while [[ "$config_ok" == "n" ]]
|
|
do
|
|
if [ ! -z "$hostname" ]
|
|
then
|
|
read -p "Hostname for your Discourse? [$hostname]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
hostname="$new_value"
|
|
fi
|
|
if [[ $hostname =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]
|
|
then
|
|
echo
|
|
echo "Discourse requires a DNS hostname. IP addresses are unsupported and will not work."
|
|
echo
|
|
hostname="discourse.example.com"
|
|
fi
|
|
fi
|
|
|
|
check_IP_match $hostname
|
|
|
|
if [ ! -z "$developer_emails" ]
|
|
then
|
|
local email_valid="n"
|
|
until [ "$email_valid" == "y" ]
|
|
do
|
|
read -p "Email address for admin account(s)? [$developer_emails]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
if [[ ${#new_value} -ge 7 && $new_value == *@* ]]
|
|
then
|
|
developer_emails="$new_value"
|
|
email_valid="y"
|
|
else
|
|
echo
|
|
echo "[Error] Invalid email address"
|
|
echo
|
|
fi
|
|
else
|
|
email_valid="y"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ ! -z "$smtp_address" ]
|
|
then
|
|
read -p "SMTP server address? [$smtp_address]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
smtp_address="$new_value"
|
|
fi
|
|
fi
|
|
|
|
if [ ! -z "$smtp_port" ]
|
|
then
|
|
read -p "SMTP port? [$smtp_port]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
smtp_port="$new_value"
|
|
fi
|
|
fi
|
|
|
|
##
|
|
## automatically set correct user name based on common mail providers unless it's been set
|
|
##
|
|
if [ "$smtp_user_name" == "user@example.com" ]
|
|
then
|
|
if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
|
|
then
|
|
smtp_user_name="SMTP_Injection"
|
|
fi
|
|
if [ "$smtp_address" == "smtp.sendgrid.net" ]
|
|
then
|
|
smtp_user_name="apikey"
|
|
fi
|
|
if [ "$smtp_address" == "smtp.mailgun.org" ]
|
|
then
|
|
smtp_user_name="postmaster@$hostname"
|
|
fi
|
|
fi
|
|
|
|
if [ ! -z "$smtp_user_name" ]
|
|
then
|
|
read -p "SMTP user name? [$smtp_user_name]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
smtp_user_name="$new_value"
|
|
fi
|
|
fi
|
|
|
|
read -p "SMTP password? [$smtp_password]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
smtp_password="$new_value"
|
|
fi
|
|
|
|
if [[ "$notification_email" == "noreply@discourse.example.com"* ]]
|
|
then
|
|
notification_email="noreply@$hostname"
|
|
fi
|
|
|
|
read -p "notification email address? [$notification_email]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
notification_email="$new_value"
|
|
fi
|
|
|
|
# set smtp_domain default value here rather than use Rails default of localhost
|
|
default_smtp_domain=${notification_email#*@}
|
|
# if DISCOURSE_SMTP_DOMAIN is in the config use that instead
|
|
smtp_domain=${discourse_smtp_domain:-${default_smtp_domain}}
|
|
|
|
if [ ! -z $letsencrypt_account_email ]
|
|
then
|
|
read -p "Optional email address for Let's Encrypt warnings? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
letsencrypt_account_email="$new_value"
|
|
if [ "${new_value,,}" = "off" ]
|
|
then
|
|
letsencrypt_status="ENTER to skip"
|
|
else
|
|
letsencrypt_status="Enter 'OFF' to disable."
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
read_config "DISCOURSE_MAXMIND_ACCOUNT_ID"
|
|
local maxmind_account_id=$read_config_result
|
|
read -p "Optional MaxMind Account ID ($maxmind_status) [$maxmind_account_id]: " new_value
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
maxmind_account_id="$new_value"
|
|
|
|
read_config "DISCOURSE_MAXMIND_LICENSE_KEY"
|
|
local maxmind_license_key=$read_config_result
|
|
read -p "MaxMind License key [$maxmind_license_key]: " new_value
|
|
|
|
if [ ! -z "$new_value" ]
|
|
then
|
|
maxmind_license_key="$new_value"
|
|
fi
|
|
fi
|
|
|
|
echo -e "\nDoes this look right?\n"
|
|
echo "Hostname : $hostname"
|
|
echo "Email : $developer_emails"
|
|
echo "SMTP address : $smtp_address"
|
|
echo "SMTP port : $smtp_port"
|
|
echo "SMTP username : $smtp_user_name"
|
|
echo "SMTP password : $smtp_password"
|
|
echo "Notification email: $notification_email"
|
|
|
|
if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
|
|
then
|
|
echo "Let's Encrypt : $letsencrypt_account_email"
|
|
fi
|
|
|
|
if [ "$maxmind_account_id" != "123456" ]
|
|
then
|
|
echo "MaxMind account ID: $maxmind_account_id"
|
|
else
|
|
echo "MaxMind account ID: (unset)"
|
|
fi
|
|
|
|
if [ "$maxmind_license_key" != "1234567890123456" ]
|
|
then
|
|
echo "MaxMind license key: $maxmind_license_key"
|
|
else
|
|
echo "MaxMind license key: (unset)"
|
|
fi
|
|
|
|
echo ""
|
|
read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
|
|
done
|
|
|
|
sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_HOSTNAME change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_DEVELOPER_EMAILS change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_SMTP_ADDRESS change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
sed -i -e "s/^ #\?DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_SMTP_PORT change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
sed -i -e "s/^ #\?DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_SMTP_USER_NAME change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
sed -i -e "s/^ #\?DISCOURSE_NOTIFICATION_EMAIL:.*/ DISCOURSE_NOTIFICATION_EMAIL: $notification_email/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_NOTIFICATION_EMAIL change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
sed -i -e "s/^ #\?DISCOURSE_SMTP_DOMAIN:.*/ DISCOURSE_SMTP_DOMAIN: $smtp_domain/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_SMTP_DOMAIN change failed."
|
|
update_ok="n"
|
|
fi
|
|
|
|
if [[ "$smtp_password" == *"\""* ]]
|
|
then
|
|
SLASH="BROKEN"
|
|
echo "========================================"
|
|
echo "WARNING!!!"
|
|
echo "Your password contains a quote (\")"
|
|
echo "Your SMTP Password will not be set. You will need to edit app.yml to enter it."
|
|
echo "========================================"
|
|
update_ok="n"
|
|
else
|
|
SLASH="|"
|
|
if [[ "$smtp_password" == *"$SLASH"* ]]
|
|
then SLASH="+"
|
|
if [[ "$smtp_password" == *"$SLASH"* ]]
|
|
then
|
|
SLASH="Q"
|
|
if [[ "$smtp_password" == *"$SLASH"* ]]
|
|
then
|
|
SLASH="BROKEN"
|
|
echo "========================================"
|
|
echo "WARNING!!!"
|
|
echo "Your password contains all available delimiters (+, |, and Q). "
|
|
echo "Your SMTP Password will not be set. You will need to edit app.yml to enter it."
|
|
echo "========================================"
|
|
update_ok="n"
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
if [[ "$SLASH" != "BROKEN" ]]
|
|
then
|
|
sed -i -e "s${SLASH}^ #\?DISCOURSE_SMTP_PASSWORD:.*${SLASH} DISCOURSE_SMTP_PASSWORD: \"${smtp_password}\"${SLASH}w $changelog" $web_file
|
|
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_SMTP_PASSWORD change failed."
|
|
update_ok="n"
|
|
fi
|
|
fi
|
|
|
|
if ! [ -z $DEBUG ]
|
|
then
|
|
echo "Enabling Let's Encrypt"
|
|
fi
|
|
sed -i -e "s/^ #\?LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "LETSENCRYPT_ACCOUNT_EMAIL change failed."
|
|
update_ok="n"
|
|
fi
|
|
local src='^ #\?- "templates\/web.ssl.template.yml"'
|
|
local dst=' \- "templates\/web.ssl.template.yml"'
|
|
sed -i -e "s/$src/$dst/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
if ! [ -z $DEBUG ]
|
|
then
|
|
echo "web.ssl.template.yml enabled"
|
|
fi
|
|
else
|
|
update_ok="n"
|
|
echo "web.ssl.template.yml NOT ENABLED--was it on already?"
|
|
fi
|
|
local src='^ #\?- "templates\/web.letsencrypt.ssl.template.yml"'
|
|
local dst=' - "templates\/web.letsencrypt.ssl.template.yml"'
|
|
|
|
sed -i -e "s/$src/$dst/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
echo "letsencrypt.ssl.template.yml enabled"
|
|
else
|
|
update_ok="n"
|
|
echo "letsencrypt.ssl.template.yml NOT ENABLED -- was it on already?"
|
|
fi
|
|
|
|
echo
|
|
|
|
if [ $maxmind_account_id != "123456" ]
|
|
then
|
|
sed -i -e "s/^.*DISCOURSE_MAXMIND_ACCOUNT_ID:.*/ DISCOURSE_MAXMIND_ACCOUNT_ID: $maxmind_account_id/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_MAXMIND_ACCOUNT_ID change failed."
|
|
update_ok="n"
|
|
fi
|
|
fi
|
|
|
|
if [ $maxmind_license_key != "1234567890123456" ]
|
|
then
|
|
sed -i -e "s/^.*DISCOURSE_MAXMIND_LICENSE_KEY:.*/ DISCOURSE_MAXMIND_LICENSE_KEY: $maxmind_license_key/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "DISCOURSE_MAXMIND_LICENSE_KEY change failed."
|
|
update_ok="n"
|
|
fi
|
|
fi
|
|
|
|
if [ "$update_ok" == "y" ]
|
|
then
|
|
echo -e "\nConfiguration file at $web_file updated successfully!\n"
|
|
else
|
|
echo -e "\nUnfortunately, there was an error changing $web_file\n"
|
|
echo -e "This may happen if you have made unexpected changes."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
##
|
|
## is our config file valid? Does it have the required fields set?
|
|
##
|
|
validate_config() {
|
|
|
|
valid_config="y"
|
|
|
|
for x in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
|
|
DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
|
|
do
|
|
read_config $x
|
|
local result=$read_config_result
|
|
read_default $x
|
|
local default=$read_default_result
|
|
|
|
if [ ! -z "$result" ]
|
|
then
|
|
if [[ "$config_line" = *"$default"* ]]
|
|
then
|
|
echo "$x left at incorrect default of $default"
|
|
valid_config="n"
|
|
fi
|
|
config_val=`echo $config_line | awk '{print $2}'`
|
|
if [ -z $config_val ]
|
|
then
|
|
echo "$x was not configured"
|
|
valid_config="n"
|
|
fi
|
|
else
|
|
echo "$x not present"
|
|
valid_config="n"
|
|
fi
|
|
done
|
|
|
|
if [ "$valid_config" != "y" ]; then
|
|
echo -e "\nSorry, these $web_file settings aren't valid -- can't continue!"
|
|
echo "If you have unusual requirements, edit $web_file and then: "
|
|
echo "./launcher bootstrap $app_name"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
|
|
##
|
|
## template file names
|
|
##
|
|
|
|
if [ "$TWO_CONTAINER" ] || [ -f containers/web_only.yml ]
|
|
then
|
|
app_name=web_only
|
|
data_name=data
|
|
web_template=samples/web_only.yml
|
|
data_template=samples/data.yml
|
|
web_file=containers/$app_name.yml
|
|
data_file=containers/$data_name.yml
|
|
else
|
|
app_name=app
|
|
data_name=app
|
|
web_template=samples/standalone.yml
|
|
data_template=""
|
|
web_file=containers/$app_name.yml
|
|
data_file=containers/$app_name.yml
|
|
fi
|
|
changelog=/tmp/changelog
|
|
|
|
##
|
|
## Check requirements before creating a copy of a config file we won't edit
|
|
##
|
|
check_root
|
|
check_and_install_docker
|
|
check_disk_and_memory
|
|
|
|
if [ -a "$web_file" ]
|
|
then
|
|
echo "The configuration file $web_file already exists!"
|
|
echo
|
|
echo ". . . reconfiguring . . ."
|
|
echo
|
|
echo
|
|
DATE=`date +"%Y-%m-%d-%H%M%S"`
|
|
BACKUP=$app_name.yml.$DATE.bak
|
|
echo Saving old file as $BACKUP
|
|
install -m0600 $web_file containers/$BACKUP
|
|
if [ "$DEBUG" != "1" ]
|
|
then
|
|
echo "Stopping existing container in 5 seconds or Control-C to cancel."
|
|
sleep 5
|
|
./launcher stop $app_name
|
|
else
|
|
echo "DEBUG MODE ON. Not stopping the container."
|
|
fi
|
|
assert_maxmind_envs
|
|
assert_notification_email
|
|
assert_smtp_domain
|
|
echo
|
|
else
|
|
if [ "$SKIP_CONNECTION_TEST" != 1 ]
|
|
then
|
|
check_ports
|
|
fi
|
|
install -v -m0600 $web_template $web_file
|
|
if [ "$data_name" == "data" ]
|
|
then
|
|
echo "--------------------------------------------------"
|
|
echo "This two container setup is currently unsupported. Use at your own risk!"
|
|
echo "--------------------------------------------------"
|
|
DISCOURSE_DB_PASSWORD=`date +%s | sha256sum | base64 | head -c 20`
|
|
|
|
sed -i -e "s/DISCOURSE_DB_PASSWORD: SOME_SECRET/DISCOURSE_DB_PASSWORD: $DISCOURSE_DB_PASSWORD/w $changelog" $web_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "Problem changing DISCOURSE_DB_PASSWORD" in $web_file
|
|
fi
|
|
|
|
install -v -m0600 $data_template $data_file
|
|
quote=\'
|
|
sed -i -e "s/password ${quote}SOME_SECRET${quote}/password '$DISCOURSE_DB_PASSWORD'/w $changelog" $data_file
|
|
if [ -s $changelog ]
|
|
then
|
|
rm $changelog
|
|
else
|
|
echo "Problem changing DISCOURSE_DB_PASSWORD" in $data_file
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
scale_ram_and_cpu
|
|
ask_user_for_config
|
|
validate_config
|
|
|
|
##
|
|
## if we reach this point without exiting, OK to proceed
|
|
## rebuild won't fail if there's nothing to rebuild and does the restart
|
|
##
|
|
if [ "$SKIP_REBUILD" ]
|
|
then
|
|
echo "Updates successful. --skip-rebuild requested. Exiting."
|
|
exit
|
|
fi
|
|
|
|
echo "Updates successful. Rebuilding in 5 seconds."
|
|
sleep 5 # Just a chance to ^C in case they were too fast on the draw
|
|
|
|
if [ "$data_name" == "$app_name" ]
|
|
then
|
|
echo Building $app_name
|
|
./launcher rebuild $app_name
|
|
else
|
|
echo Building $data_name now . . .
|
|
./launcher rebuild $data_name
|
|
echo Building $app_name now . . .
|
|
./launcher rebuild $app_name
|
|
fi
|