Fix OS X not knowing the free bash command
[discourse_docker.git] / discourse-setup
CommitLineData
c2d3ee4a
JA
1#!/bin/bash
2
ebdd72f3
JA
3##
4## Make sure only root can run our script
5##
6check_root() {
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
9 exit 1
10 fi
11}
12
18602189 13
c87c4b0a 14##
18602189
JP
15## Do we have docker?
16##
17check_and_install_docker () {
7cf781fc 18 docker_path=`which docker.io || which docker`
18602189
JP
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"
c87c4b0a 21 curl https://get.docker.com/ | sh
18602189 22 fi
7cf781fc 23 docker_path=`which docker.io || which docker`
18602189
JP
24 if [ -z $docker_path ]; then
25 echo Docker install failed. Quitting.
26 exit
27 fi
28}
29
69dcbef5
SG
30##
31## What are we running on
32##
33check_OS() {
34 echo `uname -s`
35}
36
c87c4b0a 37
c2d3ee4a
JA
38##
39## Do we have enough memory and disk space for Discourse?
40##
41check_disk_and_memory() {
c87c4b0a 42
69dcbef5
SG
43 os_type=$(check_OS)
44 avail_mem=0
45 if [ $os_type == "Darwin" ]; then
46 avail_mem=`top -l 1 | awk '/PhysMem:/ {print $2}' | sed s/G//`
47 else
48 avail_mem=`free -g --si | awk ' /Mem:/ {print $2} '`
49 fi
50
c6374a12 51 if [ "$avail_mem" -lt 1 ]; then
51890305
JA
52 echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
53 echo "to have sufficient memory."
c2d3ee4a 54 echo
51890305
JA
55 echo "Your site may not work properly, or future upgrades of Discourse may not"
56 echo "complete successfully."
c87c4b0a 57 exit 1
cdd99376 58 fi
c87c4b0a 59
f7bb85e6 60 if [ "$avail_mem" -le 2 ]; then
c6374a12
JP
61 total_swap=`free -g --si | awk ' /Swap:/ {print $2} '`
62 if [ "$total_swap" -lt 2 ]; then
bd7e6e26
JP
63 echo "WARNING: Discourse requires at least 2GB of swap when running with 2GB of RAM"
64 echo "or less. This system does not appear to have sufficient swap space."
c2d3ee4a 65 echo
8f70d450 66 echo "Without sufficient swap space, your site may not work properly, and future"
51890305 67 echo "upgrades of Discourse may not complete successfully."
c2d3ee4a 68 echo
ac1a2d67 69 read -p "ENTER to create a 2GB swapfile now, or Ctrl+C to exit"
c87c4b0a 70
8f70d450
JA
71 ##
72 ## derived from https://meta.discourse.org/t/13880
c87c4b0a 73 ##
8f70d450
JA
74 install -o root -g root -m 0600 /dev/null /swapfile
75 dd if=/dev/zero of=/swapfile bs=1k count=2048k
76 mkswap /swapfile
77 swapon /swapfile
7c2777f9 78 echo "/swapfile swap swap auto 0 0" | tee -a /etc/fstab
7802f679 79 sysctl -w vm.swappiness=10
7c2777f9 80 echo vm.swappiness = 10 | tee -a /etc/sysctl.conf
8f70d450 81
c6374a12
JP
82 total_swap=`free -g --si | awk ' /Swap:/ {print $2} '`
83 if [ "$total_swap" -lt 2 ]; then
8f70d450
JA
84 echo "Failed to create swap, sorry!"
85 exit 1
86 fi
c87c4b0a 87
c2d3ee4a
JA
88 fi
89 fi
90
c6374a12 91
c2d3ee4a
JA
92 free_disk="$(df /var | tail -n 1 | awk '{print $4}')"
93 if [ "$free_disk" -lt 5000 ]; then
51890305
JA
94 echo "WARNING: Discourse requires at least 5GB free disk space. This system"
95 echo "does not appear to have sufficient disk space."
c2d3ee4a 96 echo
51890305
JA
97 echo "Insufficient disk space may result in problems running your site, and"
98 echo "may not even allow Discourse installation to complete successfully."
c2d3ee4a
JA
99 echo
100 echo "Please free up some space, or expand your disk, before continuing."
101 echo
51890305
JA
102 echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
103 echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
c2d3ee4a
JA
104 exit 1
105 fi
106
c2d3ee4a
JA
107}
108
109
110##
111## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
112##
113scale_ram_and_cpu() {
114
642b870f 115 local changelog=/tmp/changelog.$PPID
c2d3ee4a 116 # grab info about total system ram and physical (NOT LOGICAL!) CPU cores
c6374a12 117 avail_gb="$(LANG=C free -g --si | grep '^Mem:' | awk '{print $2}')"
c2d3ee4a
JA
118 avail_cores=`cat /proc/cpuinfo | grep "cpu cores" | uniq | awk '{print $4}'`
119 echo "Found ${avail_gb}GB of memory and $avail_cores physical CPU cores"
120
121 # db_shared_buffers: 128MB for 1GB, 256MB for 2GB, or 256MB * GB, max 4096MB
122 if [ "$avail_gb" -eq "1" ]
123 then
124 db_shared_buffers=128
125 else
126 if [ "$avail_gb" -eq "2" ]
127 then
128 db_shared_buffers=256
129 else
130 db_shared_buffers=$(( 256 * $avail_gb ))
131 fi
132 fi
133 db_shared_buffers=$(( db_shared_buffers < 4096 ? db_shared_buffers : 4096 ))
134
135 sed -i -e "s/^ #db_shared_buffers:.*/ db_shared_buffers: \"${db_shared_buffers}MB\"/w $changelog" $config_file
136 if [ -s $changelog ]
137 then
138 echo "setting db_shared_buffers = ${db_shared_buffers}MB"
139 rm $changelog
140 fi
141
c2d3ee4a
JA
142 # UNICORN_WORKERS: 2 * GB for 2GB or less, or 2 * CPU, max 8
143 if [ "$avail_gb" -le "2" ]
144 then
145 unicorn_workers=$(( 2 * $avail_gb ))
146 else
147 unicorn_workers=$(( 2 * $avail_cores ))
148 fi
149 unicorn_workers=$(( unicorn_workers < 8 ? unicorn_workers : 8 ))
150
151 sed -i -e "s/^ #UNICORN_WORKERS:.*/ UNICORN_WORKERS: ${unicorn_workers}/w $changelog" $config_file
152 if [ -s $changelog ]
153 then
154 echo "setting UNICORN_WORKERS = ${unicorn_workers}"
155 rm $changelog
156 fi
157
158}
159
160
c87c4b0a 161##
c2d3ee4a
JA
162## standard http / https ports must not be occupied
163##
164check_ports() {
165 check_port "80"
166 check_port "443"
167 echo "Ports 80 and 443 are free for use"
168}
169
170
171##
172## check a port to see if it is already in use
173##
174check_port() {
c87c4b0a 175
c2d3ee4a
JA
176 local valid=$(netstat -tln | awk '{print $4}' | grep ":${1}\$")
177
178 if [ -n "$valid" ]; then
179 echo "Port ${1} appears to already be in use."
180 echo
51890305
JA
181 echo "If you are trying to run Discourse simultaneously with another web"
182 echo "server like Apache or nginx, you will need to bind to a different port"
c87c4b0a 183 echo
51890305 184 echo "See https://meta.discourse.org/t/17247"
c2d3ee4a
JA
185 exit 1
186 fi
187}
188
189##
190## prompt user for typical Discourse config file values
191##
4b1b25e3 192ask_user_for_config() {
c87c4b0a 193
642b870f 194 local changelog=/tmp/changelog.$PPID
c2d3ee4a 195 local hostname="discourse.example.com"
642b870f 196 local developer_emails="me@example.com,you@example.com"
c2d3ee4a 197 local smtp_address="smtp.example.com"
7c2777f9 198 local smtp_port="587"
c87c4b0a 199 local smtp_user_name="postmaster@discourse.example.com"
c2d3ee4a
JA
200 local smtp_password=""
201 local letsencrypt_account_email="me@example.com"
202 local letsencrypt_status="ENTER to skip"
203
204 local new_value=""
205 local config_ok="n"
206 local update_ok="y"
c87c4b0a 207
c2d3ee4a
JA
208 echo ""
209
210 while [[ "$config_ok" == "n" ]]
211 do
212 if [ ! -z $hostname ]
213 then
214 read -p "Hostname for your Discourse? [$hostname]: " new_value
215 if [ ! -z $new_value ]
216 then
217 hostname=$new_value
218 fi
219 fi
c87c4b0a 220
c2d3ee4a
JA
221 if [ ! -z $developer_emails ]
222 then
223 read -p "Email address for admin account? [$developer_emails]: " new_value
224 if [ ! -z $new_value ]
225 then
226 developer_emails=$new_value
227 fi
228 fi
c87c4b0a 229
c2d3ee4a
JA
230 if [ ! -z $smtp_address ]
231 then
232 read -p "SMTP server address? [$smtp_address]: " new_value
233 if [ ! -z $new_value ]
234 then
235 smtp_address=$new_value
236 fi
237 fi
c87c4b0a 238
7c2777f9 239 if [ ! -z $smtp_port ]
c2d3ee4a 240 then
7c2777f9
JA
241 read -p "SMTP port? [$smtp_port]: " new_value
242 if [ ! -z $new_value ]
243 then
244 smtp_port=$new_value
245 fi
c2d3ee4a 246 fi
c87c4b0a 247
7c2777f9
JA
248 ##
249 ## automatically set correct user name based on common mail providers
250 ##
251 if [ "$smtp_address" == "smtp.sparkpostmail.com" ]
252 then
253 smtp_user_name="SMTP_Injection"
c87c4b0a 254 fi
c2d3ee4a
JA
255 if [ "$smtp_address" == "smtp.sendgrid.net" ]
256 then
257 smtp_user_name="apikey"
258 fi
7c2777f9
JA
259 if [ "$smtp_address" == "smtp.mailgun.org" ]
260 then
261 smtp_user_name="postmaster@$hostname"
262 fi
c87c4b0a 263
c2d3ee4a
JA
264 if [ ! -z $smtp_user_name ]
265 then
266 read -p "SMTP user name? [$smtp_user_name]: " new_value
267 if [ ! -z $new_value ]
268 then
269 smtp_user_name=$new_value
270 fi
271 fi
c87c4b0a 272
c2d3ee4a
JA
273 read -p "SMTP password? [$smtp_password]: " new_value
274 if [ ! -z $new_value ]
275 then
276 smtp_password=$new_value
277 fi
c87c4b0a 278
c2d3ee4a
JA
279 if [ ! -z $letsencrypt_account_email ]
280 then
281 read -p "Let's Encrypt account email? ($letsencrypt_status) [$letsencrypt_account_email]: " new_value
282 if [ ! -z $new_value ]
283 then
284 letsencrypt_account_email=$new_value
285 if [ "$new_value" == "off" ]
286 then
287 letsencrypt_status="ENTER to skip"
288 else
289 letsencrypt_status="Enter 'OFF' to disable."
290 fi
291 fi
292 fi
293
51890305 294 echo -e "\nDoes this look right?\n"
c2d3ee4a
JA
295 echo "Hostname : $hostname"
296 echo "Email : $developer_emails"
297 echo "SMTP address : $smtp_address"
7c2777f9 298 echo "SMTP port : $smtp_port"
c2d3ee4a
JA
299 echo "SMTP username : $smtp_user_name"
300 echo "SMTP password : $smtp_password"
c87c4b0a 301
c2d3ee4a
JA
302 if [ "$letsencrypt_status" == "Enter 'OFF' to disable." ]
303 then
304 echo "Let's Encrypt : $letsencrypt_account_email"
305 fi
c87c4b0a 306
c2d3ee4a 307 echo ""
ac1a2d67 308 read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
c2d3ee4a
JA
309 done
310
013b5931 311 sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $config_file
c2d3ee4a
JA
312 if [ -s $changelog ]
313 then
314 rm $changelog
315 else
316 echo "DISCOURSE_HOSTNAME change failed."
317 update_ok="n"
318 fi
319
320 sed -i -e "s/^ DISCOURSE_DEVELOPER_EMAILS:.*/ DISCOURSE_DEVELOPER_EMAILS: \'$developer_emails\'/w $changelog" $config_file
321 if [ -s $changelog ]
322 then
323 rm $changelog
324 else
325 echo "DISCOURSE_DEVELOPER_EMAILS change failed."
326 update_ok="n"
327 fi
328
013b5931 329 sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
c2d3ee4a
JA
330 if [ -s $changelog ]
331 then
332 rm $changelog
333 else
334 echo "DISCOURSE_SMTP_ADDRESS change failed."
335 update_ok="n"
336 fi
337
7c2777f9
JA
338 sed -i -e "s/^ #DISCOURSE_SMTP_PORT:.*/ DISCOURSE_SMTP_PORT: $smtp_port/w $changelog" $config_file
339 if [ -s $changelog ]
340 then
341 rm $changelog
342 else
343 echo "DISCOURSE_SMTP_PORT change failed."
344 update_ok="n"
345 fi
346
013b5931 347 sed -i -e "s/^ #DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
c2d3ee4a
JA
348 if [ -s $changelog ]
349 then
350 rm $changelog
351 else
352 echo "DISCOURSE_SMTP_USER_NAME change failed."
353 update_ok="n"
354 fi
355
63b6095f 356 sed -i -e "s/^ #DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: \"${smtp_password/\//\\/}\"/w $changelog" $config_file
c2d3ee4a
JA
357 if [ -s $changelog ]
358 then
359 rm $changelog
360 else
361 echo "DISCOURSE_SMTP_PASSWORD change failed."
362 update_ok="n"
363 fi
364
365 if [ "$letsencrypt_status" != "ENTER to skip" ]
366 then
642b870f 367 sed -i -e "s/^ #LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_file
c2d3ee4a
JA
368 if [ -s $changelog ]
369 then
370 rm $changelog
371 else
372 echo "LETSENCRYPT_ACCOUNT_EMAIL change failed."
373 update_ok="n"
374 fi
375 local src='^ #- "templates\/web.ssl.template.yml"'
376 local dst=' \- "templates\/web.ssl.template.yml"'
377 sed -i -e "s/$src/$dst/w $changelog" $config_file
378 if [ -s $changelog ]
379 then
642b870f 380 echo "web.ssl.template.yml enabled"
c2d3ee4a
JA
381 else
382 update_ok="n"
383 echo "web.ssl.template.yml NOT ENABLED--was it on already?"
384 fi
385 local src='^ #- "templates\/web.letsencrypt.ssl.template.yml"'
386 local dst=' - "templates\/web.letsencrypt.ssl.template.yml"'
387
388 sed -i -e "s/$src/$dst/w $changelog" $config_file
389 if [ -s $changelog ]
390 then
391 echo "letsencrypt.ssl.template.yml enabled"
392 else
393 update_ok="n"
394 echo "letsencrypt.ssl.template.yml NOT ENABLED -- was it on already?"
395 fi
c87c4b0a 396 fi
c2d3ee4a
JA
397
398 if [ "$update_ok" == "y" ]
399 then
400 echo -e "\nConfiguration file at $config_file updated successfully!\n"
401 else
402 echo -e "\nUnfortunately, there was an error changing $config_file\n"
403 exit 1
404 fi
405}
406
407##
408## is our config file valid? Does it have the required fields set?
409##
4b1b25e3 410validate_config() {
c2d3ee4a
JA
411
412 valid_config="y"
c87c4b0a 413
c2d3ee4a
JA
414 for x in DISCOURSE_SMTP_ADDRESS DISCOURSE_SMTP_USER_NAME DISCOURSE_SMTP_PASSWORD \
415 DISCOURSE_DEVELOPER_EMAILS DISCOURSE_HOSTNAME
416 do
c87c4b0a 417 config_line=`grep "^ $x:" $config_file`
c2d3ee4a
JA
418 local result=$?
419 local default="example.com"
420
421 if (( result == 0 ))
422 then
423 if [[ $config_line = *"$default"* ]]
424 then
425 echo "$x left at incorrect default of example.com"
426 valid_config="n"
427 fi
428 config_val=`echo $config_line | awk '{print $2}'`
429 if [ -z $config_val ]
430 then
431 echo "$x was left blank"
432 valid_config="n"
433 fi
434 else
435 echo "$x not present"
436 valid_config="n"
437 fi
438 done
c87c4b0a 439
c2d3ee4a
JA
440 if [ "$valid_config" != "y" ]; then
441 echo -e "\nSorry, these $config_file settings aren't valid -- can't continue!"
d8613c71
JA
442 echo "If you have unusual requirements, edit $config_file and then: "
443 echo "./launcher bootstrap $app_name"
c2d3ee4a
JA
444 exit 1
445 fi
446}
447
448
449##
450## template file names
451##
452app_name=app
453template_path=samples/standalone.yml
454config_file=containers/$app_name.yml
455changelog=/tmp/changelog
456
4b1b25e3
JA
457##
458## Check requirements before creating a copy of a config file we won't edit
459##
ebdd72f3 460check_root
18602189 461check_and_install_docker
642b870f
JP
462check_disk_and_memory
463check_ports
464
4b1b25e3 465##
c2d3ee4a 466## make a copy of the simple standalone config file
4b1b25e3 467##
c2d3ee4a
JA
468if [ -a $config_file ]
469then
470 echo "The configuration file $config_file already exists!"
471 echo ""
472 echo "If you want to delete your old configuration file and start over:"
473 echo "rm $config_file"
474 exit 1
475else
476 cp $template_path $config_file
477fi
478
c2d3ee4a 479scale_ram_and_cpu
4b1b25e3
JA
480ask_user_for_config
481validate_config
c2d3ee4a 482
4b1b25e3
JA
483##
484## if we reach this point without exiting, OK to proceed
485##
02fd0d94 486./launcher bootstrap $app_name && ./launcher start $app_name