Escape slashes from smtp_password
[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
c2d3ee4a
JA
13##
14## Do we have enough memory and disk space for Discourse?
15##
16check_disk_and_memory() {
17
c2d3ee4a
JA
18 avail_mem="$(LANG=C free -m | grep '^Mem:' | awk '{print $2}')"
19 if [ "$avail_mem" -lt 900 ]; then
51890305
JA
20 echo "WARNING: Discourse requires 1GB RAM to run. This system does not appear"
21 echo "to have sufficient memory."
c2d3ee4a 22 echo
51890305
JA
23 echo "Your site may not work properly, or future upgrades of Discourse may not"
24 echo "complete successfully."
cdd99376
JA
25 exit 1
26 fi
27
28 if [ "$avail_mem" -lt 1800 ]; then
c2d3ee4a
JA
29 total_swap="$(LANG=C free -m | grep ^Swap: | awk '{print $2}')"
30 if [ "$total_swap" -lt 1000 ]; then
e81c0250 31 echo "WARNING: Discourse requires at least 2GB of swap when running with less "
51890305 32 echo "than 2GB of RAM. This system does not appear to have sufficient swap space."
c2d3ee4a 33 echo
8f70d450 34 echo "Without sufficient swap space, your site may not work properly, and future"
51890305 35 echo "upgrades of Discourse may not complete successfully."
c2d3ee4a 36 echo
ac1a2d67 37 read -p "ENTER to create a 2GB swapfile now, or Ctrl+C to exit"
8f70d450
JA
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
7c2777f9 46 echo "/swapfile swap swap auto 0 0" | tee -a /etc/fstab
7802f679 47 sysctl -w vm.swappiness=10
7c2777f9 48 echo vm.swappiness = 10 | tee -a /etc/sysctl.conf
8f70d450
JA
49
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!"
53 exit 1
54 fi
55
c2d3ee4a
JA
56 fi
57 fi
58
59 free_disk="$(df /var | tail -n 1 | awk '{print $4}')"
60 if [ "$free_disk" -lt 5000 ]; then
51890305
JA
61 echo "WARNING: Discourse requires at least 5GB free disk space. This system"
62 echo "does not appear to have sufficient disk space."
c2d3ee4a 63 echo
51890305
JA
64 echo "Insufficient disk space may result in problems running your site, and"
65 echo "may not even allow Discourse installation to complete successfully."
c2d3ee4a
JA
66 echo
67 echo "Please free up some space, or expand your disk, before continuing."
68 echo
51890305
JA
69 echo "Run \`apt-get autoremove && apt-get autoclean\` to clean up unused"
70 echo "packages and \`./launcher cleanup\` to remove stale Docker containers."
c2d3ee4a
JA
71 exit 1
72 fi
73
c2d3ee4a
JA
74}
75
76
77##
78## If we have lots of RAM or lots of CPUs, bump up the defaults to scale better
79##
80scale_ram_and_cpu() {
81
642b870f 82 local changelog=/tmp/changelog.$PPID
c2d3ee4a
JA
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"
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
c2d3ee4a
JA
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##
132check_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##
142check_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
51890305
JA
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"
c2d3ee4a
JA
153 exit 1
154 fi
155}
156
157##
158## prompt user for typical Discourse config file values
159##
4b1b25e3 160ask_user_for_config() {
c2d3ee4a 161
642b870f 162 local changelog=/tmp/changelog.$PPID
c2d3ee4a 163 local hostname="discourse.example.com"
642b870f 164 local developer_emails="me@example.com,you@example.com"
c2d3ee4a 165 local smtp_address="smtp.example.com"
7c2777f9
JA
166 local smtp_port="587"
167 local smtp_user_name="postmaster@discourse.example.com"
c2d3ee4a
JA
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
7c2777f9 207 if [ ! -z $smtp_port ]
c2d3ee4a 208 then
7c2777f9
JA
209 read -p "SMTP port? [$smtp_port]: " new_value
210 if [ ! -z $new_value ]
211 then
212 smtp_port=$new_value
213 fi
c2d3ee4a
JA
214 fi
215
7c2777f9
JA
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
c2d3ee4a
JA
223 if [ "$smtp_address" == "smtp.sendgrid.net" ]
224 then
225 smtp_user_name="apikey"
226 fi
7c2777f9
JA
227 if [ "$smtp_address" == "smtp.mailgun.org" ]
228 then
229 smtp_user_name="postmaster@$hostname"
230 fi
c2d3ee4a
JA
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
51890305 262 echo -e "\nDoes this look right?\n"
c2d3ee4a
JA
263 echo "Hostname : $hostname"
264 echo "Email : $developer_emails"
265 echo "SMTP address : $smtp_address"
7c2777f9 266 echo "SMTP port : $smtp_port"
c2d3ee4a
JA
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 ""
ac1a2d67 276 read -p "ENTER to continue, 'n' to try again, Ctrl+C to exit: " config_ok
c2d3ee4a
JA
277 done
278
013b5931 279 sed -i -e "s/^ DISCOURSE_HOSTNAME:.*/ DISCOURSE_HOSTNAME: $hostname/w $changelog" $config_file
c2d3ee4a
JA
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
013b5931 297 sed -i -e "s/^ DISCOURSE_SMTP_ADDRESS:.*/ DISCOURSE_SMTP_ADDRESS: $smtp_address/w $changelog" $config_file
c2d3ee4a
JA
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
7c2777f9
JA
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
013b5931 315 sed -i -e "s/^ #DISCOURSE_SMTP_USER_NAME:.*/ DISCOURSE_SMTP_USER_NAME: $smtp_user_name/w $changelog" $config_file
c2d3ee4a
JA
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
63b6095f 324 sed -i -e "s/^ #DISCOURSE_SMTP_PASSWORD:.*/ DISCOURSE_SMTP_PASSWORD: \"${smtp_password/\//\\/}\"/w $changelog" $config_file
c2d3ee4a
JA
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
642b870f 335 sed -i -e "s/^ #LETSENCRYPT_ACCOUNT_EMAIL:.*/ LETSENCRYPT_ACCOUNT_EMAIL: $letsencrypt_account_email/w $changelog" $config_file
c2d3ee4a
JA
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
642b870f 348 echo "web.ssl.template.yml enabled"
c2d3ee4a
JA
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##
4b1b25e3 378validate_config() {
c2d3ee4a
JA
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!"
d8613c71
JA
410 echo "If you have unusual requirements, edit $config_file and then: "
411 echo "./launcher bootstrap $app_name"
c2d3ee4a
JA
412 exit 1
413 fi
414}
415
416
417##
418## template file names
419##
420app_name=app
421template_path=samples/standalone.yml
422config_file=containers/$app_name.yml
423changelog=/tmp/changelog
424
4b1b25e3
JA
425##
426## Check requirements before creating a copy of a config file we won't edit
427##
ebdd72f3 428check_root
642b870f
JP
429check_disk_and_memory
430check_ports
431
4b1b25e3 432##
c2d3ee4a 433## make a copy of the simple standalone config file
4b1b25e3 434##
c2d3ee4a
JA
435if [ -a $config_file ]
436then
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
442else
443 cp $template_path $config_file
444fi
445
c2d3ee4a 446scale_ram_and_cpu
4b1b25e3
JA
447ask_user_for_config
448validate_config
c2d3ee4a 449
4b1b25e3
JA
450##
451## if we reach this point without exiting, OK to proceed
452##
02fd0d94 453./launcher bootstrap $app_name && ./launcher start $app_name