1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
|
#!/bin/sh
# On a clean Debian squeeze or Ubuntu precise installation you should
# be able to install FixMyStreet with:
#
# curl https://raw.github.com/mysociety/fixmystreet/master/bin/pre-install-as-root | \
# sh -s fms whatever.compute.amazonaws.com
#
# ... where the first argument is the Unix user who will own the code
# and the application will run as, and the second argument is the
# public hostname for the server, which will be used for creating the
# named virtualhost.
set -e
set -x
SITE=fixmystreet
DEFAULT_SERVER=false
if [ x"$1" = x"--default" ]
then
DEFAULT_SERVER=true
shift
fi
# Install some packages that we will definitely need:
apt-get install -y git-core lockfile-progs rubygems curl dnsutils lsb-release
# If we're not running on an EC2 instance, an empty body is returned
# by this request:
EC2_HOSTNAME=`curl -s http://169.254.169.254/latest/meta-data/public-hostname || true`
usage_and_exit() {
cat >&2 <<EOUSAGE
Usage: $0 [--default] <UNIX-USER> [HOST]
HOST is only optional if you are running this on an EC2 instance.
--default means to install as the default site for this server,
rather than a virtualhost for HOST.
EOUSAGE
exit 1
}
if [ $# = 1 ]
then
if [ x = x$EC2_HOSTNAME ]
then
usage_and_exit
else
HOST="$EC2_HOSTNAME"
fi
elif [ $# = 2 ]
then
HOST="$2"
else
usage_and_exit
fi
UNIX_USER="$1"
if [ $DEFAULT_SERVER = true ]
then
DIRECTORY="/var/www/$SITE"
else
DIRECTORY="/var/www/$HOST"
fi
REPOSITORY="$DIRECTORY/$SITE"
REPOSITORY_URL=git://github.com/mysociety/$SITE.git
BRANCH=master
DISTRIBUTION="$(lsb_release -i -s | tr A-Z a-z)"
VERSION="$(lsb_release -c -s)"
IP_ADDRESS_FOR_HOST="$(dig +short $HOST)"
if [ x = x"$IP_ADDRESS_FOR_HOST" ]
then
echo "The hostname $HOST didn't resolve to an IP address"
exit 1
fi
generate_locales() {
# If language-pack-en is present, install that:
apt-get install -y language-pack-en || true
# We get lots of locale errors if the en_GB.UTF-8 locale isn't
# present. (This is from Kagee's script.)
if [ "$(locale -a | egrep -i '^en_GB.utf-?8$' | wc -l)" = "1" ]
then
echo "en_GB.utf8 activated and generated"
else
echo "en_GB.utf8 not generated"
if [ x"$(grep -c '^en_GB.UTF-8 UTF-8' /etc/locale.gen)" = x1 ]
then
echo "'en_GB.UTF-8 UTF-8' already in /etc/locale.gen we will only generate"
else
echo "Appending 'en_GB.UTF-8 UTF-8' and 'cy_GB.UTF-8 UTF-8'"
echo "to /etc/locale.gen for generation"
echo "\nen_GB.UTF-8 UTF-8\ncy_GB.UTF-8 UTF-8" >> /etc/locale.gen
fi
echo "Generating new locales"
locale-gen
fi
}
set_locale() {
echo 'LANG="en_GB.UTF-8"' > /etc/default/locale
export LANG="en_GB.UTF-8"
}
add_unix_user() {
# Create the required user if it doesn't already exist:
if id "$1" 2> /dev/null > /dev/null
then
echo "The user $1 already exists."
else
adduser --disabled-password --gecos 'The FixMyStreet User' "$1"
fi
}
add_postgresql_user() {
su -l -c "createuser --createdb --no-createrole --no-superuser '$UNIX_USER'" postgres || true
}
update_apt_sources() {
if [ x"$DISTRIBUTION" = x"ubuntu" ] && [ x"$VERSION" = x"precise" ]
then
cat > /etc/apt/sources.list.d/mysociety-extra.list <<EOF
deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise multiverse
deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise multiverse
deb http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise-updates multiverse
deb-src http://eu-west-1.ec2.archive.ubuntu.com/ubuntu/ precise-updates multiverse
EOF
elif [ x"$DISTRIBUTION" = x"debian" ] && [ x"$VERSION" = x"squeeze" ]
then
# Install the basic packages we require:
cat > /etc/apt/sources.list.d/mysociety-extra.list <<EOF
# Debian mirror to use, including contrib and non-free:
deb http://the.earth.li/debian/ squeeze main contrib non-free
deb-src http://the.earth.li/debian/ squeeze main contrib non-free
# Security Updates:
deb http://security.debian.org/ squeeze/updates main non-free
deb-src http://security.debian.org/ squeeze/updates main non-free
# Debian Backports
deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free
deb-src http://backports.debian.org/debian-backports squeeze-backports main contrib non-free
EOF
else
echo Unsupport distribution and version combination $DISTRIBUTION $VERSION
exit 1
fi
apt-get update
}
clone_or_update_repository() {
# Clone the repository into place if the directory isn't already
# present:
if [ -d $REPOSITORY ]
then
echo the directory $REPOSITORY already exists
cd $REPOSITORY
git remote set-url origin "$REPOSITORY_URL"
git fetch origin
# Check that there are no uncommitted changes before doing a
# git reset --hard:
git diff --quiet || { echo "There were changes in the working tree in $REPOSITORY; exiting."; exit 1; }
git diff --cached --quiet || { echo "There were staged but uncommitted changes in $REPOSITORY; exiting."; exit 1; }
# If that was fine, carry on:
git reset --hard origin/"$BRANCH"
git submodule sync
git submodule update --recursive
else
PARENT="$(dirname $REPOSITORY)"
echo creating $PARENT
mkdir -p $PARENT
git clone --recursive --branch "$BRANCH" "$REPOSITORY_URL" "$REPOSITORY"
fi
}
install_nginx() {
apt-get install -y nginx libfcgi-procmanager-perl
}
add_website_to_nginx() {
UNIX_USER="$1"
HOST="$2"
REPOSITORY="$3"
NGINX_SITE="$HOST"
if [ $DEFAULT_SERVER = true ]
then
NGINX_SITE=default
fi
SITE_FILENAME=/etc/nginx/sites-available/"$NGINX_SITE"
SITE_LINK=/etc/nginx/sites-enabled/"$NGINX_SITE"
cp $REPOSITORY/conf/nginx.conf.example $SITE_FILENAME
sed -i "s,/var/www/$SITE,$DIRECTORY," $SITE_FILENAME
if [ $DEFAULT_SERVER = false ]
then
sed -i "/listen 80/a\
\ server_name $HOST;
" $SITE_FILENAME
fi
ln -nsf "$SITE_FILENAME" "$SITE_LINK"
LOG_DIRECTORY="$(readlink -f $REPOSITORY/../logs)"
mkdir -p "$LOG_DIRECTORY"
chown -R "$UNIX_USER"."$UNIX_USER" "$LOG_DIRECTORY"
/etc/init.d/nginx restart
}
install_sysvinit_script() {
SYSVINIT_FILENAME=/etc/init.d/$SITE
cp $REPOSITORY/conf/sysvinit.example $SYSVINIT_FILENAME
sed -i "s,/var/www/$SITE,$DIRECTORY,g" $SYSVINIT_FILENAME
sed -i "s/^ *USER=.*/USER=$UNIX_USER/" $SYSVINIT_FILENAME
chmod a+rx $SYSVINIT_FILENAME
update-rc.d $SITE start 20 2 3 4 5 . stop 20 0 1 6 .
/etc/init.d/$SITE restart
}
install_website_packages() {
EXACT_PACKAGES="$1/conf/packages.$DISTRIBUTION-$VERSION"
PRECISE_PACKAGES="$1/conf/packages.ubuntu-precise"
SQUEEZE_PACKAGES="$1/conf/packages.debian-squeeze"
GENERIC_PACKAGES="$1/conf/packages"
# If there's an exact match for the distribution and release, use that:
if [ -e "$EXACT_PACKAGES" ]
then
PACKAGES_FILE="$EXACT_PACKAGES"
# Otherwise, if this is Ubuntu, and there's a version specifically
# for precise, use that:
elif [ x"$DISTRIBUTION" = x"ubuntu" ] && [ -e "$PRECISE_PACKAGES" ]
then
PACKAGES_FILE="$PRECISE_PACKAGES"
# Otherwise, if this is Debian, and there's a version specifically
# for squeeze, use that:
elif [ x"$DISTRIBUTION" = x"debian" ] && [ -e "$SQUEEZE_PACKAGES" ]
then
PACKAGES_FILE="$SQUEEZE_PACKAGES"
else
PACKAGES_FILE="$GENERIC_PACKAGES"
fi
xargs -a "$PACKAGES_FILE" apt-get -y install
}
overwrite_rc_local() {
cat > /etc/rc.local <<EOF
#!/bin/sh -e
su -l -c $REPOSITORY/bin/ec2-rewrite-conf $UNIX_USER
/etc/init.d/$SITE restart
exit 0
EOF
chmod a+rx /etc/rc.local
}
generate_locales
set_locale
add_unix_user "$UNIX_USER"
update_apt_sources
# And remove one crippling package, if it's installed:
apt-get remove -y --purge apt-xapian-index || true
clone_or_update_repository $REPOSITORY
chown -R "$UNIX_USER"."$UNIX_USER" "$DIRECTORY"
install_nginx
install_website_packages "$REPOSITORY"
su -l -c "touch '$DIRECTORY/admin-htpasswd'" "$UNIX_USER"
add_website_to_nginx "$UNIX_USER" "$HOST" "$REPOSITORY"
add_postgresql_user "$UNIX_USER"
DEFAULT_PARAMETER=''
if [ $DEFAULT_SERVER = true ]
then
DEFAULT_PARAMETER='--default'
fi
su -l -c "$REPOSITORY/bin/install-as-user $DEFAULT_PARAMETER '$UNIX_USER' '$HOST'" "$UNIX_USER"
install_sysvinit_script
if [ $DEFAULT_SERVER = true ] && [ x != x$EC2_HOSTNAME ]
then
# If we're setting up as the default on an EC2 instance,
# make sure the ec2-rewrite-conf script is called from
# /etc/rc.local
overwrite_rc_local
fi
# Tell the user what to do next:
echo Installation complete - you should now be able to view the site at:
echo http://$HOST/
echo Or you can run the tests by switching to the "'$UNIX_USER'" user and
echo running: $REPOSITORY/bin/cron-wrapper prove -r t
|