-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkolabctl
executable file
·491 lines (407 loc) · 15.3 KB
/
kolabctl
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
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
#!/bin/bash
set -e
export CONFIG=${CONFIG:-"config.prod"}
export HOST=${HOST:-"kolab.local"}
OPENEXCHANGERATES_API_KEY=${OPENEXCHANGERATES_API_KEY}
FIREBASE_API_KEY=${FIREBASE_API_KEY}
PUBLIC_IP=${PUBLIC_IP:-"127.0.0.1"}
export CERTS_PATH=./docker/certs
export POD=kolab-prod
export IMAP_SPOOL_STORAGE="--mount=type=volume,src=$POD-imap-spool,destination=/var/spool/imap,U=true"
export IMAP_LIB_STORAGE="--mount=type=volume,src=$POD-imap-lib,destination=/var/lib/imap,U=true"
export POSTFIX_SPOOL_STORAGE="--mount=type=volume,src=$POD-postfix-spool,destination=/var/spool/imap,U=true"
export POSTFIX_LIB_STORAGE="--mount=type=volume,src=$POD-postfix-lib,destination=/var/lib/imap,U=true"
export SYNAPSE_STORAGE="--mount=type=volume,src=$POD-synapse-data,destination=/data,U=true"
export MARIADB_STORAGE="--mount=type=volume,src=$POD-mariadb-data,destination=/var/lib/mysql,U=true"
export REDIS_STORAGE="--mount=type=volume,src=$POD-redis-data,destination=/var/lib/redis,U=true"
export MINIO_STORAGE="--mount=type=volume,src=$POD-minio-data,destination=/data,U=true"
export ENV_FILE=src/.env
export PODMAN_IGNORE_CGROUPSV1_WARNING=true
source bin/podman_shared
__export_env() {
source src/.env
export APP_WEBSITE_DOMAIN
export APP_DOMAIN
export DB_HOST
export IMAP_HOST
export IMAP_PORT
export IMAP_ADMIN_LOGIN
export IMAP_ADMIN_PASSWORD
export MAIL_HOST
export MAIL_PORT
export IMAP_DEBUG
export FILEAPI_WOPI_OFFICE
export CALENDAR_CALDAV_SERVER
export KOLAB_ADDRESSBOOK_CARDDAV_SERVER
export DB_ROOT_PASSWORD
export DB_USERNAME
export DB_PASSWORD
export DB_DATABASE
export REDIS_HOST
export REDIS_PASSWORD
export MINIO_USER
export MINIO_PASSWORD
export PASSPORT_PRIVATE_KEY
export PASSPORT_PUBLIC_KEY
export DES_KEY
export MEET_SERVER_TOKEN
export MEET_WEBHOOK_TOKEN
export KOLAB_SSL_CERTIFICATE
export KOLAB_SSL_CERTIFICATE_FULLCHAIN
export KOLAB_SSL_CERTIFICATE_KEY
export PUBLIC_IP
}
kolab__configure() {
if [[ "$1" == "--force" ]]; then
rm src/.env
fi
# Generate the .env once with all the necessary secrets
if [[ -f src/.env ]]; then
echo "src/.env already exists, not regenerating"
return
fi
cp "$CONFIG/src/.env" src/.env
if [[ -z $ADMIN_PASSWORD ]]; then
echo "Please enter your new infrastructure admin password used for various infrastructure components (mysql, imap, ...):"
read -r ADMIN_PASSWORD
fi
if [[ -z $PUBLIC_IP ]]; then
PUBLIC_IP=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p')
fi
# Generate random secrets
if ! grep -q "COTURN_STATIC_SECRET" src/.env; then
COTURN_STATIC_SECRET=$(openssl rand -hex 32);
echo "COTURN_STATIC_SECRET=${COTURN_STATIC_SECRET}" >> src/.env
fi
if ! grep -q "MEET_WEBHOOK_TOKEN" src/.env; then
MEET_WEBHOOK_TOKEN=$(openssl rand -hex 32);
echo "MEET_WEBHOOK_TOKEN=${MEET_WEBHOOK_TOKEN}" >> src/.env
fi
if ! grep -q "MEET_SERVER_TOKEN" src/.env; then
MEET_SERVER_TOKEN=$(openssl rand -hex 32);
echo "MEET_SERVER_TOKEN=${MEET_SERVER_TOKEN}" >> src/.env
fi
if ! grep -q "APP_KEY=base64:" src/.env; then
APP_KEY=$(openssl rand -base64 32);
echo "APP_KEY=base64:${APP_KEY}" >> src/.env
fi
if ! grep -q "PASSPORT_PROXY_OAUTH_CLIENT_ID=" src/.env; then
PASSPORT_PROXY_OAUTH_CLIENT_ID=$(uuidgen);
echo "PASSPORT_PROXY_OAUTH_CLIENT_ID=${PASSPORT_PROXY_OAUTH_CLIENT_ID}" >> src/.env
fi
if ! grep -q "PASSPORT_PROXY_OAUTH_CLIENT_SECRET=" src/.env; then
PASSPORT_PROXY_OAUTH_CLIENT_SECRET=$(openssl rand -base64 32);
echo "PASSPORT_PROXY_OAUTH_CLIENT_SECRET=${PASSPORT_PROXY_OAUTH_CLIENT_SECRET}" >> src/.env
fi
if ! grep -q "PASSPORT_SYNAPSE_OAUTH_CLIENT_ID=" src/.env; then
PASSPORT_SYNAPSE_OAUTH_CLIENT_ID=$(uuidgen);
echo "PASSPORT_SYNAPSE_OAUTH_CLIENT_ID=${PASSPORT_SYNAPSE_OAUTH_CLIENT_ID}" >> src/.env
fi
if ! grep -q "PASSPORT_SYNAPSE_OAUTH_CLIENT_SECRET=" src/.env; then
PASSPORT_SYNAPSE_OAUTH_CLIENT_SECRET=$(openssl rand -base64 32);
echo "PASSPORT_SYNAPSE_OAUTH_CLIENT_SECRET=${PASSPORT_SYNAPSE_OAUTH_CLIENT_SECRET}" >> src/.env
fi
if ! grep -q "PASSPORT_PUBLIC_KEY=|PASSPORT_PRIVATE_KEY=" src/.env; then
PASSPORT_PRIVATE_KEY=$(openssl genrsa 4096);
echo "PASSPORT_PRIVATE_KEY=\"${PASSPORT_PRIVATE_KEY}\"" >> src/.env
PASSPORT_PUBLIC_KEY=$(echo "$PASSPORT_PRIVATE_KEY" | openssl rsa -pubout 2>/dev/null)
echo "PASSPORT_PUBLIC_KEY=\"${PASSPORT_PUBLIC_KEY}\"" >> src/.env
fi
if ! grep -q "DES_KEY=" src/.env; then
DES_KEY=$(openssl rand -base64 24);
echo "DES_KEY=${DES_KEY}" >> src/.env
fi
# Customize configuration
sed -i \
-e "s/{{ host }}/${HOST}/g" \
-e "s/{{ openexchangerates_api_key }}/${OPENEXCHANGERATES_API_KEY}/g" \
-e "s/{{ firebase_api_key }}/${FIREBASE_API_KEY}/g" \
-e "s/{{ public_ip }}/${PUBLIC_IP}/g" \
-e "s/{{ admin_password }}/${ADMIN_PASSWORD}/g" \
src/.env
if [ -f /etc/letsencrypt/live/${HOST}/cert.pem ]; then
echo "Using the available letsencrypt certificate for ${HOST}"
cat >> src/.env << EOF
KOLAB_SSL_CERTIFICATE=/etc/letsencrypt/live/${HOST}/cert.pem
KOLAB_SSL_CERTIFICATE_FULLCHAIN=/etc/letsencrypt/live/${HOST}/fullchain.pem
KOLAB_SSL_CERTIFICATE_KEY=/etc/letsencrypt/live/${HOST}/privkey.pem
EOF
fi
}
kolab__deploy() {
if [[ -z $ADMIN_PASSWORD ]]; then
echo "Please enter your new admin password for the admin@$HOST user:"
read -r ADMIN_PASSWORD
fi
echo "Deploying $CONFIG on $HOST"
if [ `getenforce` == "Enforcing" ]; then
# Patches on how to correctly configure selinux are welcome
echo "selinux breaks networking, please disable"
exit 1
fi
if [[ ! -f src/.env ]]; then
echo "Missing src/.env file, run 'kolabctl configure' to generate"
exit 1
fi
if [[ "$1" == "--reset" ]]; then
kolab__reset --force
fi
__export_env
podman volume create $POD-imap-spool --ignore -l=kolab
podman volume create $POD-imap-lib --ignore -l=kolab
podman volume create $POD-postfix-spool --ignore -l=kolab
podman volume create $POD-postfix-lib --ignore -l=kolab
podman volume create $POD-synapse-data --ignore -l=kolab
podman volume create $POD-mariadb-data --ignore -l=kolab
podman volume create $POD-redis-data --ignore -l=kolab
podman volume create $POD-minio-data --ignore -l=kolab
kolab__build
# Create the pod first
$PODMAN pod create \
--replace \
--add-host=$HOST:127.0.0.1 \
--publish "443:6443" \
--publish "465:6465" \
--publish "587:6587" \
--publish "143:6143" \
--publish "993:6993" \
--publish "44444:44444/udp" \
--publish "44444:44444/tcp" \
--name $POD
podman__run_mariadb
podman__run_redis
podman__healthcheck $POD-mariadb $POD-redis
# IMAP must be avialable for the seeder
podman__run_imap
podman__healthcheck $POD-imap
podman__run_webapp
podman__healthcheck $POD-webapp
# Ensure all commands are processed
echo "Flushing work queue"
$PODMAN exec -ti $POD-webapp ./artisan queue:work --stop-when-empty
if [[ -n $ADMIN_PASSWORD ]]; then
podman exec $POD-webapp ./artisan user:password "admin@$APP_DOMAIN" "$ADMIN_PASSWORD"
fi
podman__run_synapse
podman__run_element
podman__run_minio
podman__healthcheck $POD-minio
podman__run_meet
podman__run_roundcube
podman__run_postfix
podman__run_amavis
podman__run_collabora
podman__run_proxy
echo "Deployment complete!"
}
kolab__reset() {
if [[ "$1" == "--force" ]]; then
REPLY="y"
else
read -p "Are you sure? This will delete the pod including all data. Type y to confirm." -n 1 -r
echo
fi
if [[ "$REPLY" =~ ^[Yy]$ ]];
then
podman pod rm --force $POD
volumes=($(podman volume ls -f name=$POD | awk '{if (NR > 1) print $2}'))
for v in "${volumes[@]}"
do
podman volume rm --force $v
done
fi
}
kolab__start() {
podman pod start $POD
}
kolab__stop() {
podman pod stop $POD
}
kolab__update() {
kolab__stop
podman pull quay.io/sclorg/mariadb-105-c9s
podman pull minio/minio:latest
podman pull almalinux:9
kolab__build
kolab__start
}
kolab__backup() {
backup_path="$(pwd)/backup/"
mkdir -p "$backup_path"
echo "Stopping containers"
kolab__stop
echo "Backing up volumes"
volumes=($(podman volume ls -f name=$POD | awk '{if (NR > 1) print $2}'))
for v in "${volumes[@]}"
do
podman export -o="$backup_path/$v.tar"
done
echo "Restarting containers"
kolab__start
}
kolab__restore() {
backup_path="$(pwd)/backup/"
echo "Stopping containers"
kolab__stop
# We currently expect the volumes to exist.
# We could alternatively create volumes form existing tar files
# for f in backup/*.tar; do
# echo "$(basename $f .tar)" ;
# done
echo "Restoring volumes"
volumes=($(podman volume ls -f name=$POD | awk '{if (NR > 1) print $2}'))
for v in "${volumes[@]}"
do
podman import $v "$backup_path/$v.tar"
done
echo "Restarting containers"
kolab__start
}
kolab__selfcheck() {
set -e
APP_DOMAIN=$(grep APP_DOMAIN src/.env | tail -n1 | sed "s/APP_DOMAIN=//")
if [ -z "$ADMIN_PASSWORD" ]; then
echo "Please enter your new admin password for the admin@$HOST user:"
read -r ADMIN_PASSWORD
fi
if [ -z "$ADMIN_USER" ]; then
ADMIN_USER="admin@$APP_DOMAIN"
fi
echo "Checking for containers"
podman__is_ready $POD-imap
podman__is_ready $POD-mariadb
podman__is_ready $POD-redis
podman__is_ready $POD-webapp
podman__is_ready $POD-minio
podman__is_ready $POD-meet
podman__is_ready $POD-roundcube
podman__is_ready $POD-postfix
podman__is_ready $POD-amavis
podman__is_ready $POD-collabora
podman__is_ready $POD-proxy
echo "All containers are available"
# We skip mollie and openexchange
podman exec $POD-webapp env APP_DEBUG=false ./artisan status:health --check DB --check Redis --check IMAP --check Roundcube --check Meet --check DAV
echo "Checking postfix authentication"
podman exec $POD-postfix testsaslauthd -u "$ADMIN_USER" -p "$ADMIN_PASSWORD"
echo "Checking imap authentication"
podman exec $POD-imap testsaslauthd -u "$ADMIN_USER" -p "$ADMIN_PASSWORD"
# podman run -ti --rm utils ./mailtransporttest.py --sender-username "$ADMIN_USER" --sender-password "$ADMIN_PASSWORD" --sender-host "127.0.0.1" --recipient-username "$ADMIN_USER" --recipient-password "$ADMIN_PASSWORD" --recipient-host "127.0.0.1" --recipient-port "11143"
# podman run -ti --rm utils ./kolabendpointtester.py --verbose --host "$APP_DOMAIN" --dav "https://$APP_DOMAIN/dav/" --imap "$APP_DOMAIN" --activesync "$APP_DOMAIN" --user "$ADMIN_USER" --password "$ADMIN_PASSWORD"
echo "All tests have passed!"
}
kolab__ps() {
command podman ps | grep $POD
}
kolab__exec() {
container=$1
shift
command podman exec -ti $POD-$container $@
}
kolab__run() {
__export_env
podman__run_$1
}
kolab__pull() {
podman pull quay.io/apheleiait/kolab/imap:latest
podman tag kolab/imap:latest kolab-imap:latest
podman pull quay.io/apheleiait/kolab/webapp:latest
podman tag kolab/webapp:latest kolab-webapp:latest
podman pull quay.io/apheleiait/kolab/collabora:latest
podman tag kolab/collabora:latest kolab-collabora:latest
podman pull quay.io/apheleiait/kolab/redis:latest
podman tag kolab/redis:latest redis:latest
podman pull quay.io/apheleiait/kolab/roundcube:latest
podman tag kolab/roundcube:latest roundcube:latest
podman pull quay.io/apheleiait/kolab/mariadb:latest
podman tag kolab/mariadb:latest mariadb:latest
podman pull quay.io/apheleiait/kolab/meet:latest
podman tag kolab/meet:latest kolab-meet:latest
podman pull quay.io/apheleiait/kolab/coturn:latest
podman tag kolab/coturn:latest kolab-coturn:latest
podman pull quay.io/apheleiait/kolab/postfix:latest
podman tag kolab/postfix:latest kolab-postfix:latest
podman pull quay.io/apheleiait/kolab/amavis:latest
podman tag kolab/amavis:latest kolab-amavis:latest
podman pull quay.io/apheleiait/kolab/utils:latest
podman tag kolab/utils:latest kolab-utils:latest
podman pull quay.io/apheleiait/kolab/minio:latest
podman tag kolab/minio:latest minio/minio:latest
podman pull quay.io/apheleiait/kolab/proxy:latest
podman tag kolab/proxy:latest kolab-proxy:latest
# podman pull quay.io/apheleiait/kolab/synapse:latest
# podman tag kolab/synapse:latest synapse:latest
# podman pull quay.io/apheleiait/kolab/element:latest
# podman tag kolab/element:latest element:latest
}
kolab__build() {
pin_git_refs
if [[ $1 != "" ]]; then
podman__build_$1
else
podman__build_base
podman__build_webapp
podman__build_meet
podman__build_imap
podman__build docker/mariadb mariadb
podman__build docker/redis redis
podman__build_proxy
podman__build docker/synapse synapse
podman__build docker/element element
podman__build_roundcube
podman__build_utils
podman__build_postfix
podman__build_amavis
podman__build_collabora
env CERT_DIR=docker/certs APP_DOMAIN=$HOST bin/regen-certs
fi
}
kolab__cyradm() {
# command podman exec -ti $POD-imap cyradm --auth PLAIN -u admin@kolab.local -w simple123 --port 11143 localhost
if [[ "$@" ]]; then
command podman exec -ti $POD-imap echo "$@" | cyradm --auth PLAIN -u $(grep IMAP_ADMIN_LOGIN src/.env | cut -d '=' -f 2 ) -w $(grep IMAP_ADMIN_PASSWORD src/.env | cut -d '=' -f 2 ) --port 11143 localhost
else
command podman exec -ti $POD-imap cyradm --auth PLAIN -u $(grep IMAP_ADMIN_LOGIN src/.env | cut -d '=' -f 2 ) -w $(grep IMAP_ADMIN_PASSWORD src/.env | cut -d '=' -f 2 ) --port 11143 localhost
fi
}
kolab__shell() {
kolab__exec $1 /bin/bash
}
kolab__run() {
__export_env
podman__run_$1
}
kolab__logs() {
command podman logs -f $POD-$1
}
kolab__help() {
cat <<EOF
This is the kolab commandline utility.
The following commands are available:
configure: Initial configuration.
deploy: Deploy kolab in the kolab-prod pod. Can be re-executed without loosing data.
build: Build all containers (Automatically executed as part of deploy).
reset: Remove pod and all volumes. Will delete all data.
start: Start pod
stop: Stop pod
update: This will update all containers.
backup: Create a backup in backup/
restore: Restore a backup from backup/
selfcheck: Run a selfcheck to ensure kolab is functional
shell: Get a shell in the given container.
run: Re-run an individual container.
exec: exec inside the given container.
logs: Access logs of the given container.
cyradm: Get a cyradm shell
EOF
}
cmdname=$1
shift
# make sure we actually *did* get passed a valid function name
if declare -f "kolab__$cmdname" >/dev/null 2>&1; then
"kolab__$cmdname" "${@:1}"
else
echo "Function $cmdname not recognized" >&2
kolab__help
exit 1
fi