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