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
17 check_and_install_docker
() {
18 docker_path
=`which docker.io || which docker`
19 if [ -z $docker_path ]; then
20 read -p "Docker not installed. Enter to install from https://get.docker.com/ or Ctrl+C to exit"
21 curl https
://get.docker.com
/ | sh
23 docker_path
=`which docker.io || which docker`
24 if [ -z $docker_path ]; then
25 echo Docker
install failed. Quitting.
31 ## What are we running on
38 ## OS X available memory
41 echo `top -l 1 | awk '/PhysMem:/ {print $2}' | sed s/G//`
45 ## Linux available memory
47 check_linux_memory
() {
48 echo `free -g --si | awk ' /Mem:/ {print $2} '`
52 ## Do we have enough memory and disk space for Discourse?
54 check_disk_and_memory
() {
58 if [ $os_type == "Darwin" ]; then
59 avail_mem
=$
(check_osx_memory
)
61 avail_mem
=$
(check_linux_memory
)
64 if [ "$avail_mem" -lt 1 ]; then
65 echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
66 echo "to have sufficient memory."
68 echo "Your site may not work properly, or future upgrades of Discourse may not"
69 echo "complete successfully."
73 if [ "$avail_mem" -le 2 ]; then
74 total_swap
=`free -g --si | awk ' /Swap:/ {print $2} '`
75 if [ "$total_swap" -lt 2 ]; then
76 echo "WARNING: Discourse requires at least 2GB of swap when running with 2GB of RAM"
77 echo "or less. This system does not appear to have sufficient swap space."
79 echo "Without sufficient swap space, your site may not work properly, and future"
80 echo "upgrades of Discourse may not complete successfully."
82 read -p "ENTER to create a 2GB swapfile now, or Ctrl+C to exit"
85 ## derived from https://meta.discourse.org/t/13880
87 install -o root
-g root
-m 0600 /dev
/null
/swapfile
88 dd if=/dev
/zero of
=/swapfile bs
=1k count
=2048k
91 echo "/swapfile swap swap auto 0 0" |
tee -a /etc
/fstab
92 sysctl
-w vm.swappiness
=10
93 echo vm.swappiness
= 10 |
tee -a /etc
/sysctl.conf
95 total_swap
=`free -g --si | awk ' /Swap:/ {print $2} '`
96 if [ "$total_swap" -lt 2 ]; then
97 echo "Failed to create swap, sorry!"
105 free_disk
="$(df /var | tail -n 1 | awk '{print $4}')"
106 if [ "$free_disk" -lt 5000 ]; then
107 echo "WARNING: Discourse requires at least 5GB free disk space. This system"
108 echo "does not appear to have sufficient disk space."
110 echo "Insufficient disk space may result in problems running your site, and"
111 echo "may not even allow Discourse installation to complete successfully."
113 echo "Please free up some space, or expand your disk, before continuing."
115 echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
116 echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
124 ## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
126 scale_ram_and_cpu
() {
128 local changelog
=/tmp
/changelog.
$PPID
129 # grab info about total system ram and physical (NOT LOGICAL!) CPU cores
133 if [ $os_type == "Darwin" ]; then
134 avail_gb
=$
(check_osx_memory
)
135 avail_cores
=`sysctl hw.ncpu | awk '/hw.ncpu:/ {print $2}'`
137 avail_gb
=$
(check_linux_memory
)
138 avail_cores
=$
((`awk '/cpu cores/ {print $4;exit}' /proc/cpuinfo`*`sort /proc/cpuinfo | uniq | grep -c "physical id"`))
140 echo "Found ${avail_gb}GB of memory and $avail_cores physical CPU cores"
142 # db_shared_buffers: 128MB for 1GB, 256MB for 2GB, or 256MB * GB, max 4096MB
143 if [ "$avail_gb" -eq "1" ]
145 db_shared_buffers
=128
147 if [ "$avail_gb" -eq "2" ]
149 db_shared_buffers
=256
151 db_shared_buffers
=$
(( 256 * $avail_gb ))
154 db_shared_buffers
=$
(( db_shared_buffers
< 4096 ? db_shared_buffers
: 4096 ))
156 sed -i -e "s/^ #db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}MB\"/w $changelog" $config_file
159 echo "setting db_shared_buffers = ${db_shared_buffers}MB"
163 # UNICORN_WORKERS: 2 * GB for 2GB or less, or 2 * CPU, max 8
164 if [ "$avail_gb" -le "2" ]
166 unicorn_workers
=$
(( 2 * $avail_gb ))
168 unicorn_workers
=$
(( 2 * $avail_cores ))
170 unicorn_workers
=$
(( unicorn_workers
< 8 ? unicorn_workers
: 8 ))
172 sed -i -e "s/^ #UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
175 echo "setting UNICORN_WORKERS = ${unicorn_workers}"
183 ## standard http / https ports must not be occupied
188 echo "Ports 80 and 443 are free for use"
193 ## check a port to see if it is already in use
197 local valid
=$
(netstat
-tln |
awk '{print $4}' |
grep ":${1}\$")
199 if [ -n "$valid" ]; then
200 echo "Port ${1} appears to already be in use."
202 echo "If you are trying to run Discourse simultaneously with another web"
203 echo "server like Apache or nginx, you will need to bind to a different port"
205 echo "See https://meta.discourse.org/t/17247"
211 ## prompt user for typical Discourse config file values
213 ask_user_for_config
() {
215 local changelog
=/tmp
/changelog.
$PPID
216 local hostname
="discourse.example.com"
217 local developer_emails
="me@example.com,you@example.com"
218 local smtp_address
="smtp.example.com"
219 local smtp_port
="587"
220 local smtp_user_name
="postmaster@discourse.example.com"
221 local smtp_password
=""
222 local letsencrypt_account_email
="me@example.com"
223 local letsencrypt_status
="ENTER to skip"
231 while [[ "$config_ok" == "n" ]]
233 if [ ! -z $hostname ]
235 read -p "Hostname for your Discourse? [$hostname]: " new_value
236 if [ ! -z $new_value ]
242 if [ ! -z $developer_emails ]
244 read -p "Email address for admin account? [$developer_emails]: " new_value
245 if [ ! -z $new_value ]
247 developer_emails
=$new_value
251 if [ ! -z $smtp_address ]
253 read -p "SMTP server address? [$smtp_address]: " new_value
254 if [ ! -z $new_value ]
256 smtp_address
=$new_value
260 if [ ! -z $smtp_port ]
262 read -p "SMTP port? [$smtp_port]: " new_value
263 if [ ! -z $new_value ]
270 ## automatically set correct user name based on common mail providers
272 if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
274 smtp_user_name
="SMTP_Injection"
276 if [ "$smtp_address" == "smtp.sendgrid.net" ]
278 smtp_user_name
="apikey"
280 if [ "$smtp_address" == "smtp.mailgun.org" ]
282 smtp_user_name
="postmaster@$hostname"
285 if [ ! -z $smtp_user_name ]
287 read -p "SMTP user name? [$smtp_user_name]: " new_value
288 if [ ! -z $new_value ]
290 smtp_user_name
=$new_value
294 read -p "SMTP password? [$smtp_password]: " new_value
295 if [ ! -z $new_value ]
297 smtp_password
=$new_value
300 if [ ! -z $letsencrypt_account_email ]
302 read -p "Let's Encrypt account email? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
303 if [ ! -z $new_value ]
305 letsencrypt_account_email
=$new_value
306 if [ "$new_value" == "off" ]
308 letsencrypt_status
="ENTER to skip"
310 letsencrypt_status
="Enter 'OFF' to disable."
315 echo -e "\nDoes this look right?\n"
316 echo "Hostname : $hostname"
317 echo "Email : $developer_emails"
318 echo "SMTP address : $smtp_address"
319 echo "SMTP port : $smtp_port"
320 echo "SMTP username : $smtp_user_name"
321 echo "SMTP password : $smtp_password"
323 if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
325 echo "Let's Encrypt : $letsencrypt_account_email"
329 read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
332 sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $config_file
337 echo "DISCOURSE_HOSTNAME change failed."
341 sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $config_file
346 echo "DISCOURSE_DEVELOPER_EMAILS change failed."
350 sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
355 echo "DISCOURSE_SMTP_ADDRESS change failed."
359 sed -i -e "s/^ #DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $config_file
364 echo "DISCOURSE_SMTP_PORT change failed."
368 sed -i -e "s/^ #DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
373 echo "DISCOURSE_SMTP_USER_NAME change failed."
377 sed -i -e "s/^ #DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: \"${smtp_password/\//\\/}\"/w $changelog" $config_file
382 echo "DISCOURSE_SMTP_PASSWORD change failed."
386 if [ "$letsencrypt_status" != "ENTER to skip" ]
388 sed -i -e "s/^ #LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_file
393 echo "LETSENCRYPT_ACCOUNT_EMAIL change failed."
396 local src
='^ #- "templates\/web.ssl.template.yml"'
397 local dst
=' \- "templates\/web.ssl.template.yml"'
398 sed -i -e "s/$src/$dst/w $changelog" $config_file
401 echo "web.ssl.template.yml enabled"
404 echo "web.ssl.template.yml NOT ENABLED--was it on already?"
406 local src
='^ #- "templates\/web.letsencrypt.ssl.template.yml"'
407 local dst
=' - "templates\/web.letsencrypt.ssl.template.yml"'
409 sed -i -e "s/$src/$dst/w $changelog" $config_file
412 echo "letsencrypt.ssl.template.yml enabled"
415 echo "letsencrypt.ssl.template.yml NOT ENABLED -- was it on already?"
419 if [ "$update_ok" == "y" ]
421 echo -e "\nConfiguration file at $config_file updated successfully!\n"
423 echo -e "\nUnfortunately, there was an error changing $config_file\n"
429 ## is our config file valid? Does it have the required fields set?
435 for x
in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
436 DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
438 config_line
=`grep "^ $x:" $config_file`
440 local default
="example.com"
444 if [[ $config_line = *"$default"* ]]
446 echo "$x left at incorrect default of example.com"
449 config_val
=`echo $config_line | awk '{print $2}'`
450 if [ -z $config_val ]
452 echo "$x was left blank"
456 echo "$x not present"
461 if [ "$valid_config" != "y" ]; then
462 echo -e "\nSorry, these $config_file settings aren't valid -- can't continue!"
463 echo "If you have unusual requirements, edit $config_file and then: "
464 echo "./launcher bootstrap $app_name"
471 ## template file names
474 template_path
=samples
/standalone.yml
475 config_file
=containers
/$app_name.yml
476 changelog
=/tmp
/changelog
479 ## Check requirements before creating a copy of a config file we won't edit
482 check_and_install_docker
483 check_disk_and_memory
487 ## make a copy of the simple standalone config file
489 if [ -a $config_file ]
491 echo "The configuration file $config_file already exists!"
493 echo "If you want to delete your old configuration file and start over:"
494 echo "rm $config_file"
497 cp $template_path $config_file
505 ## if we reach this point without exiting, OK to proceed
507 .
/launcher bootstrap
$app_name && .
/launcher start
$app_name