diff options
Diffstat (limited to 'cluster/prod/app')
-rw-r--r-- | cluster/prod/app/backup/build/backup-garage/Dockerfile | 7 | ||||
-rw-r--r-- | cluster/prod/app/backup/build/backup-garage/do-backup.sh | 84 | ||||
-rw-r--r-- | cluster/prod/app/backup/deploy/backup-daily.hcl | 51 | ||||
-rw-r--r-- | cluster/prod/app/email/deploy/email-android7.hcl | 126 | ||||
-rw-r--r-- | cluster/prod/app/email/integration/README.md | 23 | ||||
-rw-r--r-- | cluster/prod/app/email/integration/tls-tls-proxy.sh | 13 | ||||
-rw-r--r-- | cluster/prod/app/email/secrets.toml | 9 | ||||
-rw-r--r-- | cluster/prod/app/matrix/build/docker-compose.yml | 10 | ||||
-rw-r--r-- | cluster/prod/app/matrix/config/synapse/homeserver.yaml | 2 | ||||
-rw-r--r-- | cluster/prod/app/matrix/deploy/im.hcl | 6 |
10 files changed, 319 insertions, 12 deletions
diff --git a/cluster/prod/app/backup/build/backup-garage/Dockerfile b/cluster/prod/app/backup/build/backup-garage/Dockerfile new file mode 100644 index 0000000..ea42331 --- /dev/null +++ b/cluster/prod/app/backup/build/backup-garage/Dockerfile @@ -0,0 +1,7 @@ +FROM alpine:3.17 + +RUN apk add rclone btrfs-progs curl bash jq + +COPY do-backup.sh /do-backup.sh + +CMD bash /do-backup.sh diff --git a/cluster/prod/app/backup/build/backup-garage/do-backup.sh b/cluster/prod/app/backup/build/backup-garage/do-backup.sh new file mode 100644 index 0000000..36ba2f2 --- /dev/null +++ b/cluster/prod/app/backup/build/backup-garage/do-backup.sh @@ -0,0 +1,84 @@ +#!/usr/bin/env bash + +# DEPENDENCIES: btrfs-progs curl rclone jq + +# PARAMETERS (environmenet variables) +# $BACKUP_BASEDIR => where to store backups and btrfs snapshots +# $GARAGE_ADMIN_TOKEN => Garage administration access token +# $GARAGE_ACCESS_KEY => Garage access key +# $GARAGE_SECRET_KEY => Garage secret key + +if [ -z "$BACKUP_BASEDIR" -o -z "$GARAGE_ACCESS_KEY" -o -z "$GARAGE_ADMIN_TOKEN" ]; then + echo "Missing parameters" +fi + +if [ ! -d "$BACKUP_BASEDIR/buckets" ]; then + btrfs subvolume create "$BACKUP_BASEDIR/buckets" +fi + + +function gcurl { + curl -s -H "Authorization: Bearer $GARAGE_ADMIN_TOKEN" $@ +} + +BUCKETS=$(gcurl "http://localhost:3903/v0/bucket" | jq -r '.[].id') + +for BUCKET in $BUCKETS; do + echo "==== BUCKET $BUCKET ====" + + gcurl "http://localhost:3903/v0/bucket?id=$BUCKET" > "$BACKUP_BASEDIR/buckets/$BUCKET.json" + + ALIASES=$(jq -r '.globalAliases[]' < "$BACKUP_BASEDIR/buckets/$BUCKET.json") + echo "(aka. $ALIASES)" + + case $ALIASES in + *backup*) + echo "Skipping $BUCKET (not doing backup of backup)" + ;; + *cache*) + echo "Skipping $BUCKET (not doing backup of cache)" + ;; + *) + echo "Backing up $BUCKET" + + if [ ! -d "$BACKUP_BASEDIR/buckets/$BUCKET" ]; then + mkdir "$BACKUP_BASEDIR/buckets/$BUCKET" + fi + + gcurl -X POST -H "Content-Type: application/json" --data @- "http://localhost:3903/v0/bucket/allow" >/dev/null <<EOF + { + "bucketId": "$BUCKET", + "accessKeyId": "$GARAGE_ACCESS_KEY", + "permissions": {"read": true} + } +EOF + + rclone sync --s3-endpoint http://localhost:3900 \ + --s3-access-key-id $GARAGE_ACCESS_KEY \ + --s3-secret-access-key $GARAGE_SECRET_KEY \ + --s3-region garage \ + --s3-force-path-style \ + --transfers 32 \ + --fast-list \ + --stats-one-line \ + --stats 10s \ + --stats-log-level NOTICE \ + ":s3:$BUCKET" "$BACKUP_BASEDIR/buckets/$BUCKET" 2>&1 + ;; + esac +done + +echo "========= DONE SYNCHRONIZING ==========" + +if [ ! -d "$BACKUP_BASEDIR/snapshots" ]; then + mkdir "$BACKUP_BASEDIR/snapshots" +fi + +SNAPSHOT="$BACKUP_BASEDIR/snapshots/buckets-$(date +%F)" +if [ ! -e "$SNAPSHOT" ]; then + echo "Making snapshot: $SNAPSHOT" + btrfs subvolume snapshot "$BACKUP_BASEDIR/buckets" "$SNAPSHOT" + btrfs prop set "$SNAPSHOT" ro true +fi + + diff --git a/cluster/prod/app/backup/deploy/backup-daily.hcl b/cluster/prod/app/backup/deploy/backup-daily.hcl index f3da8aa..96e97bc 100644 --- a/cluster/prod/app/backup/deploy/backup-daily.hcl +++ b/cluster/prod/app/backup/deploy/backup-daily.hcl @@ -1,5 +1,5 @@ job "backup_daily" { - datacenters = ["orion", "neptune"] + datacenters = ["orion", "neptune", "scorpio"] type = "batch" priority = "60" @@ -44,7 +44,7 @@ EOH resources { cpu = 500 memory = 100 - memory_max = 300 + memory_max = 1000 } restart { @@ -90,7 +90,7 @@ EOH resources { cpu = 500 memory = 100 - memory_max = 300 + memory_max = 1000 } restart { @@ -227,7 +227,52 @@ EOH resources { cpu = 500 + memory = 100 + memory_max = 1000 + } + + restart { + attempts = 2 + interval = "30m" + delay = "15s" + mode = "fail" + } + } + } + + group "backup-garage" { + constraint { + attribute = "${attr.unique.hostname}" + operator = "=" + value = "abricot" + } + + task "main" { + driver = "docker" + + config { + image = "lxpz/backup_garage:4" + network_mode = "host" + volumes = [ + "/mnt/storage/backup/garage.deuxfleurs.fr:/backup" + ] + } + + template { + data = <<EOH +BACKUP_BASEDIR=/backup +GARAGE_ADMIN_TOKEN={{ key "secrets/garage/admin_token" }} +GARAGE_ACCESS_KEY={{ key "secrets/backup/garage/s3_access_key_id" }} +GARAGE_SECRET_KEY={{ key "secrets/backup/garage/s3_secret_access_key" }} +EOH + destination = "secrets/env_vars" + env = true + } + + resources { + cpu = 500 memory = 200 + memory_max = 4000 } restart { diff --git a/cluster/prod/app/email/deploy/email-android7.hcl b/cluster/prod/app/email/deploy/email-android7.hcl new file mode 100644 index 0000000..967f58a --- /dev/null +++ b/cluster/prod/app/email/deploy/email-android7.hcl @@ -0,0 +1,126 @@ +job "email-android7" { + datacenters = ["neptune"] + type = "service" + priority = 100 + + group "rsa-ecc-proxy" { + network { + port "smtps" { + static = 465 + to = 465 + } + port "imaps" { + static = 993 + to = 993 + } + } + task "imaps-proxy" { + driver = "docker" + config { + image = "alpine/socat:1.7.4.4" + readonly_rootfs = true + ports = [ "imaps" ] + network_mode = "host" + args = [ + "openssl-listen:993,reuseaddr,fork,verify=0,bind=0.0.0.0,cert=/var/secrets/rsa.crt,key=/var/secrets/rsa.key", + "openssl:imap.deuxfleurs.fr:993,verify=0", + ] + volumes = [ + "secrets/certs:/var/secrets" + ] + } + + template { + data = "{{ key \"secrets/email/tls-tls-proxy/rsa.crt\" }}" + destination = "secrets/certs/rsa.crt" + } + template { + data = "{{ key \"secrets/email/tls-tls-proxy/rsa.key\" }}" + destination = "secrets/certs/rsa.key" + } + + resources { + cpu = 50 + memory = 50 + } + + service { + name = "imap-android7" + port = "imaps" + address_mode = "host" + tags = [ + "rsa-ecc-proxy", + "(diplonat (tcp_port 993))", + "d53-a imap-android7.deuxfleurs.fr", + # ipv6 is commented for now as socat does not listen on ipv6 now + # "d53-aaaa imap-android7.deuxfleurs.fr" + ] + check { + type = "tcp" + port = "imaps" + interval = "60s" + timeout = "5s" + check_restart { + limit = 3 + grace = "90s" + ignore_warnings = false + } + } + } + } + task "smtps-proxy" { + driver = "docker" + config { + image = "alpine/socat:1.7.4.4" + readonly_rootfs = true + network_mode = "host" + ports = [ "smtps" ] + args = [ + "openssl-listen:465,reuseaddr,fork,verify=0,bind=0.0.0.0,cert=/var/secrets/rsa.crt,key=/var/secrets/rsa.key", + "openssl:smtp.deuxfleurs.fr:465,verify=0", + ] + volumes = [ + "secrets/certs:/var/secrets" + ] + } + + template { + data = "{{ key \"secrets/email/tls-tls-proxy/rsa.crt\" }}" + destination = "secrets/certs/rsa.crt" + } + template { + data = "{{ key \"secrets/email/tls-tls-proxy/rsa.key\" }}" + destination = "secrets/certs/rsa.key" + } + + resources { + cpu = 50 + memory = 50 + } + + service { + name = "smtp-android7" + port = "smtps" + address_mode = "host" + tags = [ + "rsa-ecc-proxy", + "(diplonat (tcp_port 465))", + "d53-a smtp-android7.deuxfleurs.fr", + # ipv6 is commented for now as socat does not listen on ipv6 now + # "d53-aaaa smtp-android7.deuxfleurs.fr" + ] + check { + type = "tcp" + port = "smtps" + interval = "60s" + timeout = "5s" + check_restart { + limit = 3 + grace = "90s" + ignore_warnings = false + } + } + } + } + } +} diff --git a/cluster/prod/app/email/integration/README.md b/cluster/prod/app/email/integration/README.md new file mode 100644 index 0000000..d396277 --- /dev/null +++ b/cluster/prod/app/email/integration/README.md @@ -0,0 +1,23 @@ +# Email + +## TLS TLS Proxy + +Required for Android 7.0 that does not support elliptic curves. + +Generate a key: + +```bash +openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout rsa.key -out rsa.crt -subj "/CN=imap.deuxfleurs.fr" -addext "subjectAltName=DNS:smtp.deuxfleurs.fr" +``` + +Run the command: + +```bash +./integration/proxy.sh imap.deuxfleurs.fr:993 1993 +``` + +Test it: + +```bash +openssl s_client localhost:1993 +``` diff --git a/cluster/prod/app/email/integration/tls-tls-proxy.sh b/cluster/prod/app/email/integration/tls-tls-proxy.sh new file mode 100644 index 0000000..afb7317 --- /dev/null +++ b/cluster/prod/app/email/integration/tls-tls-proxy.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +UPSTREAM=$1 +PROXY_PORT=$2 +socat -dd \ +"openssl-listen:${PROXY_PORT},\ +reuseaddr,\ +fork,\ +cert=/tmp/tls-tls-proxy/rsa.crt,\ +key=/tmp/tls-tls-proxy/rsa.key,\ +verify=0,\ +bind=0.0.0.0" \ +"openssl:${UPSTREAM},\ +verify=0" diff --git a/cluster/prod/app/email/secrets.toml b/cluster/prod/app/email/secrets.toml index 6263e33..54bee46 100644 --- a/cluster/prod/app/email/secrets.toml +++ b/cluster/prod/app/email/secrets.toml @@ -21,3 +21,12 @@ password_secret = "email/sogo/ldap_bindpw" type = 'user' description = 'SoGo postgres auth (format: sogo:<password>) (TODO: replace this with two separate files and change template)' +# ---- TLS TLS PROXY --- + +[secrets."email/tls-tls-proxy/rsa.crt"] +type="user" +description="PEM encoded file containing the RSA certificate" + +[secrets."email/tls-tls-proxy/rsa.key"] +type="user" +description="PEM encoded file containing the RSA key" diff --git a/cluster/prod/app/matrix/build/docker-compose.yml b/cluster/prod/app/matrix/build/docker-compose.yml index 05bb91c..18a4fea 100644 --- a/cluster/prod/app/matrix/build/docker-compose.yml +++ b/cluster/prod/app/matrix/build/docker-compose.yml @@ -6,18 +6,18 @@ services: context: ./riotweb args: # https://github.com/vector-im/riot-web/releases - VERSION: 1.11.12 - image: superboum/amd64_riotweb:v32 + VERSION: 1.11.25 + image: superboum/amd64_riotweb:v33 synapse: build: context: ./matrix-synapse args: # https://github.com/matrix-org/synapse/releases - VERSION: 1.70.0 + VERSION: 1.79.0 # https://github.com/matrix-org/synapse-s3-storage-provider/commits/main # Update with the latest commit on main each time you update the synapse version # otherwise synapse may fail to launch due to incompatibility issues # see this issue for an example: https://github.com/matrix-org/synapse-s3-storage-provider/issues/64 - S3_VERSION: 40c6a5599b2d8176318003f84b167ea545cebba3 - image: superboum/amd64_synapse:v55 + S3_VERSION: v1.2.0 + image: superboum/amd64_synapse:v56 diff --git a/cluster/prod/app/matrix/config/synapse/homeserver.yaml b/cluster/prod/app/matrix/config/synapse/homeserver.yaml index 78eb913..aac8709 100644 --- a/cluster/prod/app/matrix/config/synapse/homeserver.yaml +++ b/cluster/prod/app/matrix/config/synapse/homeserver.yaml @@ -450,7 +450,7 @@ presence: enabled: false limit_remote_rooms: enabled: true - complexity: 3.0 + complexity: 10.0 complexity_error: "Ce salon de discussion a trop d'activité, le serveur n'est pas assez puissant pour le rejoindre. N'hésitez pas à remonter l'information à l'équipe technique, nous pourrons ajuster la limitation au besoin." admins_can_join: false retention: diff --git a/cluster/prod/app/matrix/deploy/im.hcl b/cluster/prod/app/matrix/deploy/im.hcl index 5bc6e13..0d5387e 100644 --- a/cluster/prod/app/matrix/deploy/im.hcl +++ b/cluster/prod/app/matrix/deploy/im.hcl @@ -14,7 +14,7 @@ job "matrix" { driver = "docker" config { - image = "superboum/amd64_synapse:v55" + image = "superboum/amd64_synapse:v56" network_mode = "host" readonly_rootfs = true ports = [ "api_port" ] @@ -98,7 +98,7 @@ job "matrix" { driver = "docker" config { - image = "superboum/amd64_synapse:v55" + image = "superboum/amd64_synapse:v56" readonly_rootfs = true command = "/usr/local/bin/matrix-s3-async" work_dir = "/tmp" @@ -142,7 +142,7 @@ EOH task "server" { driver = "docker" config { - image = "superboum/amd64_riotweb:v32" + image = "superboum/amd64_riotweb:v33" ports = [ "web_port" ] volumes = [ "secrets/config.json:/srv/http/config.json" |