To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / deploy @ 1595:98384d0defa0

1 1595:98384d0defa0 Chris
2
Deploying the SoundSoftware site
3
4 1593:83412a0a2389 Chris
#!/bin/bash
5
6
# To be sourced into a container-specific start.sh file, not run
7
# standalone
8
9
usage() {
10
    echo "Usage: $0 <database-password> <api-key> <api-httpauth-password>" 1>&2
11
    exit 2
12
}
13
14
dbpass="$1"
15
if [ -z "$dbpass" ]; then
16
    usage
17
fi
18
19
apikey="$2"
20
if [ -z "$apikey" ]; then
21
    usage
22
fi
23
24
apipass="$3"
25
if [ -z "$apipass" ]; then
26
    usage
27
fi
28
29
set -eu -o pipefail
30
31
rootdir="$mydir/../.."
32
33
deploydir="$rootdir"/deploy
34
if [ ! -d "$deploydir" ]; then
35
    echo "ERROR: Unexpected repository layout - expected directory at $deploydir"
36
    exit 2
37
fi
38
39
managerdir="$deploydir/vagrant"
40
if [ ! -d "$managerdir" ]; then
41
    echo "ERROR: Required directory $managerdir not found"
42
    exit 2
43
fi
44
45
configdir="$deploydir/config"
46
if [ ! -d "$configdir" ]; then
47
    echo "ERROR: Required directory $configdir not found"
48
    exit 2
49
fi
50
51
if [ ! -f "$rootdir/postgres-dumpall" ]; then
52
    echo "ERROR: I expect to find a Postgres SQL multi-db dump file in $rootdir/postgres-dumpall"
53
    exit 2
54
fi
55
56
fontdir="$rootdir"/public/themes/soundsoftware/stylesheets/fonts
57
if [ ! -f "$fontdir/24BC0E_0_0.woff" ]; then
58
    echo "ERROR: I expect to find necessary webfonts in $fontdir"
59
    exit 2
60
fi
61
62
apischeme=http
63
apihost=localhost
64
65
#apischeme=https
66
#apihost=code.soundsoftware.ac.uk
67
68
for f in "$configdir"/*.in "$rootdir"/extra/soundsoftware/extract-docs.sh ; do
69
    out="$configdir"/$(basename "$f" .in).gen
70
    cat "$f" | sed \
71
                   -e 's/INSERT_DATABASE_PASSWORD_HERE/'"$dbpass"'/g' \
72
                   -e 's/INSERT_API_KEY_HERE/'"$apikey"'/g' \
73
                   -e 's/INSERT_API_SCHEME_HERE/'"$apischeme"'/g' \
74
                   -e 's/INSERT_API_HOST_HERE/'"$apihost"'/g' \
75
                   -e 's/INSERT_API_USER_HERE/user/g' \
76
                   -e 's/INSERT_API_PASSWORD_HERE/'"$apipass"'/g' \
77
                   > "$out"
78
done
79 1570:ae2f71010562 Chris
80
# A test Apache config. Lacks SSL, lacks a desirable extra layer of
81
# authentication for admin interface paths. Do not deploy this.
82
83 1593:83412a0a2389 Chris
# Note this has been updated for Apache 2.4, which introduced a number
84
# of (welcome) changes to access control directives.
85
86 1570:ae2f71010562 Chris
PerlLoadModule Apache::Authn::SoundSoftware
87
88
<VirtualHost *:80>
89
        ServerName code.soundsoftware.ac.uk
90
        ServerAdmin chris.cannam@soundsoftware.ac.uk
91
92
        DocumentRoot /var/www/code/public
93
        PassengerRestartDir restart_files
94
        PassengerHighPerformance on
95
        PassengerMaxRequests 50000
96
        PassengerStatThrottleRate 5
97
	PassengerStartTimeout 60
98 1571:4c2b25b7e85f Chris
	PassengerFriendlyErrorPages on
99 1570:ae2f71010562 Chris
        RailsSpawnMethod smart
100
        ExpiresDefault "access plus 1 minute"
101
102 1590:c18460da6620 Chris
#        <Location /sys>
103
#		AuthType Basic
104
#		AuthUserFile "/etc/apache2/auth/user.htpasswd"
105
#		AuthName "code.soundsoftware.ac.uk"
106
#		Require user user
107
#	</Location>
108
109
#	<Location /admin>
110
#		AuthType Digest
111
#		AuthUserFile "/etc/apache2/auth/admin.htdigest"
112
#		AuthName "code.soundsoftware.ac.uk admin interface"
113
#		Require user admin
114
#	</Location>
115
116 1570:ae2f71010562 Chris
        <DirectoryMatch "^/.*/\.svn/">
117 1593:83412a0a2389 Chris
                Require all denied
118 1570:ae2f71010562 Chris
        </DirectoryMatch>
119
120
        <DirectoryMatch "^/.*/\.hg/">
121 1593:83412a0a2389 Chris
                Require all denied
122 1570:ae2f71010562 Chris
        </DirectoryMatch>
123
124
        <DirectoryMatch "^/.*/\.git/">
125 1593:83412a0a2389 Chris
                Require all denied
126 1570:ae2f71010562 Chris
        </DirectoryMatch>
127
128
        <Directory /var/www/code/public>
129
                Options -MultiViews
130
	</Directory>
131
132
        <Directory /var/www/code/public/themes/soundsoftware/stylesheets/fonts>
133
		# Avoid other sites embedding our fonts
134
		RewriteEngine on
135
		RewriteCond %{HTTP_REFERER} !^$
136
		RewriteCond %{HTTP_REFERER} !^http(s)?://code.soundsoftware.ac.uk/.*$ [NC]
137
		RewriteRule \.(ttf|woff|eot|otf|svg|zip|gz|html|txt)$ - [F]
138
	</Directory>
139
140
	ScriptAlias /hg "/var/hg/index.cgi"
141
142
	<Location /hg>
143
               	AuthName "Mercurial"
144
                AuthType Basic
145
                Require valid-user
146
		PerlAccessHandler Apache::Authn::SoundSoftware::access_handler
147
      		PerlAuthenHandler Apache::Authn::SoundSoftware::authen_handler
148
		PerlSetVar HTTPS "on"
149
		SoundSoftwareDSN "dbi:Pg:database=code;host=localhost"
150
    		SoundSoftwareDbUser "code"
151 1593:83412a0a2389 Chris
     		SoundSoftwareDbPass "INSERT_DATABASE_PASSWORD_HERE"
152 1570:ae2f71010562 Chris
		SoundSoftwareRepoPrefix "/var/hg/"
153 1576:d1de6986e429 Chris
                #!!! "on" in production please!:
154
                SoundSoftwareSslRequired "off"
155 1570:ae2f71010562 Chris
		Options +ExecCGI
156
		AddHandler cgi-script .cgi
157
		ExpiresDefault now
158
        </Location>
159
160
	Alias /git "/var/files/git-mirror"
161
162
	<Directory "/var/files/git-mirror">
163
		Options -Indexes +FollowSymLinks
164 1593:83412a0a2389 Chris
                Require all granted
165 1570:ae2f71010562 Chris
	</Directory>
166
	<Directory ~ "/var/files/git-mirror/.*\.workdir">
167 1593:83412a0a2389 Chris
                Require all denied
168 1570:ae2f71010562 Chris
	</Directory>
169
	<Directory ~ "/var/files/git-mirror/__.*">
170 1593:83412a0a2389 Chris
                Require all denied
171 1570:ae2f71010562 Chris
	</Directory>
172
173
	ErrorLog /var/log/apache2/code-error.log
174
	CustomLog /var/log/apache2/code-access.log vhost_combined
175
176
        LogLevel warn
177
        ServerSignature Off
178
179
</VirtualHost>
180
181 1586:d0d59d12db94 Chris
#!/bin/sh
182 1590:c18460da6620 Chris
183 1586:d0d59d12db94 Chris
outfile="/var/files/backups/postgres-dumpall-`date +%Y%m%d%H%M`"
184 1590:c18460da6620 Chris
185 1586:d0d59d12db94 Chris
oldmask=`umask`
186
umask 0277
187 1590:c18460da6620 Chris
188 1586:d0d59d12db94 Chris
su postgres -c /usr/bin/pg_dumpall > "$outfile" && bzip2 "$outfile"
189 1590:c18460da6620 Chris
190 1586:d0d59d12db94 Chris
umask "$oldmask"
191
#!/bin/bash
192 1590:c18460da6620 Chris
193 1586:d0d59d12db94 Chris
cd /tmp
194 1590:c18460da6620 Chris
195 1586:d0d59d12db94 Chris
/var/www/code/docgen/extract-docs.sh
196 1590:c18460da6620 Chris
197 1586:d0d59d12db94 Chris
#!/bin/bash
198 1590:c18460da6620 Chris
199 1586:d0d59d12db94 Chris
sudo -u code sh -c "cd /var/www/code ; ./script/rails runner -e production extra/soundsoftware/get-statistics.rb >> log/statistics.log"
200 1590:c18460da6620 Chris
201 1586:d0d59d12db94 Chris
#!/bin/bash
202 1590:c18460da6620 Chris
203 1586:d0d59d12db94 Chris
tail -2 /var/log/external-repos.log
204
#!/bin/bash
205
206 1590:c18460da6620 Chris
## No longer used - this site is now static
207
208
# /usr/bin/wget -O - -q -t 1 http://www.soundsoftware.ac.uk/cron.php
209
210 1586:d0d59d12db94 Chris
#!/bin/bash
211 1590:c18460da6620 Chris
212 1586:d0d59d12db94 Chris
sudo -u code sh -c "cd /var/www/code ; ./script/rails runner \"Repository.fetch_changesets\" -e production 2>&1 | grep -v 'Not trusting' | grep -v 'svn:' | grep -v 'working copy' | grep -v 'deprecated' | grep -v 'version_requirements'"
213
exit 0
214 1590:c18460da6620 Chris
215 1586:d0d59d12db94 Chris
#!/bin/bash
216 1590:c18460da6620 Chris
217 1586:d0d59d12db94 Chris
sudo -H -u www-data /var/www/code/reposman/run-external.sh
218 1590:c18460da6620 Chris
219 1586:d0d59d12db94 Chris
#!/bin/sh
220 1590:c18460da6620 Chris
221 1586:d0d59d12db94 Chris
rm -f /var/www/code/tmp/cache/*/*/views*explore*
222
#!/bin/bash
223 1590:c18460da6620 Chris
224 1586:d0d59d12db94 Chris
logfile="/var/www/code/log/export-git.log"
225 1590:c18460da6620 Chris
226 1586:d0d59d12db94 Chris
sudo -u code sh -c "cd /tmp ; /var/www/code/extra/soundsoftware/export-git.sh production /var/hg /var/files/git-mirror >> $logfile 2>&1"
227 1590:c18460da6620 Chris
228 1586:d0d59d12db94 Chris
#!/bin/bash
229 1590:c18460da6620 Chris
230 1586:d0d59d12db94 Chris
sudo -u www-data /var/www/code/reposman/run-reposman.sh
231
232
#!/bin/sh
233
for location in var/www etc/apache2 etc/cron.*; do
234
	target="/var/files/backups/`echo $location | sed 's,/,_,g'`-`date +%Y%m%d%H%M`"
235
	oldmask=`umask`
236
	umask 0277
237
	cd /
238
	tar cjf "$target".tar.bz2 "$location"
239
	umask "$oldmask"
240
done
241
242 1570:ae2f71010562 Chris
production:
243
  adapter: postgresql
244
  database: code
245
  host: localhost
246
  username: code
247 1593:83412a0a2389 Chris
  password: "INSERT_DATABASE_PASSWORD_HERE"
248 1570:ae2f71010562 Chris
249 1576:d1de6986e429 Chris
[paths]
250
/ = /var/hg/*
251
252
[web]
253
allow_archive = gz, zip, bz2
254
allow_push = *
255
#!/usr/bin/env python
256
#
257
# An example CGI script to export multiple hgweb repos, edit as necessary
258
259
# adjust python path if not a system-wide install:
260
#import sys
261
#sys.path.insert(0, "/path/to/python/lib")
262
263
# enable importing on demand to reduce startup time
264
from mercurial import demandimport; demandimport.enable()
265
266
# Uncomment to send python tracebacks to the browser if an error occurs:
267
import cgitb
268
cgitb.enable()
269
270
# If you'd like to serve pages with UTF-8 instead of your default
271
# locale charset, you can do so by uncommenting the following lines.
272
# Note that this will cause your .hgrc files to be interpreted in
273
# UTF-8 and all your repo files to be displayed using UTF-8.
274
#
275
import os
276
os.environ["HGENCODING"] = "UTF-8"
277
278
from mercurial.hgweb.hgwebdir_mod import hgwebdir
279
import mercurial.hgweb.wsgicgi as wsgicgi
280
281
# The config file looks like this.  You can have paths to individual
282
# repos, collections of repos in a directory tree, or both.
283
#
284
# [paths]
285
# virtual/path1 = /real/path1
286
# virtual/path2 = /real/path2
287
# virtual/root = /real/root/*
288
# / = /real/root2/*
289
# virtual/root2 = /real/root2/**
290
#
291
# [collections]
292
# /prefix/to/strip/off = /root/of/tree/full/of/repos
293
#
294
# paths example:
295
#
296
# * First two lines mount one repository into one virtual path, like
297
# '/real/path1' into 'virtual/path1'.
298
#
299
# * The third entry mounts every mercurial repository found in '/real/root'
300
# in 'virtual/root'. This format is preferred over the [collections] one,
301
# since using absolute paths as configuration keys is not supported on every
302
# platform (especially on Windows).
303
#
304
# * The fourth entry is a special case mounting all repositories in
305
# /'real/root2' in the root of the virtual directory.
306
#
307
# * The fifth entry recursively finds all repositories under the real root,
308
# and mounts them using their relative path (to given real root) under the
309
# virtual root.
310
#
311
# collections example: say directory tree /foo contains repos /foo/bar,
312
# /foo/quux/baz.  Give this config section:
313
#   [collections]
314
#   /foo = /foo
315
# Then repos will list as bar and quux/baz.
316
#
317
# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
318
# or use a dictionary with entries like 'virtual/path': '/real/path'
319
320
application = hgwebdir('hgweb.config')
321
wsgicgi.launch(application)
322 1586:d0d59d12db94 Chris
# see "man logrotate" for details
323
# rotate log files weekly
324
weekly
325
326 1590:c18460da6620 Chris
# use the syslog group by default, since this is the owning group
327
# of /var/log/syslog.
328
su root syslog
329
330 1586:d0d59d12db94 Chris
# keep 4 weeks worth of backlogs
331
rotate 4
332
333
# create new (empty) log files after rotating old ones
334
create
335
336
# uncomment this if you want your log files compressed
337
#compress
338
339
# packages drop log rotation information into this directory
340
include /etc/logrotate.d
341
342
# no packages own wtmp, or btmp -- we'll rotate them here
343
/var/log/wtmp {
344
    missingok
345
    monthly
346
    create 0664 root utmp
347
    rotate 1
348
}
349
350
/var/log/btmp {
351
    missingok
352
    monthly
353
    create 0660 root utmp
354
    rotate 1
355
}
356
357
# system-specific logs may be configured here
358
/var/www/code/log/*.log {
359
	weekly
360
	missingok
361
	rotate 52
362
	compress
363
	delaycompress
364
	create 640 code code
365
	sharedscripts
366
	postrotate
367
		touch /var/www/code/restart_files/restart.txt
368
	endscript
369
}
370
371
/var/log/reposman.log {
372
        weekly
373
        missingok
374
        rotate 52
375
        compress
376
        delaycompress
377
        create 640 www-data code
378
        sharedscripts
379
}
380
381
/var/log/external-repos.log {
382
        weekly
383
        missingok
384
        rotate 52
385
        compress
386
        delaycompress
387
        create 640 www-data code
388
        sharedscripts
389
}
390
391 1571:4c2b25b7e85f Chris
PassengerMaxPoolSize 60
392
393
LoadModule passenger_module /var/lib/gems/2.3.0/gems/passenger-4.0.60/buildout/apache2/mod_passenger.so
394
PassengerRoot /var/lib/gems/2.3.0/gems/passenger-4.0.60
395
PassengerDefaultRuby /usr/bin/ruby2.3
396
# Apache::DBI is supposed to be a transparent replacement for Perl DBI with
397
# better performance when multiple connections are made with common DSN, user
398
# and password
399
PerlModule Apache::DBI
400 1590:c18460da6620 Chris
#!/bin/bash
401
logfile=/var/log/external-repos.log
402
(
403
flock -s 200
404
echo >> $logfile
405
date >> $logfile
406
/var/www/code/reposman/convert-external-repos.rb \
407
	-s /var/hg \
408 1593:83412a0a2389 Chris
	-r INSERT_API_SCHEME_HERE://INSERT_API_HOST_HERE/ \
409 1590:c18460da6620 Chris
	-k INSERT_API_KEY_HERE \
410
	-v \
411 1593:83412a0a2389 Chris
	--http-user=INSERT_API_USER_HERE \
412
	--http-pass=INSERT_API_PASSWORD_HERE \
413 1590:c18460da6620 Chris
        -c "/var/www/code/reposman/update-external-repo.sh" \
414
	>> $logfile 2>&1
415
date >> $logfile
416
echo Done >> $logfile
417
)200>>$logfile
418
#!/bin/bash
419
logfile=/var/log/reposman.log
420
(
421
flock -s 200
422
echo >> $logfile
423
/var/www/code/reposman/reposman-soundsoftware.rb \
424
	-s /var/hg \
425 1593:83412a0a2389 Chris
	-r INSERT_API_SCHEME_HERE://INSERT_API_HOST_HERE/ \
426 1590:c18460da6620 Chris
	-k INSERT_API_KEY_HERE \
427 1593:83412a0a2389 Chris
	--http-user=INSERT_API_USER_HERE \
428
	--http-pass=INSERT_API_PASSWORD_HERE \
429 1590:c18460da6620 Chris
	-o www-data \
430
	-g code \
431
	-c "/var/www/code/reposman/run-hginit.sh" \
432
	--scm=Mercurial \
433
	>> $logfile 2>&1
434
)200>>$logfile
435 1587:d8949733849d Chris
436
FROM ubuntu:16.04
437
MAINTAINER Chris Cannam <cannam@all-day-breakfast.com>
438
439
COPY . /var/www/code
440
441
WORKDIR /var/www/code
442
443
INSERT_PROVISIONING_HERE
444
445
# Start Postgres and foregrounded Apache
446
447
RUN echo "#!/bin/bash"                      > container-run.sh
448
RUN echo "/etc/init.d/postgresql start"    >> container-run.sh
449
RUN echo "apache2ctl -D FOREGROUND"        >> container-run.sh
450
RUN chmod +x container-run.sh
451
452
EXPOSE 80
453
CMD ./container-run.sh
454
455
456
# For documentation and experimental purposes only. As a
457
# reconstruction of the machine image that runs this application,
458
# there are lots of things missing here; but as a good Docker
459
# configuration, it fails by mixing together rather a lot of concerns.
460
461
FROM ubuntu:16.04
462
MAINTAINER Chris Cannam <cannam@all-day-breakfast.com>
463
464
RUN apt-get update && \
465
    apt-get install -y \
466
    apache2 \
467
    apache2-dev \
468
    apt-utils \
469
    build-essential \
470
    cron \
471
    curl \
472
    doxygen \
473
    exim4 \
474
    git \
475
    graphviz \
476
    imagemagick \
477
    libapache-dbi-perl \
478
    libapache2-mod-perl2 \
479
    libapr1-dev \
480
    libaprutil1-dev \
481
    libauthen-simple-ldap-perl \
482
    libcurl4-openssl-dev \
483
    libdbd-pg-perl \
484
    libpq-dev \
485
    libmagickwand-dev \
486
    libio-socket-ssl-perl \
487
    logrotate \
488
    mercurial \
489
    postgresql \
490
    rsync \
491
    ruby \
492
    ruby-dev \
493
    sudo
494
495
# Also used on the live site, for javadoc extraction, but this is
496
# would be by far the biggest package here: let's omit it while we're
497
# not making use of it
498
#   openjdk-9-jdk-headless
499
500
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
501
502
503
# Passenger gets installed through gem, not apt
504
505
RUN gem install passenger -v 4.0.60 --no-rdoc --no-ri
506
RUN passenger-install-apache2-module --languages=ruby
507
508
509
# Copy across webapp, set up ownership
510
511
COPY . /var/www/code
512
513
RUN groupadd code
514
RUN useradd -g code -G www-data code
515
RUN chown -R code.www-data /var/www/code
516
RUN find /var/www/code -type d -exec chmod g+s \{\} \;
517
518
519
# Initialise /var/hg (in reality this would be mounted from somewhere)
520
521
RUN mkdir -p /var/hg
522
RUN chown code.www-data /var/hg
523
RUN chmod g+s /var/hg
524
COPY extra/soundsoftware/scripted-deploy/config/index.cgi /var/hg/
525
COPY extra/soundsoftware/scripted-deploy/config/hgweb.config /var/hg/
526
RUN chmod +x /var/hg/index.cgi
527
528
529
# We're based in the code webapp directory from here on
530
531
WORKDIR /var/www/code
532
533
534
# Set up database config etc
535
536
RUN cp extra/soundsoftware/scripted-deploy/config/database.yml.interpolated config/database.yml
537
538
539
# Install Rails and dependencies (database.yml must be populated before this)
540
541
RUN gem install bundler
542
RUN bundle install
543
544
545
# Initialise Redmine token (bundler must be installed before this)
546
547
RUN bundle exec rake generate_secret_token
548
549
550
# Import Postgres database from postgres-dumpall file
551
552
RUN chown postgres postgres-dumpall
553
RUN /etc/init.d/postgresql start && sudo -u postgres psql -f postgres-dumpall postgres
554
RUN rm postgres-dumpall
555
556
557
# Install Perl auth module for Hg access
558
559
RUN mkdir -p /usr/local/lib/site_perl/Apache/Authn/
560
RUN cp extra/soundsoftware/SoundSoftware.pm /usr/local/lib/site_perl/Apache/Authn/
561
562
563
# Set up Apache config (todo: insert variables)
564
565
RUN rm -f /etc/apache2/sites-enabled/000-default.conf
566
567
RUN cp extra/soundsoftware/scripted-deploy/config/passenger.conf /etc/apache2/mods-available/
568
RUN cp extra/soundsoftware/scripted-deploy/config/passenger.load /etc/apache2/mods-available/
569
RUN cp extra/soundsoftware/scripted-deploy/config/perl.conf      /etc/apache2/mods-available/
570
571
RUN ln -s ../mods-available/passenger.conf  /etc/apache2/mods-enabled/
572
RUN ln -s ../mods-available/passenger.load  /etc/apache2/mods-enabled/
573
RUN ln -s ../mods-available/perl.conf       /etc/apache2/mods-enabled/
574
RUN ln -s ../mods-available/expires.load    /etc/apache2/mods-enabled/
575
RUN ln -s ../mods-available/rewrite.load    /etc/apache2/mods-enabled/
576
RUN ln -s ../mods-available/cgi.load        /etc/apache2/mods-enabled/
577
578
RUN cp extra/soundsoftware/scripted-deploy/config/code.conf.interpolated /etc/apache2/sites-available/code.conf
579
RUN ln -s ../sites-available/code.conf /etc/apache2/sites-enabled/10-code.conf
580
581
RUN apache2ctl configtest
582
583
584
# Start Postgres and foregrounded Apache
585
586
RUN echo "#!/bin/bash"                      > container-run.sh
587
RUN echo "/etc/init.d/postgresql start"    >> container-run.sh
588
RUN echo "apache2ctl -D FOREGROUND"        >> container-run.sh
589
RUN chmod +x container-run.sh
590
591
EXPOSE 80
592
CMD ./container-run.sh
593
594 1569:26a4f99ec679 Chris
#!/bin/bash
595
596 1586:d0d59d12db94 Chris
mydir=$(dirname "$0")
597 1593:83412a0a2389 Chris
. "$mydir"/../any/prepare.sh
598 1574:7b23adecd963 Chris
599 1587:d8949733849d Chris
provisioning_commands=$(
600 1590:c18460da6620 Chris
    for x in "$deploydir"/provision.d/[0-9]*.sh; do
601 1587:d8949733849d Chris
        echo "RUN /bin/bash /var/www/code/deploy/provision.d/$(basename $x)"
602
    done | sed 's/$/\\n/' | fmt -2000 | sed 's/ RUN/RUN/g' )
603
604
( echo
605
  echo "### DO NOT EDIT THIS FILE - it is generated from Dockerfile.in"
606
  echo
607
) > "$managerdir/Dockerfile"
608
609
cat "$managerdir/Dockerfile.in" |
610
    sed 's,INSERT_PROVISIONING_HERE,'"$provisioning_commands"',' >> \
611 1593:83412a0a2389 Chris
        "$managerdir/Dockerfile.gen"
612 1587:d8949733849d Chris
613 1586:d0d59d12db94 Chris
cd "$rootdir"
614
615 1569:26a4f99ec679 Chris
dockertag="cannam/soundsoftware-site"
616
617 1593:83412a0a2389 Chris
sudo docker build -t "$dockertag" -f "deploy/docker/Dockerfile.gen" .
618 1571:4c2b25b7e85f Chris
sudo docker run -p 8080:80 -d "$dockertag"
619 1569:26a4f99ec679 Chris
620 1577:e38eee2e1d47 Chris
#!/bin/bash
621
622
set -e
623
624 1589:94669513c53c Chris
# Install necessary system packages. This assumes we are deploying on
625
# Ubuntu 16.04.
626
627
# We aim to make all of these provisioning scripts non-destructive if
628
# run more than once. In this case, running the script again will
629
# install any outstanding updates.
630
631 1587:d8949733849d Chris
apt-get update && \
632
    apt-get dist-upgrade -y && \
633
    apt-get install -y \
634
            ack-grep \
635
            apache2 \
636
            apache2-dev \
637
            apt-utils \
638
            build-essential \
639
            cron \
640 1582:f26dc3004b3f Chris
            curl \
641
            doxygen \
642 1587:d8949733849d Chris
            exim4 \
643 1582:f26dc3004b3f Chris
            git \
644 1587:d8949733849d Chris
            graphviz \
645
            imagemagick \
646
            libapache-dbi-perl \
647
            libapache2-mod-perl2 \
648
            libapr1-dev \
649
            libaprutil1-dev \
650
            libauthen-simple-ldap-perl \
651
            libcurl4-openssl-dev \
652
            libdbd-pg-perl \
653
            libpq-dev \
654
            libmagickwand-dev \
655
            libio-socket-ssl-perl \
656
            logrotate \
657 1582:f26dc3004b3f Chris
            mercurial \
658 1589:94669513c53c Chris
            openjdk-9-jdk-headless \
659 1582:f26dc3004b3f Chris
            postgresql \
660 1587:d8949733849d Chris
            rsync \
661
            ruby \
662
            ruby-dev \
663
            sudo
664 1582:f26dc3004b3f Chris
665 1587:d8949733849d Chris
locale-gen en_US.UTF-8
666 1582:f26dc3004b3f Chris
667
668 1577:e38eee2e1d47 Chris
#!/bin/bash
669
670
set -e
671
672 1589:94669513c53c Chris
# Phusion Passenger as application server.
673
# This gets installed through gem, not apt, and we ask for a specific
674
# version (the last in the 4.0.x line).
675 1577:e38eee2e1d47 Chris
676
if [ ! -f /var/lib/gems/2.3.0/gems/passenger-4.0.60/buildout/apache2/mod_passenger.so ]; then
677
    gem install passenger -v 4.0.60 --no-rdoc --no-ri
678
    passenger-install-apache2-module --languages=ruby
679
fi
680
681
#!/bin/bash
682
683
set -e
684
685 1590:c18460da6620 Chris
# The webapp directory is owned and run by the code user, in group
686
# www-data. The repos and other things served directly are the other
687
# way around -- owned by the www-data user, in group code.
688 1589:94669513c53c Chris
689 1590:c18460da6620 Chris
for user in code docgen ; do
690
    if ! grep -q "^$user:" /etc/passwd ; then
691
        groupadd "$user"
692
        useradd -g "$user" -G www-data "$user"
693
    fi
694
done
695 1577:e38eee2e1d47 Chris
696
#!/bin/bash
697
698
set -e
699
700 1589:94669513c53c Chris
# We might be running in one of two ways:
701
#
702
# 1. The code directory is already at /var/www/code, either because a
703
# previous provisioning step has imported it there or because this
704
# script has been run before -- in this situation all we do is
705
# re-check the ownership and permissions. OR
706
#
707
# 2. The code directory has not yet been copied to /var/www/code, in
708
# which case we expect to find it at /code-to-deploy, e.g. as a
709
# Vagrant shared folder, and we copy it over from there. (We don't
710
# deploy directly from shared folders as we might not be able to
711
# manipulate ownership and permissions properly there.)
712
713 1577:e38eee2e1d47 Chris
if [ ! -d /var/www/code ]; then
714 1587:d8949733849d Chris
    if [ ! -d /code-to-deploy ]; then
715 1589:94669513c53c Chris
        echo "ERROR: Expected to find code tree at /var/www/code or /code-to-deploy: is the deployment script being invoked correctly?"
716 1587:d8949733849d Chris
        exit 2
717
    fi
718
    cp -a /code-to-deploy /var/www/code
719 1577:e38eee2e1d47 Chris
fi
720
721 1587:d8949733849d Chris
chown -R code.www-data /var/www/code
722
find /var/www/code -type d -exec chmod g+s \{\} \;
723
724
725 1577:e38eee2e1d47 Chris
#!/bin/bash
726
727
set -e
728
729 1589:94669513c53c Chris
# In a real deployment, /var/hg is probably mounted from somewhere
730
# else. But in an empty deployment we need to create it, and in both
731
# cases we set up the config files with their current versions here.
732
733 1577:e38eee2e1d47 Chris
if [ ! -f /var/hg/index.cgi ]; then
734
    mkdir -p /var/hg
735
fi
736 1589:94669513c53c Chris
737
cp /var/www/code/deploy/config/index.cgi /var/hg/
738
cp /var/www/code/deploy/config/hgweb.config /var/hg/
739
740
chmod +x /var/hg/index.cgi
741
742 1590:c18460da6620 Chris
chown -R www-data.code /var/hg
743 1589:94669513c53c Chris
find /var/hg -type d -exec chmod g+s \{\} \;
744
745 1577:e38eee2e1d47 Chris
#!/bin/bash
746
747
set -e
748
749 1589:94669513c53c Chris
# Copy across the database config file (the source file has presumably
750
# been generated from a skeleton, earlier in provisioning)
751
752 1593:83412a0a2389 Chris
infile=/var/www/code/deploy/config/database.yml.gen
753 1589:94669513c53c Chris
outfile=/var/www/code/config/database.yml
754 1587:d8949733849d Chris
755 1589:94669513c53c Chris
if [ ! -f "$outfile" ]; then
756
    if [ ! -f "$infile" ]; then
757
        echo "ERROR: Database config file $infile not found - has the database secret been interpolated from $infile.in correctly?"
758
        exit 2
759
    fi
760
    cp "$infile" "$outfile"
761 1577:e38eee2e1d47 Chris
fi
762
763
#!/bin/bash
764
765
set -e
766
767 1589:94669513c53c Chris
# Install Ruby gems for the web app.
768
769
# We aim to make all of these provisioning scripts non-destructive if
770
# run more than once. In this case, running the script again will
771
# install any outstanding updates.
772
773 1577:e38eee2e1d47 Chris
cd /var/www/code
774
gem install bundler
775
bundle install
776
777
#!/bin/bash
778
779
set -e
780
781 1589:94669513c53c Chris
# Create a session token if it hasn't already been created.
782
783 1577:e38eee2e1d47 Chris
cd /var/www/code
784
785 1589:94669513c53c Chris
if [ ! -f config/initializers/secret_token.rb ]; then
786
    bundle exec rake generate_secret_token
787
fi
788
789
790 1577:e38eee2e1d47 Chris
#!/bin/bash
791
792
set -e
793
794 1589:94669513c53c Chris
# Start the database and if a dump file is found, load it. The dump
795
# file is then deleted so that the db won't be overwritten on
796
# subsequent runs. (The original repo contains no dump file, so it
797
# should exist only if you have provided some data to load.)
798
799 1577:e38eee2e1d47 Chris
/etc/init.d/postgresql start
800
801
cd /var/www/code
802
803
if [ -f postgres-dumpall ]; then
804
    chmod ugo+r postgres-dumpall
805
    sudo -u postgres psql -f postgres-dumpall postgres
806 1589:94669513c53c Chris
    rm postgres-dumpall
807 1577:e38eee2e1d47 Chris
fi
808
809
#!/bin/bash
810
811
set -e
812
813 1589:94669513c53c Chris
# Install the Apache mod_perl module used for hg repo access control
814
815 1577:e38eee2e1d47 Chris
if [ ! -f /usr/local/lib/site_perl/Apache/Authn/SoundSoftware.pm ]; then
816
    mkdir -p /usr/local/lib/site_perl/Apache/Authn/
817 1589:94669513c53c Chris
    cp /var/www/code/extra/soundsoftware/SoundSoftware.pm \
818
       /usr/local/lib/site_perl/Apache/Authn/
819 1577:e38eee2e1d47 Chris
fi
820
821
#!/bin/bash
822
823
set -e
824
825 1589:94669513c53c Chris
# Install Apache config files and module loaders
826
827 1577:e38eee2e1d47 Chris
cd /var/www/code
828
829 1593:83412a0a2389 Chris
codeconffile=/var/www/code/deploy/config/code.conf.gen
830 1587:d8949733849d Chris
831
if [ ! -f "$codeconffile" ]; then
832 1593:83412a0a2389 Chris
    echo "ERROR: Apache config file $codeconffile not found - has the database secret been interpolated from its input file correctly?"
833 1587:d8949733849d Chris
    exit 2
834
fi
835
836 1577:e38eee2e1d47 Chris
if [ ! -f /etc/apache2/sites-enabled/10-code.conf ]; then
837
838
    rm -f /etc/apache2/sites-enabled/000-default.conf
839
840 1587:d8949733849d Chris
    cp deploy/config/passenger.conf /etc/apache2/mods-available/
841
    cp deploy/config/passenger.load /etc/apache2/mods-available/
842
    cp deploy/config/perl.conf      /etc/apache2/mods-available/
843 1577:e38eee2e1d47 Chris
844
    ln -s ../mods-available/passenger.conf  /etc/apache2/mods-enabled/
845
    ln -s ../mods-available/passenger.load  /etc/apache2/mods-enabled/
846
    ln -s ../mods-available/perl.conf       /etc/apache2/mods-enabled/
847
    ln -s ../mods-available/expires.load    /etc/apache2/mods-enabled/
848
    ln -s ../mods-available/rewrite.load    /etc/apache2/mods-enabled/
849 1578:06ca2df3d7ca Chris
    ln -s ../mods-available/cgi.load        /etc/apache2/mods-enabled/
850 1577:e38eee2e1d47 Chris
851 1587:d8949733849d Chris
    cp "$codeconffile" /etc/apache2/sites-available/code.conf
852 1577:e38eee2e1d47 Chris
    ln -s ../sites-available/code.conf /etc/apache2/sites-enabled/10-code.conf
853
854
    apache2ctl configtest
855
856
fi
857
858 1588:9149f2098413 Chris
#!/bin/bash
859
860
set -e
861
862 1589:94669513c53c Chris
# In case we are running without a properly mounted /var/hg directory,
863
# check for the existence of one repo and, if absent, attempt to clone
864
# it so that we have something we can serve for test purposes.
865
866 1588:9149f2098413 Chris
if [ ! -d /var/hg/vamp-plugin-sdk ]; then
867
    echo "Cloning vamp-plugin-sdk repo for testing..."
868
    cd /var/hg
869
    hg clone https://code.soundsoftware.ac.uk/hg/vamp-plugin-sdk
870 1590:c18460da6620 Chris
    chown -R www-data.code vamp-plugin-sdk
871 1588:9149f2098413 Chris
fi
872 1590:c18460da6620 Chris
#!/bin/bash
873
874
set -e
875
876
# Copy docgen scripts to the place they actually live. This is
877
# particularly badly managed, since the target location is actually
878
# within the repo already
879
880
cd /var/www/code
881
882
mkdir -p docgen
883
884
for file in \
885
    doxysafe.pl \
886
    extract-doxygen.sh \
887
    extract-javadoc.sh \
888
    extract-matlabdocs.sh \
889
    matlab-docs.conf \
890
    matlab-docs-credit.html \
891
    matlab-docs.pl ; do
892
    if [ ! -f docgen/"$file" ]; then
893
        cp extra/soundsoftware/"$file" docgen/
894
    fi
895
done
896
897 1593:83412a0a2389 Chris
for file in \
898
    extract-docs.sh ; do
899
    if [ ! -f docgen/"$file" ]; then
900
        cp deploy/config/"$file".gen docgen/"$file"
901
    fi
902
done
903
904 1590:c18460da6620 Chris
chown code.www-data docgen/*
905
chmod +x docgen/*.sh
906
907
#!/bin/bash
908
909
set -e
910
911
# Copy reposman scripts to the place they actually live. Like docgen,
912
# this is particularly badly managed, since the target location is
913
# actually within the repo already. At least in this case some of the
914
# scripts have to be edited to insert the server's API key, so there
915
# is a bit of logic there
916
917
cd /var/www/code
918
919
mkdir -p reposman
920
921
for file in \
922
    convert-external-repos.rb \
923
    reposman-soundsoftware.rb \
924
    run-hginit.sh \
925
    update-external-repo.sh ; do
926
    if [ ! -f reposman/"$file" ]; then
927
        cp extra/soundsoftware/"$file" reposman/
928
    fi
929
done
930
931
for file in \
932
    run-external.sh \
933
    run-reposman.sh ; do
934
    if [ ! -f reposman/"$file" ]; then
935 1593:83412a0a2389 Chris
        cp deploy/config/"$file".gen reposman/"$file"
936 1590:c18460da6620 Chris
    fi
937
done
938
939
chown code.www-data reposman/*
940
chmod +x reposman/*.sh
941
chmod +x reposman/*.rb
942
943
touch /var/log/reposman.log
944
touch /var/log/external-repos.log
945
chown www-data.code /var/log/reposman.log
946
chown www-data.code /var/log/external-repos.log
947
948
#!/bin/bash
949
950
set -e
951
952
# Initialise directories used as targets for cron activity (if they
953
# don't already exist)
954
955
for dir in \
956
    /var/files/backups \
957
    /var/doc \
958
    /var/files/git-mirror ; do
959
    if [ ! -d "$dir" ]; then
960
        mkdir -p "$dir"
961
        chown -R code.www-data "$dir"
962
        chmod g+s "$dir"
963
    fi
964
done
965
966
# Copy cron scripts to the appropriate destinations
967
968
cd /var/www/code
969
970
if [ ! -d /etc/cron.minutely ]; then
971
    mkdir -p /etc/cron.minutely
972
    echo '*  *    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.minutely )' >> /etc/crontab
973
fi
974
975
for t in minutely hourly daily monthly; do
976
    for s in deploy/config/cron.$t/[0-9]* ; do
977
        name=$(basename $s)
978
        dest="/etc/cron.$t/$name"
979
        if [ ! -f "$dest" ]; then
980
            cp "$s" "$dest"
981
            chmod +x "$dest"
982
        fi
983
    done
984
done
985
986
987
988
#!/bin/bash
989
990
cd /var/www/code
991
cp deploy/config/logrotate.conf /etc/logrotate.conf
992 1581:ae8043b014c7 Chris
#!/bin/bash
993
994
set -e
995
996 1589:94669513c53c Chris
# Last action: start the webserver
997
998 1581:ae8043b014c7 Chris
apache2ctl restart
999
1000 1577:e38eee2e1d47 Chris
# -*- mode: ruby -*-
1001
# vi: set ft=ruby :
1002
1003
Vagrant.configure("2") do |config|
1004 1583:0dcd4f8c2b8a Chris
  config.vm.box = "ubuntu/xenial64"
1005 1577:e38eee2e1d47 Chris
  config.vm.network "forwarded_port", guest: 80, host: 8080
1006 1587:d8949733849d Chris
  config.vm.synced_folder "../..", "/code-to-deploy"
1007 1577:e38eee2e1d47 Chris
  config.vm.provision :shell, path: "vagrant-provision.sh"
1008
end
1009 1581:ae8043b014c7 Chris
#!/bin/bash
1010
1011 1586:d0d59d12db94 Chris
mydir=$(dirname "$0")
1012 1593:83412a0a2389 Chris
. "$mydir"/../any/prepare.sh
1013 1581:ae8043b014c7 Chris
1014
cd "$managerdir"
1015
vagrant up
1016
1017 1577:e38eee2e1d47 Chris
#!/bin/bash
1018
1019
#!!! still not covered:
1020
# * https
1021 1590:c18460da6620 Chris
# * http auth for API (/sys) and /admin interfaces
1022 1593:83412a0a2389 Chris
# * sending email
1023 1577:e38eee2e1d47 Chris
1024
set -e
1025
1026 1590:c18460da6620 Chris
for f in /code-to-deploy/deploy/provision.d/[0-9]*.sh ; do
1027 1577:e38eee2e1d47 Chris
    case "$f" in
1028
        *~) ;;
1029 1593:83412a0a2389 Chris
        *) echo "Running provisioning script: $f"
1030 1577:e38eee2e1d47 Chris
           /bin/bash "$f";;
1031
    esac
1032
done
1033
1034 1593:83412a0a2389 Chris
echo "All provisioning scripts complete"