4 ## Make sure only root can run our script
7 if [[ $EUID -ne 0 ]]; then
8 echo "This script must be run as root. Please sudo or log in as root first." 1>&2
15 ## Does the current IP match the domain name?
19 echo Checking your domain name . . .
22 local IFCONFIG
=`which ifconfig`
23 /sbin
/route |
grep default
> /tmp
/route
$PPID
25 if grep default
/tmp
/route
$PPID > /dev
/null
27 local IFACE
=`cut -c 73-100 /tmp/route$PPID |head -1`
29 echo WARNING
: Cannot check your IP number.
31 local IP
=`$IFCONFIG $IFACE|grep "inet addr:" |cut -d":" -f 2|cut -d" " -f1|head -1`
32 local RESOLVED_IP
=`dig +short $1`
35 if [[ ! -z $RESOLVED_IP ]]
37 if [ $IP == $RESOLVED_IP ]
39 echo $1 resolves to
$IP. Looks good
!
44 if [ $IP_LOOKS_GOOD == 0 ]
46 echo "-----------------------------------------"
47 echo $1 does not resolve to
$IP.
48 echo IT IS ALMOST CERTAINLY A BAD IDEA TO TURN ON LET
\'S ENCRYPT
!!
49 echo Unless you know why this check failed
, DO NOT USE Let
\'s Encrypt.
51 echo You should answer
\"n
\" at the next prompt and disable Let
\'s Encrypt.
52 echo You have been warned.
53 echo "-----------------------------------------"
61 check_and_install_docker
() {
62 docker_path
=`which docker.io || which docker`
63 if [ -z $docker_path ]; then
64 read -p "Docker not installed. Enter to install from https://get.docker.com/ or Ctrl+C to exit"
65 curl https
://get.docker.com
/ | sh
67 docker_path
=`which docker.io || which docker`
68 if [ -z $docker_path ]; then
69 echo Docker
install failed. Quitting.
75 ## What are we running on
82 ## OS X available memory
85 echo `top -l 1 | awk '/PhysMem:/ {print $2}' | sed s/G//`
89 ## Linux available memory
91 check_linux_memory
() {
92 echo `free -g --si | awk ' /Mem:/ {print $2} '`
96 ## Do we have enough memory and disk space for Discourse?
98 check_disk_and_memory
() {
102 if [ $os_type == "Darwin" ]; then
103 avail_mem
=$
(check_osx_memory
)
105 avail_mem
=$
(check_linux_memory
)
108 if [ "$avail_mem" -lt 1 ]; then
109 echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
110 echo "to have sufficient memory."
112 echo "Your site may not work properly, or future upgrades of Discourse may not"
113 echo "complete successfully."
117 if [ "$avail_mem" -le 2 ]; then
118 total_swap
=`free -g --si | awk ' /Swap:/ {print $2} '`
119 if [ "$total_swap" -lt 2 ]; then
120 echo "WARNING: Discourse requires at least 2GB of swap when running with 2GB of RAM"
121 echo "or less. This system does not appear to have sufficient swap space."
123 echo "Without sufficient swap space, your site may not work properly, and future"
124 echo "upgrades of Discourse may not complete successfully."
126 read -p "ENTER to create a 2GB swapfile now, or Ctrl+C to exit"
129 ## derived from https://meta.discourse.org/t/13880
131 install -o root
-g root
-m 0600 /dev
/null
/swapfile
132 dd if=/dev
/zero of
=/swapfile bs
=1k count
=2048k
135 echo "/swapfile swap swap auto 0 0" |
tee -a /etc
/fstab
136 sysctl
-w vm.swappiness
=10
137 echo vm.swappiness
= 10 |
tee -a /etc
/sysctl.conf
139 total_swap
=`free -g --si | awk ' /Swap:/ {print $2} '`
140 if [ "$total_swap" -lt 2 ]; then
141 echo "Failed to create swap, sorry!"
149 free_disk
="$(df /var | tail -n 1 | awk '{print $4}')"
150 if [ "$free_disk" -lt 5000 ]; then
151 echo "WARNING: Discourse requires at least 5GB free disk space. This system"
152 echo "does not appear to have sufficient disk space."
154 echo "Insufficient disk space may result in problems running your site, and"
155 echo "may not even allow Discourse installation to complete successfully."
157 echo "Please free up some space, or expand your disk, before continuing."
159 echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
160 echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
168 ## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
170 scale_ram_and_cpu
() {
172 local changelog
=/tmp
/changelog.
$PPID
173 # grab info about total system ram and physical (NOT LOGICAL!) CPU cores
177 if [ $os_type == "Darwin" ]; then
178 avail_gb
=$
(check_osx_memory
)
179 avail_cores
=`sysctl hw.ncpu | awk '/hw.ncpu:/ {print $2}'`
181 avail_gb
=$
(check_linux_memory
)
182 avail_cores
=$
((`awk '/cpu cores/ {print $4;exit}' /proc/cpuinfo`*`sort /proc/cpuinfo | uniq | grep -c "physical id"`))
184 echo "Found ${avail_gb}GB of memory and $avail_cores physical CPU cores"
186 # db_shared_buffers: 128MB for 1GB, 256MB for 2GB, or 256MB * GB, max 4096MB
187 if [ "$avail_gb" -eq "1" ]
189 db_shared_buffers
=128
191 if [ "$avail_gb" -eq "2" ]
193 db_shared_buffers
=256
195 db_shared_buffers
=$
(( 256 * $avail_gb ))
198 db_shared_buffers
=$
(( db_shared_buffers
< 4096 ? db_shared_buffers
: 4096 ))
200 sed -i -e "s/^ #\?db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}MB\"/w $changelog" $config_file
203 echo "setting db_shared_buffers = ${db_shared_buffers}MB"
207 # UNICORN_WORKERS: 2 * GB for 2GB or less, or 2 * CPU, max 8
208 if [ "$avail_gb" -le "2" ]
210 unicorn_workers
=$
(( 2 * $avail_gb ))
212 unicorn_workers
=$
(( 2 * $avail_cores ))
214 unicorn_workers
=$
(( unicorn_workers
< 8 ? unicorn_workers
: 8 ))
216 sed -i -e "s/^ #\?UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
219 echo "setting UNICORN_WORKERS = ${unicorn_workers}"
227 ## standard http / https ports must not be occupied
232 echo "Ports 80 and 443 are free for use"
237 ## check a port to see if it is already in use
241 local valid
=$
(netstat
-tln |
awk '{print $4}' |
grep ":${1}\$")
243 if [ -n "$valid" ]; then
244 echo "Port ${1} appears to already be in use."
246 echo "If you are trying to run Discourse simultaneously with another web"
247 echo "server like Apache or nginx, you will need to bind to a different port"
249 echo "See https://meta.discourse.org/t/17247"
251 echo "If you are reconfiguring an already-configured Discourse, use "
253 echo "./launcher stop app"
255 echo "to stop Discourse before you reconfigure it and try again."
261 ## read a variable from the config file
265 config_line
=`egrep "^ #?$1:" $config_file`
266 read_config_result
=`echo $config_line | awk '{print $2}'`
267 read_config_result
=`echo $read_config_result | sed "s/^\([\"']\)\(.*\)\1\$/\2/g"`
273 ## prompt user for typical Discourse config file values
275 ask_user_for_config
() {
277 # NOTE: Defaults now come from standalone.yml
279 local changelog
=/tmp
/changelog.
$PPID
280 read_config
"DISCOURSE_SMTP_ADDRESS"
281 local smtp_address
=$read_config_result
282 # NOTE: if there are spaces between emails, this breaks, but a human should be paying attention
283 read_config
"DISCOURSE_DEVELOPER_EMAILS"
284 local developer_emails
=$read_config_result
285 read_config
"DISCOURSE_SMTP_PASSWORD"
286 local smtp_password
=$read_config_result
287 read_config
"DISCOURSE_SMTP_PORT"
288 local smtp_port
=$read_config_result
289 read_config
"DISCOURSE_SMTP_USER_NAME"
290 local smtp_user_name
=$read_config_result
291 if [ "$smtp_password" = "pa$$word" ]
295 read_config
"LETSENCRYPT_ACCOUNT_EMAIL"
296 local letsencrypt_account_email
=$read_config_result
297 if [ $letsencrypt_account_email = "me@example.com" ]
299 local letsencrypt_status
="ENTER to skip"
301 local letsencrypt_status
="Enter 'OFF' to disable."
304 read_config
"DISCOURSE_HOSTNAME"
305 hostname
=$read_config_result
313 while [[ "$config_ok" == "n" ]]
315 if [ ! -z $hostname ]
317 read -p "Hostname for your Discourse? [$hostname]: " new_value
318 if [ ! -z $new_value ]
324 if [ ! -z $developer_emails ]
326 read -p "Email address for admin account(s)? [$developer_emails]: " new_value
327 if [ ! -z $new_value ]
329 developer_emails
=$new_value
333 if [ ! -z $smtp_address ]
335 read -p "SMTP server address? [$smtp_address]: " new_value
336 if [ ! -z $new_value ]
338 smtp_address
=$new_value
342 if [ ! -z $smtp_port ]
344 read -p "SMTP port? [$smtp_port]: " new_value
345 if [ ! -z $new_value ]
352 ## automatically set correct user name based on common mail providers
354 if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
356 smtp_user_name
="SMTP_Injection"
358 if [ "$smtp_address" == "smtp.sendgrid.net" ]
360 smtp_user_name
="apikey"
362 if [ "$smtp_address" == "smtp.mailgun.org" ]
364 smtp_user_name
="postmaster@$hostname"
367 if [ ! -z $smtp_user_name ]
369 read -p "SMTP user name? [$smtp_user_name]: " new_value
370 if [ ! -z $new_value ]
372 smtp_user_name
=$new_value
376 read -p "SMTP password? [$smtp_password]: " new_value
377 if [ ! -z $new_value ]
379 smtp_password
=$new_value
382 if [ ! -z $letsencrypt_account_email ]
384 read -p "Let's Encrypt account email? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
385 if [ ! -z $new_value ]
387 letsencrypt_account_email
=$new_value
388 if [ "${new_value,,}" = "off" ]
390 letsencrypt_status
="ENTER to skip"
392 letsencrypt_status
="Enter 'OFF' to disable."
397 if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
399 check_IP_match
$hostname
402 echo -e "\nDoes this look right?\n"
403 echo "Hostname : $hostname"
404 echo "Email : $developer_emails"
405 echo "SMTP address : $smtp_address"
406 echo "SMTP port : $smtp_port"
407 echo "SMTP username : $smtp_user_name"
408 echo "SMTP password : $smtp_password"
410 if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
412 echo "Let's Encrypt : $letsencrypt_account_email"
417 read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
420 sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $config_file
425 echo "DISCOURSE_HOSTNAME change failed."
429 sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $config_file
434 echo "DISCOURSE_DEVELOPER_EMAILS change failed."
438 sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
443 echo "DISCOURSE_SMTP_ADDRESS change failed."
447 sed -i -e "s/^ #\?DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $config_file
452 echo "DISCOURSE_SMTP_PORT change failed."
456 sed -i -e "s/^ #\?DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
461 echo "DISCOURSE_SMTP_USER_NAME change failed."
465 sed -i -e "s/^ #\?DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: \"${smtp_password/\//\\/}\"/w $changelog" $config_file
470 echo "DISCOURSE_SMTP_PASSWORD change failed."
474 if [ "$letsencrypt_status" = "ENTER to skip" ]
476 local src
='^ #\?- "templates\/web.ssl.template.yml"'
477 local dst
=' #\- "templates\/web.ssl.template.yml"'
478 sed -i -e "s/$src/$dst/w $changelog" $config_file
479 if [ ! -s $changelog ]
482 echo "web.ssl.template.yml NOT DISABLED--Are you using a non-standard template?"
484 local src
='^ #\?- "templates\/web.letsencrypt.ssl.template.yml"'
485 local dst
=' #- "templates\/web.letsencrypt.ssl.template.yml"'
487 sed -i -e "s/$src/$dst/w $changelog" $config_file
488 if [ ! -s $changelog ]
491 echo "web.ssl.template.yml NOT DISABLED--Are you using a non-standard template?"
493 else # enable let's encrypt
494 echo "Let's Encrypt will be enabled for $letsencrypt_account_email"
495 sed -i -e "s/^ #\?LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_file
500 echo "LETSENCRYPT_ACCOUNT_EMAIL change failed."
503 local src
='^ #\?- "templates\/web.ssl.template.yml"'
504 local dst
=' \- "templates\/web.ssl.template.yml"'
505 sed -i -e "s/$src/$dst/w $changelog" $config_file
508 echo "web.ssl.template.yml enabled"
511 echo "web.ssl.template.yml NOT ENABLED--was it on already?"
513 local src
='^ #\?- "templates\/web.letsencrypt.ssl.template.yml"'
514 local dst
=' - "templates\/web.letsencrypt.ssl.template.yml"'
516 sed -i -e "s/$src/$dst/w $changelog" $config_file
519 echo "letsencrypt.ssl.template.yml enabled"
522 echo "letsencrypt.ssl.template.yml NOT ENABLED -- was it on already?"
526 if [ "$update_ok" == "y" ]
528 echo -e "\nConfiguration file at $config_file updated successfully!\n"
530 echo -e "\nUnfortunately, there was an error changing $config_file\n"
536 ## is our config file valid? Does it have the required fields set?
542 for x
in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
543 DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
545 config_line
=`grep "^ $x:" $config_file`
547 local default
="example.com"
551 if [[ $config_line = *"$default"* ]]
553 echo "$x left at incorrect default of example.com"
556 config_val
=`echo $config_line | awk '{print $2}'`
557 if [ -z $config_val ]
559 echo "$x was left blank"
563 echo "$x not present"
568 if [ "$valid_config" != "y" ]; then
569 echo -e "\nSorry, these $config_file settings aren't valid -- can't continue!"
570 echo "If you have unusual requirements, edit $config_file and then: "
571 echo "./launcher bootstrap $app_name"
578 ## template file names
581 template_path
=samples
/standalone.yml
582 config_file
=containers
/$app_name.yml
583 changelog
=/tmp
/changelog
586 ## Check requirements before creating a copy of a config file we won't edit
589 check_and_install_docker
590 check_disk_and_memory
594 ## make a copy of the simple standalone config file
596 if [ -a $config_file ]
598 echo "The configuration file $config_file already exists!"
600 echo ". . . reconfiguring . . ."
603 cp $template_path $config_file
611 ## if we reach this point without exiting, OK to proceed
612 ## rebuild won't fail if there's nothing to rebuild and does the restart
614 sleep 5 # Just a chance to ^C in case they were too fast on the draw
615 time .
/launcher rebuild
$app_name