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
14 ## Do we have enough memory and disk space for Discourse?
16 check_disk_and_memory
() {
18 avail_mem
="$(LANG=C free -m | grep '^Mem:' | awk '{print $2}')"
19 if [ "$avail_mem" -lt 900 ]; then
20 echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
21 echo "to have sufficient memory."
23 echo "Your site may not work properly, or future upgrades of Discourse may not"
24 echo "complete successfully."
28 if [ "$avail_mem" -lt 1800 ]; then
29 total_swap
="$(LANG=C free -m | grep ^Swap: | awk '{print $2}')"
30 if [ "$total_swap" -lt 1000 ]; then
31 echo "WARNING: Discourse requires at least 2GB of swap when running with less "
32 echo "than 2GB of RAM. This system does not appear to have sufficient swap space."
34 echo "Without sufficient swap space, your site may not work properly, and future"
35 echo "upgrades of Discourse may not complete successfully."
37 read -p "ENTER to create a 2GB swapfile now, or Ctrl+C to exit"
40 ## derived from https://meta.discourse.org/t/13880
42 install -o root
-g root
-m 0600 /dev
/null
/swapfile
43 dd if=/dev
/zero of
=/swapfile bs
=1k count
=2048k
46 echo "/swapfile swap swap auto 0 0" |
tee -a /etc
/fstab
47 sysctl
-w vm.swappiness
=10
48 echo vm.swappiness
= 10 |
tee -a /etc
/sysctl.conf
50 total_swap
="$(LANG=C free -m | grep ^Swap: | awk '{print $2}')"
51 if [ "$total_swap" -lt 1000 ]; then
52 echo "Failed to create swap, sorry!"
59 free_disk
="$(df /var | tail -n 1 | awk '{print $4}')"
60 if [ "$free_disk" -lt 5000 ]; then
61 echo "WARNING: Discourse requires at least 5GB free disk space. This system"
62 echo "does not appear to have sufficient disk space."
64 echo "Insufficient disk space may result in problems running your site, and"
65 echo "may not even allow Discourse installation to complete successfully."
67 echo "Please free up some space, or expand your disk, before continuing."
69 echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
70 echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
78 ## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
82 local changelog
=/tmp
/changelog.
$PPID
83 # grab info about total system ram and physical (NOT LOGICAL!) CPU cores
84 avail_mem
="$(LANG=C free -m | grep '^Mem:' | awk '{print $2}')"
85 avail_gb
=$
(( $avail_mem / 950 ))
86 avail_cores
=`cat /proc/cpuinfo | grep "cpu cores" | uniq | awk '{print $4}'`
87 echo "Found ${avail_gb}GB of memory and $avail_cores physical CPU cores"
89 # db_shared_buffers: 128MB for 1GB, 256MB for 2GB, or 256MB * GB, max 4096MB
90 if [ "$avail_gb" -eq "1" ]
94 if [ "$avail_gb" -eq "2" ]
98 db_shared_buffers
=$
(( 256 * $avail_gb ))
101 db_shared_buffers
=$
(( db_shared_buffers
< 4096 ? db_shared_buffers
: 4096 ))
103 sed -i -e "s/^ #db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}MB\"/w $changelog" $config_file
106 echo "setting db_shared_buffers = ${db_shared_buffers}MB"
110 # UNICORN_WORKERS: 2 * GB for 2GB or less, or 2 * CPU, max 8
111 if [ "$avail_gb" -le "2" ]
113 unicorn_workers
=$
(( 2 * $avail_gb ))
115 unicorn_workers
=$
(( 2 * $avail_cores ))
117 unicorn_workers
=$
(( unicorn_workers
< 8 ? unicorn_workers
: 8 ))
119 sed -i -e "s/^ #UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
122 echo "setting UNICORN_WORKERS = ${unicorn_workers}"
130 ## standard http / https ports must not be occupied
135 echo "Ports 80 and 443 are free for use"
140 ## check a port to see if it is already in use
144 local valid
=$
(netstat
-tln |
awk '{print $4}' |
grep ":${1}\$")
146 if [ -n "$valid" ]; then
147 echo "Port ${1} appears to already be in use."
149 echo "If you are trying to run Discourse simultaneously with another web"
150 echo "server like Apache or nginx, you will need to bind to a different port"
152 echo "See https://meta.discourse.org/t/17247"
158 ## prompt user for typical Discourse config file values
160 ask_user_for_config
() {
162 local changelog
=/tmp
/changelog.
$PPID
163 local hostname
="discourse.example.com"
164 local developer_emails
="me@example.com,you@example.com"
165 local smtp_address
="smtp.example.com"
166 local smtp_port
="587"
167 local smtp_user_name
="postmaster@discourse.example.com"
168 local smtp_password
=""
169 local letsencrypt_account_email
="me@example.com"
170 local letsencrypt_status
="ENTER to skip"
178 while [[ "$config_ok" == "n" ]]
180 if [ ! -z $hostname ]
182 read -p "Hostname for your Discourse? [$hostname]: " new_value
183 if [ ! -z $new_value ]
189 if [ ! -z $developer_emails ]
191 read -p "Email address for admin account? [$developer_emails]: " new_value
192 if [ ! -z $new_value ]
194 developer_emails
=$new_value
198 if [ ! -z $smtp_address ]
200 read -p "SMTP server address? [$smtp_address]: " new_value
201 if [ ! -z $new_value ]
203 smtp_address
=$new_value
207 if [ ! -z $smtp_port ]
209 read -p "SMTP port? [$smtp_port]: " new_value
210 if [ ! -z $new_value ]
217 ## automatically set correct user name based on common mail providers
219 if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
221 smtp_user_name
="SMTP_Injection"
223 if [ "$smtp_address" == "smtp.sendgrid.net" ]
225 smtp_user_name
="apikey"
227 if [ "$smtp_address" == "smtp.mailgun.org" ]
229 smtp_user_name
="postmaster@$hostname"
232 if [ ! -z $smtp_user_name ]
234 read -p "SMTP user name? [$smtp_user_name]: " new_value
235 if [ ! -z $new_value ]
237 smtp_user_name
=$new_value
241 read -p "SMTP password? [$smtp_password]: " new_value
242 if [ ! -z $new_value ]
244 smtp_password
=$new_value
247 if [ ! -z $letsencrypt_account_email ]
249 read -p "Let's Encrypt account email? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
250 if [ ! -z $new_value ]
252 letsencrypt_account_email
=$new_value
253 if [ "$new_value" == "off" ]
255 letsencrypt_status
="ENTER to skip"
257 letsencrypt_status
="Enter 'OFF' to disable."
262 echo -e "\nDoes this look right?\n"
263 echo "Hostname : $hostname"
264 echo "Email : $developer_emails"
265 echo "SMTP address : $smtp_address"
266 echo "SMTP port : $smtp_port"
267 echo "SMTP username : $smtp_user_name"
268 echo "SMTP password : $smtp_password"
270 if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
272 echo "Let's Encrypt : $letsencrypt_account_email"
276 read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
279 sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $config_file
284 echo "DISCOURSE_HOSTNAME change failed."
288 sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $config_file
293 echo "DISCOURSE_DEVELOPER_EMAILS change failed."
297 sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
302 echo "DISCOURSE_SMTP_ADDRESS change failed."
306 sed -i -e "s/^ #DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $config_file
311 echo "DISCOURSE_SMTP_PORT change failed."
315 sed -i -e "s/^ #DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
320 echo "DISCOURSE_SMTP_USER_NAME change failed."
324 sed -i -e "s/^ #DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: $smtp_password/w $changelog" $config_file
329 echo "DISCOURSE_SMTP_PASSWORD change failed."
333 if [ "$letsencrypt_status" != "ENTER to skip" ]
335 sed -i -e "s/^ #LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_file
340 echo "LETSENCRYPT_ACCOUNT_EMAIL change failed."
343 local src
='^ #- "templates\/web.ssl.template.yml"'
344 local dst
=' \- "templates\/web.ssl.template.yml"'
345 sed -i -e "s/$src/$dst/w $changelog" $config_file
348 echo "web.ssl.template.yml enabled"
351 echo "web.ssl.template.yml NOT ENABLED--was it on already?"
353 local src
='^ #- "templates\/web.letsencrypt.ssl.template.yml"'
354 local dst
=' - "templates\/web.letsencrypt.ssl.template.yml"'
356 sed -i -e "s/$src/$dst/w $changelog" $config_file
359 echo "letsencrypt.ssl.template.yml enabled"
362 echo "letsencrypt.ssl.template.yml NOT ENABLED -- was it on already?"
366 if [ "$update_ok" == "y" ]
368 echo -e "\nConfiguration file at $config_file updated successfully!\n"
370 echo -e "\nUnfortunately, there was an error changing $config_file\n"
376 ## is our config file valid? Does it have the required fields set?
382 for x
in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
383 DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
385 config_line
=`grep "^ $x:" $config_file`
387 local default
="example.com"
391 if [[ $config_line = *"$default"* ]]
393 echo "$x left at incorrect default of example.com"
396 config_val
=`echo $config_line | awk '{print $2}'`
397 if [ -z $config_val ]
399 echo "$x was left blank"
403 echo "$x not present"
408 if [ "$valid_config" != "y" ]; then
409 echo -e "\nSorry, these $config_file settings aren't valid -- can't continue!"
410 echo "If you have unusual requirements, edit $config_file and then: "
411 echo "./launcher bootstrap $app_name"
418 ## template file names
421 template_path
=samples
/standalone.yml
422 config_file
=containers
/$app_name.yml
423 changelog
=/tmp
/changelog
426 ## Check requirements before creating a copy of a config file we won't edit
429 check_disk_and_memory
433 ## make a copy of the simple standalone config file
435 if [ -a $config_file ]
437 echo "The configuration file $config_file already exists!"
439 echo "If you want to delete your old configuration file and start over:"
440 echo "rm $config_file"
443 cp $template_path $config_file
451 ## if we reach this point without exiting, OK to proceed
453 .
/launcher bootstrap
$app_name && .
/launcher start
$app_name