-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbootstrap.sh
437 lines (371 loc) · 13.8 KB
/
bootstrap.sh
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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
#!/bin/bash
# shellcheck disable=SC2181
# set -o xtrace
DOMAIN_SUFFIX=".$(echo "$VIRTUAL_HOST" | cut -d '.' -f2-)"
IS_STANDALONE=$([ -z "$VIRTUAL_HOST" ] && echo "true" )
indent() { sed 's/^/ /'; }
# Prepare waiting page during auto installation
cp /root/installing.html /var/www/html/installing.html
tee /etc/apache2/conf-enabled/install.conf << EOF
<Directory "/var/www/html">
AllowOverride None
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} !/installing.html$
RewriteRule .* /installing.html [L]
</Directory>
EOF
pkill -USR1 apache2
output() {
echo "$@"
echo "$@" >> /var/www/html/installing.html
}
fatal() {
output "======================================================================================="
output "$@"
output "======================================================================================="
exit 1
}
OCC() {
output "occ" "$@"
# shellcheck disable=SC2068
sudo -E -u www-data php "$WEBROOT/occ" $@ | indent
}
update_permission() {
chown -R www-data:www-data "$WEBROOT"/apps-writable
chown -R www-data:www-data "$WEBROOT"/data
chown www-data:www-data "$WEBROOT"/config
chown www-data:www-data "$WEBROOT"/config/config.php 2>/dev/null
if [ -f /shared/config.php ]
then
ln -sf /shared/config.php "$WEBROOT"/config/user.config.php
fi
}
configure_xdebug_mode() {
if [ -n "$PHP_XDEBUG_MODE" ]
then
sed -i "s/^xdebug.mode\s*=.*/xdebug.mode = ${PHP_XDEBUG_MODE//\//_}/" /usr/local/etc/php/conf.d/xdebug.ini
unset PHP_XDEBUG_MODE
else
echo "⚠ No value for PHP_XDEBUG_MODE was found. Not updating the setting."
fi
}
wait_for_other_containers() {
output "⌛ Waiting for other containers"
retry_with_timeout() {
local cmd=$1
local timeout=$2
local error_message=$3
local START_TIME=$SECONDS
while ! bash -c "$cmd"; do
if [ "$((SECONDS - START_TIME))" -ge "$timeout" ]; then
fatal "$error_message"
fi
sleep 2
done
}
case "$SQL" in
"mysql" | "mariadb-replica")
output " - MySQL"
retry_with_timeout "(echo > /dev/tcp/database-$SQL/3306) 2>/dev/null" 30 "⚠ Unable to connect to the MySQL server"
sleep 2
;;
"pgsql")
retry_with_timeout "(echo > /dev/tcp/database-pgsql/5432) 2>/dev/null" 30 "⚠ Unable to connect to the PostgreSQL server"
sleep 2
;;
"maxscale")
for node in database-mariadb-primary database-mariadb-replica; do
echo " - Waiting for $node"
retry_with_timeout "(echo > /dev/tcp/$node/3306) 2>/dev/null" 30 "⚠ Unable to reach to the $node"
retry_with_timeout "mysql -u root -pnextcloud -h $node -e 'SELECT 1' 2>/dev/null" 30 "⚠ Unable to connect to the $node"
echo "✅"
done
;;
"oci")
output " - Oracle"
retry_with_timeout "(echo > /dev/tcp/database-$SQL/1521) 2>/dev/null" 30 "⚠ Unable to connect to the Oracle server"
sleep 45
;;
"sqlite")
output " - SQLite"
;;
*)
fatal 'Not implemented'
;;
esac
[ $? -eq 0 ] && output "✅ Database server ready"
}
configure_gs() {
OCC config:system:set lookup_server --value=""
if [[ "$IS_STANDALONE" = "true" ]]; then
return 0
fi
get_protocol
LOOKUP_SERVER="${PROTOCOL}://lookup${DOMAIN_SUFFIX}/index.php"
MASTER_SERVER="${PROTOCOL}://portal${DOMAIN_SUFFIX}"
if [ "$GS_MODE" = "master" ]
then
OCC app:enable globalsiteselector
OCC config:system:set lookup_server --value "$LOOKUP_SERVER"
OCC config:system:set gs.enabled --type boolean --value true
OCC config:system:set gss.jwt.key --value 'random-key'
OCC config:system:set gss.mode --value 'master'
OCC config:system:set gss.master.admin 0 --value 'admin'
OCC config:system:set gss.master.csp-allow 0 --value "*${DOMAIN_SUFFIX}"
fi
if [ "$GS_MODE" = "slave" ]
then
OCC app:enable globalsiteselector
OCC config:system:set lookup_server --value "$LOOKUP_SERVER"
OCC config:system:set gs.enabled --type boolean --value true
OCC config:system:set gs.federation --value 'global'
OCC config:system:set gss.jwt.key --value 'random-key'
OCC config:system:set gss.mode --value 'slave'
OCC config:system:set gss.master.url --value "$MASTER_SERVER"
fi
}
configure_ldap() {
if [[ "$IS_STANDALONE" = "true" ]]; then
return 0
fi
timeout 5 bash -c 'until echo > /dev/tcp/ldap/389; do sleep 0.5; done' 2>/dev/null
if [ $? -eq 0 ]; then
output "LDAP server available"
export LDAP_USER_FILTER="(|(objectclass=inetOrgPerson))"
OCC app:enable user_ldap
OCC ldap:create-empty-config
OCC ldap:set-config s01 ldapAgentName "cn=admin,dc=planetexpress,dc=com"
OCC ldap:set-config s01 ldapAgentPassword "admin"
OCC ldap:set-config s01 ldapAttributesForUserSearch "sn;givenname"
OCC ldap:set-config s01 ldapBase "dc=planetexpress,dc=com"
OCC ldap:set-config s01 ldapEmailAttribute "mail"
OCC ldap:set-config s01 ldapExpertUsernameAttr "uid"
OCC ldap:set-config s01 ldapGroupDisplayName "description"
OCC ldap:set-config s01 ldapGroupFilter '(|(objectclass=groupOfNames))'
OCC ldap:set-config s01 ldapGroupFilterObjectclass 'groupOfNames'
OCC ldap:set-config s01 ldapGroupMemberAssocAttr 'member'
OCC ldap:set-config s01 ldapHost 'ldap'
OCC ldap:set-config s01 ldapLoginFilter "(&$LDAP_USER_FILTER(uid=%uid))"
OCC ldap:set-config s01 ldapLoginFilterMode '1'
OCC ldap:set-config s01 ldapLoginFilterUsername '1'
OCC ldap:set-config s01 ldapPort '389'
OCC ldap:set-config s01 ldapTLS '0'
OCC ldap:set-config s01 ldapUserDisplayName 'cn'
OCC ldap:set-config s01 ldapUserFilter "$LDAP_USER_FILTER"
OCC ldap:set-config s01 ldapUserFilterMode "1"
OCC ldap:set-config s01 ldapConfigurationActive "1"
fi
}
configure_oidc() {
if [[ "$IS_STANDALONE" = "true" ]]; then
return 0
fi
OCC app:enable user_oidc
get_protocol
OCC user_oidc:provider Keycloak -c nextcloud -s 09e3c268-d8bc-42f1-b7c6-74d307ef5fde -d "$PROTOCOL://keycloak${DOMAIN_SUFFIX}/realms/Example/.well-known/openid-configuration"
}
PROTOCOL="${PROTOCOL:-http}"
get_protocol() {
if [[ "$IS_STANDALONE" = "true" ]]; then
PROTOCOL=http
return 0
fi
}
configure_ssl_proxy() {
if [[ "$IS_STANDALONE" = "true" ]]; then
return 0
fi
get_protocol
if [[ "$PROTOCOL" == "https" ]]; then
echo "🔑 SSL proxy available, configuring overwrite.cli.url accordingly"
OCC config:system:set overwrite.cli.url --value "https://$VIRTUAL_HOST" &
else
echo "🗝 No SSL proxy, configuring overwrite.cli.url accordingly"
OCC config:system:set overwrite.cli.url --value "http://$VIRTUAL_HOST" &
fi
update-ca-certificates
}
configure_add_user() {
export OC_PASS=$1
OCC user:add --password-from-env "$1"
}
install() {
DBNAME=$(echo "$VIRTUAL_HOST" | cut -d '.' -f1)
SQLHOST="database-$SQL"
echo "database name will be $DBNAME"
USER="admin"
PASSWORD="admin"
run_hook_before_install
output "🔧 Starting auto installation"
if [ "$SQL" = "oci" ]; then
OCC maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database="$SQL" --database-name=FREE --database-host="$SQLHOST" --database-port=1521 --database-user=system --database-pass=oracle
elif [ "$SQL" = "pgsql" ]; then
OCC maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database="$SQL" --database-name="$DBNAME" --database-host="$SQLHOST" --database-user=postgres --database-pass=postgres
elif [ "$SQL" = "mysql" ]; then
OCC maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database="$SQL" --database-name="$DBNAME" --database-host="$SQLHOST" --database-user=root --database-pass=nextcloud
elif [ "$SQL" = "mariadb-replica" ]; then
OCC maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database="mysql" --database-name="$DBNAME" --database-host="database-mariadb-primary" --database-user=root --database-pass=nextcloud
elif [ "$SQL" = "maxscale" ]; then
sleep 10
# FIXME only works for main container as maxscale does not pass root along
OCC maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database="mysql" --database-name="$DBNAME" --database-host="database-mariadb-primary" --database-user=nextcloud --database-pass=nextcloud
OCC config:system:set dbhost --value="database-maxscale"
OCC config:system:set dbuser --value="nextcloud"
else
OCC maintenance:install --admin-user=$USER --admin-pass=$PASSWORD --database="$SQL"
fi;
output "🔧 Server installed"
output "🔧 Provisioning apps"
OCC app:disable password_policy
for app in $NEXTCLOUD_AUTOINSTALL_APPS; do
APP_ENABLED=$(OCC app:enable "$app")
output "$APP_ENABLED"
WAIT_TIME=0
until [[ $WAIT_TIME -eq ${NEXTCLOUD_AUTOINSTALL_APPS_WAIT_TIME:-0} ]] || [[ $APP_ENABLED =~ ${app}.*enabled$ ]]
do
# if app is not installed pause for 1 seconds and enable again
output "🔄 retrying"
sleep 1
APP_ENABLED=$(OCC app:enable "$app")
output "$APP_ENABLED"
((WAIT_TIME++))
done
done
configure_gs
configure_ldap
configure_oidc
output "🔧 Finetuning the configuration"
if [ "$WITH_REDIS" != "NO" ]; then
cp /root/redis.config.php "$WEBROOT"/config/
else
cp /root/apcu.config.php "$WEBROOT"/config/
fi
# Setup domains
# localhost is at index 0 due to the installation
INTERNAL_IP_ADDRESS=$(ip a show type veth | grep -o "inet [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*" | grep -o "[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*")
NEXTCLOUD_TRUSTED_DOMAINS="${NEXTCLOUD_TRUSTED_DOMAINS:-nextcloud} ${VIRTUAL_HOST} ${INTERNAL_IP_ADDRESS} localhost"
if [ -n "${NEXTCLOUD_TRUSTED_DOMAINS+x}" ]; then
echo "🔧 setting trusted domains…"
NC_TRUSTED_DOMAIN_IDX=1
for DOMAIN in $NEXTCLOUD_TRUSTED_DOMAINS ; do
DOMAIN=$(echo "$DOMAIN" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
OCC config:system:set trusted_domains $NC_TRUSTED_DOMAIN_IDX --value="$DOMAIN"
NC_TRUSTED_DOMAIN_IDX=$((NC_TRUSTED_DOMAIN_IDX + 1))
done
fi
TRUSTED_PROXY=$(ip a show type veth | awk '/scope global/ {print $2}')
OCC config:system:set trusted_proxies 0 --value="$TRUSTED_PROXY"
configure_ssl_proxy
output "🔧 Preparing cron job"
OCC dav:sync-system-addressbook
# Setup initial configuration
OCC background:cron
# Trigger initial cron run
sudo -E -u www-data php cron.php &
# run custom shell script from nc root
# [ -e /var/www/html/nc-dev-autosetup.sh ] && bash /var/www/html/nc-dev-autosetup.sh
output "🔧 Setting up users and LDAP in the background"
OCC user:setting admin settings email admin@example.net &
INSTANCENAME=$(echo "$VIRTUAL_HOST" | cut -d '.' -f1)
configure_add_user "${INSTANCENAME:-nextcloud}" &
configure_add_user user1 &
configure_add_user user2 &
configure_add_user user3 &
configure_add_user user4 &
configure_add_user user5 &
configure_add_user user6 &
configure_add_user jane &
configure_add_user john &
configure_add_user alice &
configure_add_user bob &
run_hook_after_install
output "🚀 Finished setup using $SQL database…"
}
run_hook_before_install() {
[ -e /shared/hooks/before-install.sh ] && bash /shared/hooks/before-install.sh
}
run_hook_after_install() {
[ -e /shared/hooks/after-install.sh ] && bash /shared/hooks/after-install.sh
}
run_hook_before_start() {
[ -e /shared/hooks/before-start.sh ] && bash /shared/hooks/before-start.sh
}
run_hook_after_start() {
[ -e /shared/hooks/after-start.sh ] && bash /shared/hooks/after-start.sh
}
add_hosts() {
echo "Add the host IP as host.docker.internal to /etc/hosts ..."
ip -4 route list match 0/0 | awk '{print $3 " host.docker.internal"}' >> /etc/hosts
}
setup() {
update_permission
configure_xdebug_mode
STATUS=$(OCC status)
if [[ "$STATUS" = *"installed: true"* ]] || [[ ! -f $WEBROOT/config/config.php ]]
then
output "🚀 Nextcloud already installed ... skipping setup"
# configuration that should be applied on each start
configure_ssl_proxy
else
# We copy the default config to the container
cp /root/default.config.php "$WEBROOT"/config/config.php
chown -R www-data:www-data "$WEBROOT"/config/config.php
mkdir -p "$WEBROOT/apps-extra"
mkdir -p "$WEBROOT/apps-shared"
update_permission
if [ "$NEXTCLOUD_AUTOINSTALL" != "NO" ]
then
add_hosts
install
else
touch "${WEBROOT}/config/CAN_INSTALL"
fi
fi
}
check_source() {
FILE=/var/www/html/status.php
if [ -f "$FILE" ]; then
output "Server source is mounted, continuing"
else
# Only autoinstall when not running in docker compose
if [ -n "$VIRTUAL_HOST" ] && [ ! -f "$WEBROOT"/version.php ]
then
output "======================================================================================="
output " 🚨 Could not find a valid Nextcloud source in $WEBROOT "
output " Double check your REPO_PATH_SERVER and STABLE_ROOT_PATH environment variables in .env "
output "======================================================================================="
exit 1
fi
output "Server source is not present, fetching ${SERVER_BRANCH:-master}"
git clone --depth 1 --branch "${SERVER_BRANCH:-master}" https://github.com/nextcloud/server.git /tmp/server
(cd /tmp/server && git submodule update --init)
output "Cloning additional apps"
git clone --depth 1 --branch "${SERVER_BRANCH:-master}" https://github.com/nextcloud/viewer.git /tmp/server/apps/viewer
# shallow clone of submodules https://stackoverflow.com/questions/2144406/how-to-make-shallow-git-submodules
git config -f .gitmodules submodule.3rdparty.shallow true
(cd /tmp/server && git submodule update --init)
rsync -a --chmod=755 --chown=www-data:www-data /tmp/server/ /var/www/html
chown www-data: /var/www/html
chown www-data: /var/www/html/.htaccess
fi
output "Nextcloud server source is ready"
}
(
check_source
wait_for_other_containers
setup
run_hook_before_start
rm /etc/apache2/conf-enabled/install.conf
rm -f /var/www/html/installing.html
pkill -USR1 apache2
run_hook_after_start
) &
touch /var/log/cron/nextcloud.log "$WEBROOT"/data/nextcloud.log /var/log/xdebug.log
chown www-data /var/log/xdebug.log
echo "📰 Watching log file"
tail --follow "$WEBROOT"/data/nextcloud.log /var/log/cron/nextcloud.log /var/log/xdebug.log &
echo "⌚ Starting cron"
/usr/sbin/cron -f &
echo "🚀 Starting apache"
exec "$@"