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