#!/usr/bin/env bash
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $DIR
##
## Make sure only root can run our script
connect_to_port () {
HOST="$1"
PORT="$2"
- VERIFY=`date +%s | sha256sum | base64 | head -c 20`
- 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
+ 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
- curl --proto =http -s localhost:$PORT >/dev/null 2>&1
- return 1
+ 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 () {
+check_IP_match() {
HOST="$1"
echo
echo Checking your domain name . . .
- if connect_to_port $HOST 443
- then
- echo
+ connect_to_port $HOST 443; ec=$?
+ case $ec in
+ 0)
echo "Connection to $HOST succeeded."
- else
- echo WARNING:: This server does not appear to be accessible at $HOST:443.
- echo
- if connect_to_port $HOST 80
- then
- echo A connection to port 80 succeeds, however.
- 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 "A connection to http://$HOST (port 80) also fails."
+ ;;
+ 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 This suggests that $HOST resolves to the wrong IP address
- echo or that traffic is not being routed to your server.
- fi
- echo
- echo Google: \"open ports YOUR CLOUD SERVICE\" for information for resolving this problem.
- echo
- echo You should probably answer \"n\" at the next prompt and disable Let\'s Encrypt.
- echo
- echo This test might not work for all situations,
- echo so if you can access Discourse at http://$HOST, you might try anyway.
- sleep 3
- fi
+ 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 "Continuing without port check."
+ ;;
+ esac
}
##
## OS X available memory
##
check_osx_memory() {
- echo `top -l 1 | awk '/PhysMem:/ {print $2}' | sed s/G//`
+ echo `free -m | awk '/Mem:/ {print $2}'`
}
##
## Linux available memory
##
check_linux_memory() {
- echo `free -g --si | awk ' /Mem:/ {print $2} '`
+ ## 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
}
##
## derived from https://meta.discourse.org/t/13880
##
install -o root -g root -m 0600 /dev/null /swapfile
- dd if=/dev/zero of=/swapfile bs=1k count=2048k
+ 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 | tee -a /etc/sysctl.conf
+ 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, sorry!"
+ echo "Failed to create swap: are you root? Are you running on real hardware, or a fully virtualized server?"
exit 1
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" $config_file
+ 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"
fi
unicorn_workers=$(( unicorn_workers < 8 ? unicorn_workers : 8 ))
- sed -i -e "s/^ #\?UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
+ 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 $config_file memory parameters updated.
+ echo $data_file memory parameters updated.
}
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
## read a variable from the config file
##
read_config() {
-
- config_line=`egrep "^ #?$1:" $config_file`
- read_config_result=`echo $config_line | awk '{print $2}'`
+ config_line=`egrep "^ #?$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=`egrep "^ #?$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"`
+}
##
## prompt user for typical Discourse config file values
while [[ "$config_ok" == "n" ]]
do
- if [ ! -z $hostname ]
+ if [ ! -z "$hostname" ]
then
read -p "Hostname for your Discourse? [$hostname]: " new_value
- if [ ! -z $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
- hostname=$new_value
+ echo
+ echo "Discourse requires a DNS hostname. IP addresses are unsupported and will not work."
+ echo
+ hostname="discourse.example.com"
fi
fi
- if [ ! -z $developer_emails ]
+ check_IP_match $hostname
+
+ if [ ! -z "$developer_emails" ]
then
read -p "Email address for admin account(s)? [$developer_emails]: " new_value
- if [ ! -z $new_value ]
+ if [ ! -z "$new_value" ]
then
- developer_emails=$new_value
+ developer_emails="$new_value"
fi
fi
- if [ ! -z $smtp_address ]
+ if [ ! -z "$smtp_address" ]
then
read -p "SMTP server address? [$smtp_address]: " new_value
- if [ ! -z $new_value ]
+ if [ ! -z "$new_value" ]
then
- smtp_address=$new_value
+ smtp_address="$new_value"
fi
fi
- if [ ! -z $smtp_port ]
+ if [ ! -z "$smtp_port" ]
then
read -p "SMTP port? [$smtp_port]: " new_value
- if [ ! -z $new_value ]
+ if [ ! -z "$new_value" ]
then
- smtp_port=$new_value
+ smtp_port="$new_value"
fi
fi
##
- ## automatically set correct user name based on common mail providers
+ ## automatically set correct user name based on common mail providers unless it's been set
##
- if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
- then
- smtp_user_name="SMTP_Injection"
- fi
- if [ "$smtp_address" == "smtp.sendgrid.net" ]
+ if [ "$smtp_user_name" == "user@example.com" ]
then
- smtp_user_name="apikey"
- fi
- if [ "$smtp_address" == "smtp.mailgun.org" ]
- then
- smtp_user_name="postmaster@$hostname"
+ 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 ]
+ if [ ! -z "$smtp_user_name" ]
then
read -p "SMTP user name? [$smtp_user_name]: " new_value
- if [ ! -z $new_value ]
+ if [ ! -z "$new_value" ]
then
- smtp_user_name=$new_value
+ smtp_user_name="$new_value"
fi
fi
read -p "SMTP password? [$smtp_password]: " new_value
- if [ ! -z $new_value ]
+ if [ ! -z "$new_value" ]
then
- smtp_password=$new_value
+ smtp_password="$new_value"
fi
if [ ! -z $letsencrypt_account_email ]
then
- read -p "Let's Encrypt account email? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
- if [ ! -z $new_value ]
+ 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
+ letsencrypt_account_email="$new_value"
if [ "${new_value,,}" = "off" ]
then
letsencrypt_status="ENTER to skip"
fi
fi
- if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
- then
- check_IP_match $hostname
- fi
-
echo -e "\nDoes this look right?\n"
echo "Hostname : $hostname"
echo "Email : $developer_emails"
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" $config_file
+ sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $web_file
if [ -s $changelog ]
then
rm $changelog
update_ok="n"
fi
- sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $config_file
+ sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $web_file
if [ -s $changelog ]
then
rm $changelog
update_ok="n"
fi
- sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
+ sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $web_file
if [ -s $changelog ]
then
rm $changelog
update_ok="n"
fi
- sed -i -e "s/^ #\?DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $config_file
+ sed -i -e "s/^ #\?DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $web_file
if [ -s $changelog ]
then
rm $changelog
update_ok="n"
fi
- sed -i -e "s/^ #\?DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
+ 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
update_ok="n"
fi
- sed -i -e "s/^ #\?DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: \"${smtp_password/\//\\/}\"/w $changelog" $config_file
- if [ -s $changelog ]
+ if [[ "$smtp_password" == *"\""* ]]
then
- rm $changelog
- else
- echo "DISCOURSE_SMTP_PASSWORD change failed."
+ 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 [ "$letsencrypt_status" = "ENTER to skip" ]
+ if [[ "$SLASH" != "BROKEN" ]]
then
- local src='^ #\?- "templates\/web.ssl.template.yml"'
- local dst=' #\- "templates\/web.ssl.template.yml"'
- sed -i -e "s/$src/$dst/w $changelog" $config_file
- if [ ! -s $changelog ]
- then
- update_ok="n"
- echo "web.ssl.template.yml NOT DISABLED--Are you using a non-standard template?"
- fi
- local src='^ #\?- "templates\/web.letsencrypt.ssl.template.yml"'
- local dst=' #- "templates\/web.letsencrypt.ssl.template.yml"'
+ sed -i -e "s${SLASH}^ #\?DISCOURSE_SMTP_PASSWORD:.*${SLASH} DISCOURSE_SMTP_PASSWORD: \"${smtp_password}\"${SLASH}w $changelog" $web_file
- sed -i -e "s/$src/$dst/w $changelog" $config_file
- if [ ! -s $changelog ]
- then
- update_ok="n"
- echo "web.ssl.template.yml NOT DISABLED--Are you using a non-standard template?"
- fi
- else # enable let's encrypt
- echo "Let's Encrypt will be enabled for $letsencrypt_account_email"
- sed -i -e "s/^ #\?LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_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" $config_file
- if [ -s $changelog ]
- then
- echo "web.ssl.template.yml enabled"
- 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" $config_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
+ if [ -s $changelog ]
+ then
+ rm $changelog
+ else
+ echo "DISCOURSE_SMTP_PASSWORD change failed."
+ update_ok="n"
+ fi
fi
+ echo "Enabling Let's Encrypt"
+ 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
+ echo "web.ssl.template.yml enabled"
+ 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
+
if [ "$update_ok" == "y" ]
then
echo -e "\nConfiguration file at $config_file updated successfully!\n"
for x in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
do
- config_line=`grep "^ $x:" $config_file`
- local result=$?
- local default="example.com"
+ read_config $x
+ local result=$read_config_result
+ read_default $x
+ local default=$read_default_result
- if (( result == 0 ))
+ if [ ! -z "$result" ]
then
if [[ "$config_line" = *"$default"* ]]
then
- echo "$x left at incorrect default of example.com"
+ 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 left blank"
+ echo "$x was not configured"
valid_config="n"
fi
else
done
if [ "$valid_config" != "y" ]; then
- echo -e "\nSorry, these $config_file settings aren't valid -- can't continue!"
- echo "If you have unusual requirements, edit $config_file and 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
##
-app_name=app
-template_path=samples/standalone.yml
-config_file=containers/$app_name.yml
-changelog=/tmp/changelog
+
+if [ "$1" == "2container" ]
+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_and_install_docker
check_disk_and_memory
-##
-## make a copy of the simple standalone config file
-##
-if [ -a $config_file ]
+if [ -a "$web_file" ]
then
- echo "The configuration file $config_file already exists."
+ echo "The configuration file $web_file already exists!"
echo
echo ". . . reconfiguring . . ."
echo
DATE=`date +"%Y-%m-%d-%H%M%S"`
BACKUP=$app_name.yml.$DATE.bak
echo Saving old file as $BACKUP
- cp $config_file containers/$BACKUP
+ cp $web_file containers/$BACKUP
echo "Stopping existing container in 5 seconds or Control-C to cancel."
sleep 5
./launcher stop app
echo
else
- check_ports # don't need to check ports if Discourse was already installed
- cp $template_path $config_file
+ check_ports
+ cp -v $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
+
+ cp -v $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
##
echo "Updates successful. Rebuilding in 5 seconds."
sleep 5 # Just a chance to ^C in case they were too fast on the draw
-time ./launcher rebuild $app_name
+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