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 if [ -z $docker_path ]; then
19 read -p "Docker not installed. Enter to install from https://get.docker.com/ or Ctrl+C to exit"
20 curl https
://get.docker.com
/ | sh
22 if [ -z $docker_path ]; then
23 echo Docker
install failed. Quitting.
30 ## Do we have enough memory and disk space for Discourse?
32 check_disk_and_memory
() {
34 avail_mem
=`free -g --si | awk ' /Mem:/ {print $2} '`
35 if [ "$avail_mem" -lt 1 ]; then
36 echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
37 echo "to have sufficient memory."
39 echo "Your site may not work properly, or future upgrades of Discourse may not"
40 echo "complete successfully."
44 if [ "$avail_mem" -lt 2 ]; then
45 total_swap
=`free -g --si | awk ' /Swap:/ {print $2} '`
46 if [ "$total_swap" -lt 2 ]; then
47 echo "WARNING: Discourse requires at least 2GB of swap when running with less "
48 echo "than 2GB of RAM. This system does not appear to have sufficient swap space."
50 echo "Without sufficient swap space, your site may not work properly, and future"
51 echo "upgrades of Discourse may not complete successfully."
53 read -p "ENTER to create a 2GB swapfile now, or Ctrl+C to exit"
56 ## derived from https://meta.discourse.org/t/13880
58 install -o root
-g root
-m 0600 /dev
/null
/swapfile
59 dd if=/dev
/zero of
=/swapfile bs
=1k count
=2048k
62 echo "/swapfile swap swap auto 0 0" |
tee -a /etc
/fstab
63 sysctl
-w vm.swappiness
=10
64 echo vm.swappiness
= 10 |
tee -a /etc
/sysctl.conf
66 total_swap
=`free -g --si | awk ' /Swap:/ {print $2} '`
67 if [ "$total_swap" -lt 2 ]; then
68 echo "Failed to create swap, sorry!"
76 free_disk
="$(df /var | tail -n 1 | awk '{print $4}')"
77 if [ "$free_disk" -lt 5000 ]; then
78 echo "WARNING: Discourse requires at least 5GB free disk space. This system"
79 echo "does not appear to have sufficient disk space."
81 echo "Insufficient disk space may result in problems running your site, and"
82 echo "may not even allow Discourse installation to complete successfully."
84 echo "Please free up some space, or expand your disk, before continuing."
86 echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
87 echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
95 ## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
99 local changelog
=/tmp
/changelog.
$PPID
100 # grab info about total system ram and physical (NOT LOGICAL!) CPU cores
101 avail_gb
="$(LANG=C free -g --si | grep '^Mem:' | awk '{print $2}')"
102 avail_cores
=`cat /proc/cpuinfo | grep "cpu cores" | uniq | awk '{print $4}'`
103 echo "Found ${avail_gb}GB of memory and $avail_cores physical CPU cores"
105 # db_shared_buffers: 128MB for 1GB, 256MB for 2GB, or 256MB * GB, max 4096MB
106 if [ "$avail_gb" -eq "1" ]
108 db_shared_buffers
=128
110 if [ "$avail_gb" -eq "2" ]
112 db_shared_buffers
=256
114 db_shared_buffers
=$
(( 256 * $avail_gb ))
117 db_shared_buffers
=$
(( db_shared_buffers
< 4096 ? db_shared_buffers
: 4096 ))
119 sed -i -e "s/^ #db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}MB\"/w $changelog" $config_file
122 echo "setting db_shared_buffers = ${db_shared_buffers}MB"
126 # UNICORN_WORKERS: 2 * GB for 2GB or less, or 2 * CPU, max 8
127 if [ "$avail_gb" -le "2" ]
129 unicorn_workers
=$
(( 2 * $avail_gb ))
131 unicorn_workers
=$
(( 2 * $avail_cores ))
133 unicorn_workers
=$
(( unicorn_workers
< 8 ? unicorn_workers
: 8 ))
135 sed -i -e "s/^ #UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
138 echo "setting UNICORN_WORKERS = ${unicorn_workers}"
146 ## standard http / https ports must not be occupied
151 echo "Ports 80 and 443 are free for use"
156 ## check a port to see if it is already in use
160 local valid
=$
(netstat
-tln |
awk '{print $4}' |
grep ":${1}\$")
162 if [ -n "$valid" ]; then
163 echo "Port ${1} appears to already be in use."
165 echo "If you are trying to run Discourse simultaneously with another web"
166 echo "server like Apache or nginx, you will need to bind to a different port"
168 echo "See https://meta.discourse.org/t/17247"
174 ## prompt user for typical Discourse config file values
176 ask_user_for_config
() {
178 local changelog
=/tmp
/changelog.
$PPID
179 local hostname
="discourse.example.com"
180 local developer_emails
="me@example.com,you@example.com"
181 local smtp_address
="smtp.example.com"
182 local smtp_port
="587"
183 local smtp_user_name
="postmaster@discourse.example.com"
184 local smtp_password
=""
185 local letsencrypt_account_email
="me@example.com"
186 local letsencrypt_status
="ENTER to skip"
194 while [[ "$config_ok" == "n" ]]
196 if [ ! -z $hostname ]
198 read -p "Hostname for your Discourse? [$hostname]: " new_value
199 if [ ! -z $new_value ]
205 if [ ! -z $developer_emails ]
207 read -p "Email address for admin account? [$developer_emails]: " new_value
208 if [ ! -z $new_value ]
210 developer_emails
=$new_value
214 if [ ! -z $smtp_address ]
216 read -p "SMTP server address? [$smtp_address]: " new_value
217 if [ ! -z $new_value ]
219 smtp_address
=$new_value
223 if [ ! -z $smtp_port ]
225 read -p "SMTP port? [$smtp_port]: " new_value
226 if [ ! -z $new_value ]
233 ## automatically set correct user name based on common mail providers
235 if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
237 smtp_user_name
="SMTP_Injection"
239 if [ "$smtp_address" == "smtp.sendgrid.net" ]
241 smtp_user_name
="apikey"
243 if [ "$smtp_address" == "smtp.mailgun.org" ]
245 smtp_user_name
="postmaster@$hostname"
248 if [ ! -z $smtp_user_name ]
250 read -p "SMTP user name? [$smtp_user_name]: " new_value
251 if [ ! -z $new_value ]
253 smtp_user_name
=$new_value
257 read -p "SMTP password? [$smtp_password]: " new_value
258 if [ ! -z $new_value ]
260 smtp_password
=$new_value
263 if [ ! -z $letsencrypt_account_email ]
265 read -p "Let's Encrypt account email? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
266 if [ ! -z $new_value ]
268 letsencrypt_account_email
=$new_value
269 if [ "$new_value" == "off" ]
271 letsencrypt_status
="ENTER to skip"
273 letsencrypt_status
="Enter 'OFF' to disable."
278 echo -e "\nDoes this look right?\n"
279 echo "Hostname : $hostname"
280 echo "Email : $developer_emails"
281 echo "SMTP address : $smtp_address"
282 echo "SMTP port : $smtp_port"
283 echo "SMTP username : $smtp_user_name"
284 echo "SMTP password : $smtp_password"
286 if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
288 echo "Let's Encrypt : $letsencrypt_account_email"
292 read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
295 sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $config_file
300 echo "DISCOURSE_HOSTNAME change failed."
304 sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $config_file
309 echo "DISCOURSE_DEVELOPER_EMAILS change failed."
313 sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
318 echo "DISCOURSE_SMTP_ADDRESS change failed."
322 sed -i -e "s/^ #DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $config_file
327 echo "DISCOURSE_SMTP_PORT change failed."
331 sed -i -e "s/^ #DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
336 echo "DISCOURSE_SMTP_USER_NAME change failed."
340 sed -i -e "s/^ #DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: \"${smtp_password/\//\\/}\"/w $changelog" $config_file
345 echo "DISCOURSE_SMTP_PASSWORD change failed."
349 if [ "$letsencrypt_status" != "ENTER to skip" ]
351 sed -i -e "s/^ #LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_file
356 echo "LETSENCRYPT_ACCOUNT_EMAIL change failed."
359 local src
='^ #- "templates\/web.ssl.template.yml"'
360 local dst
=' \- "templates\/web.ssl.template.yml"'
361 sed -i -e "s/$src/$dst/w $changelog" $config_file
364 echo "web.ssl.template.yml enabled"
367 echo "web.ssl.template.yml NOT ENABLED--was it on already?"
369 local src
='^ #- "templates\/web.letsencrypt.ssl.template.yml"'
370 local dst
=' - "templates\/web.letsencrypt.ssl.template.yml"'
372 sed -i -e "s/$src/$dst/w $changelog" $config_file
375 echo "letsencrypt.ssl.template.yml enabled"
378 echo "letsencrypt.ssl.template.yml NOT ENABLED -- was it on already?"
382 if [ "$update_ok" == "y" ]
384 echo -e "\nConfiguration file at $config_file updated successfully!\n"
386 echo -e "\nUnfortunately, there was an error changing $config_file\n"
392 ## is our config file valid? Does it have the required fields set?
398 for x
in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
399 DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
401 config_line
=`grep "^ $x:" $config_file`
403 local default
="example.com"
407 if [[ $config_line = *"$default"* ]]
409 echo "$x left at incorrect default of example.com"
412 config_val
=`echo $config_line | awk '{print $2}'`
413 if [ -z $config_val ]
415 echo "$x was left blank"
419 echo "$x not present"
424 if [ "$valid_config" != "y" ]; then
425 echo -e "\nSorry, these $config_file settings aren't valid -- can't continue!"
426 echo "If you have unusual requirements, edit $config_file and then: "
427 echo "./launcher bootstrap $app_name"
434 ## template file names
437 template_path
=samples
/standalone.yml
438 config_file
=containers
/$app_name.yml
439 changelog
=/tmp
/changelog
442 ## Check requirements before creating a copy of a config file we won't edit
445 check_and_install_docker
446 check_disk_and_memory
450 ## make a copy of the simple standalone config file
452 if [ -a $config_file ]
454 echo "The configuration file $config_file already exists!"
456 echo "If you want to delete your old configuration file and start over:"
457 echo "rm $config_file"
460 cp $template_path $config_file
468 ## if we reach this point without exiting, OK to proceed
470 .
/launcher bootstrap
$app_name && .
/launcher start
$app_name