app/matrix: update software components, refactor config handling

Dynamic config generation based on environment variables in Synapse is
no longer supported. To pass secrets to container we use a patch that
implements configuration overrides via environment variables directly.
(to be upstreamed...)

Due to Synapse update, appservice configuration ConfigMaps don't need to
be copied into Synapse /data volume anymore.

Change-Id: I70e6480983bfb997362739c6ce0ec3c313320836
diff --git a/app/matrix/homeserver.yaml b/app/matrix/homeserver.yaml
new file mode 100644
index 0000000..d83dc3d
--- /dev/null
+++ b/app/matrix/homeserver.yaml
@@ -0,0 +1,137 @@
+# vim:ft=yaml

+

+## Server ##

+

+server_name: "hackerspace.pl"

+pid_file: /homeserver.pid

+web_client: False

+soft_file_limit: 0

+log_config: "/config/log.config"

+

+## Ports ##

+

+listeners:

+  - port: 8008

+    tls: false

+    bind_addresses: ['::']

+    type: http

+    x_forwarded: true

+

+    resources:

+      - names: [client]

+        compress: true

+      - names: [federation]

+        compress: false

+

+## Database ##

+

+database:

+  name: "psycopg2"

+  args:

+    user: "synapse"

+    database: "synapse"

+    host: "postgres"

+    port: "5432"

+    cp_min: 5

+    cp_max: 10

+

+

+## Performance ##

+

+event_cache_size: "10K"

+

+## Ratelimiting ##

+

+rc_messages_per_second: 0.2

+rc_message_burst_count: 10.0

+federation_rc_window_size: 1000

+federation_rc_sleep_limit: 10

+federation_rc_sleep_delay: 500

+federation_rc_reject_limit: 50

+federation_rc_concurrent: 3

+

+## Files ##

+

+media_store_path: "/data/media"

+uploads_path: "/data/uploads"

+max_upload_size: "10M"

+max_image_pixels: "32M"

+dynamic_thumbnails: false

+

+# List of thumbnail to precalculate when an image is uploaded.

+thumbnail_sizes:

+- width: 32

+  height: 32

+  method: crop

+- width: 96

+  height: 96

+  method: crop

+- width: 320

+  height: 240

+  method: scale

+- width: 640

+  height: 480

+  method: scale

+- width: 800

+  height: 600

+  method: scale

+

+url_preview_enabled: False

+max_spider_size: "10M"

+

+

+## Registration ##

+

+enable_registration: False

+bcrypt_rounds: 12

+allow_guest_access: True

+enable_group_creation: true

+

+# The list of identity servers trusted to verify third party

+# identifiers by this server.

+#

+# Also defines the ID server which will be called when an account is

+# deactivated (one will be picked arbitrarily).

+trusted_third_party_id_servers:

+    - matrix.org

+    - vector.im

+

+## Metrics ###

+

+enable_metrics: False

+report_stats: False

+

+

+## API Configuration ##

+

+room_invite_state_types:

+    - "m.room.join_rules"

+    - "m.room.canonical_alias"

+    - "m.room.avatar"

+    - "m.room.name"

+

+

+app_service_config_files: ["/appservices/irc-freenode/registration.yaml"]

+expire_access_token: False

+

+## Signing Keys ##

+

+signing_key_path: "/data/hackerspace.pl.signing.key"

+old_signing_keys: {}

+key_refresh_interval: "1d" # 1 Day.

+

+# The trusted servers to download signing keys from.

+perspectives:

+  servers:

+    "matrix.org":

+      verify_keys:

+        "ed25519:auto":

+          key: "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"

+

+password_config:

+   enabled: true

+

+cas_config:

+  enabled: true

+  server_url: "https://matrix.hackerspace.pl/_cas"

+  service_url: "https://matrix.hackerspace.pl"

diff --git a/app/matrix/homeserver.yaml.j2 b/app/matrix/homeserver.yaml.j2
deleted file mode 100644
index 75ac5aa..0000000
--- a/app/matrix/homeserver.yaml.j2
+++ /dev/null
@@ -1,233 +0,0 @@
-# vim:ft=yaml
-
-## TLS ##
-
-{% if not SYNAPSE_NO_TLS %}
-
-tls_certificate_path: "/data/{{ SYNAPSE_SERVER_NAME }}.tls.crt"
-tls_private_key_path: "/data/{{ SYNAPSE_SERVER_NAME }}.tls.key"
-
-{% if SYNAPSE_ACME %}
-acme:
-    enabled: true
-    port: 8009
-{% endif %}
-
-{% endif %}
-
-## Server ##
-
-server_name: "{{ SYNAPSE_SERVER_NAME }}"
-pid_file: /homeserver.pid
-web_client: False
-soft_file_limit: 0
-log_config: "/compiled/log.config"
-
-## Ports ##
-
-listeners:
-  {% if not SYNAPSE_NO_TLS %}
-  -
-    port: 8448
-    bind_addresses: ['::']
-    type: http
-    tls: true
-    x_forwarded: true
-    resources:
-      - names: [client]
-        compress: true
-      - names: [federation]  # Federation APIs
-        compress: false
-  {% endif %}
-
-  - port: 8008
-    tls: false
-    bind_addresses: ['::']
-    type: http
-    x_forwarded: true
-
-    resources:
-      - names: [client]
-        compress: true
-      - names: [federation]
-        compress: false
-
-## Database ##
-
-{% if POSTGRES_PASSWORD %}
-database:
-  name: "psycopg2"
-  args:
-    user: "{{ POSTGRES_USER or "synapse" }}"
-    password: "{{ POSTGRES_PASSWORD }}"
-    database: "{{ POSTGRES_DB or "synapse" }}"
-    host: "{{ POSTGRES_HOST or "db" }}"
-    port: "{{ POSTGRES_PORT or "5432" }}"
-    cp_min: 5
-    cp_max: 10
-{% else %}
-database:
-  name: "sqlite3"
-  args:
-    database: "/data/homeserver.db"
-{% endif %}
-
-## Performance ##
-
-event_cache_size: "{{ SYNAPSE_EVENT_CACHE_SIZE or "10K" }}"
-
-## Ratelimiting ##
-
-rc_messages_per_second: 0.2
-rc_message_burst_count: 10.0
-federation_rc_window_size: 1000
-federation_rc_sleep_limit: 10
-federation_rc_sleep_delay: 500
-federation_rc_reject_limit: 50
-federation_rc_concurrent: 3
-
-## Files ##
-
-media_store_path: "/data/media"
-uploads_path: "/data/uploads"
-max_upload_size: "{{ SYNAPSE_MAX_UPLOAD_SIZE or "10M" }}"
-max_image_pixels: "32M"
-dynamic_thumbnails: false
-
-# List of thumbnail to precalculate when an image is uploaded.
-thumbnail_sizes:
-- width: 32
-  height: 32
-  method: crop
-- width: 96
-  height: 96
-  method: crop
-- width: 320
-  height: 240
-  method: scale
-- width: 640
-  height: 480
-  method: scale
-- width: 800
-  height: 600
-  method: scale
-
-url_preview_enabled: False
-max_spider_size: "10M"
-
-## Captcha ##
-
-{% if SYNAPSE_RECAPTCHA_PUBLIC_KEY %}
-recaptcha_public_key: "{{ SYNAPSE_RECAPTCHA_PUBLIC_KEY }}"
-recaptcha_private_key: "{{ SYNAPSE_RECAPTCHA_PRIVATE_KEY }}"
-enable_registration_captcha: True
-recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
-{% else %}
-recaptcha_public_key: "YOUR_PUBLIC_KEY"
-recaptcha_private_key: "YOUR_PRIVATE_KEY"
-enable_registration_captcha: False
-recaptcha_siteverify_api: "https://www.google.com/recaptcha/api/siteverify"
-{% endif %}
-
-## Turn ##
-
-{% if SYNAPSE_TURN_URIS %}
-turn_uris:
-{% for uri in SYNAPSE_TURN_URIS.split(',') %}    - "{{ uri }}"
-{% endfor %}
-turn_shared_secret: "{{ SYNAPSE_TURN_SECRET }}"
-turn_user_lifetime: "1h"
-turn_allow_guests: True
-{% else %}
-turn_uris: []
-turn_shared_secret: "YOUR_SHARED_SECRET"
-turn_user_lifetime: "1h"
-turn_allow_guests: True
-{% endif %}
-
-## Registration ##
-
-enable_registration: {{ "True" if SYNAPSE_ENABLE_REGISTRATION else "False" }}
-registration_shared_secret: "{{ SYNAPSE_REGISTRATION_SHARED_SECRET }}"
-bcrypt_rounds: 12
-allow_guest_access: {{ "True" if SYNAPSE_ALLOW_GUEST else "False" }}
-enable_group_creation: true
-
-# The list of identity servers trusted to verify third party
-# identifiers by this server.
-#
-# Also defines the ID server which will be called when an account is
-# deactivated (one will be picked arbitrarily).
-trusted_third_party_id_servers:
-    - matrix.org
-    - vector.im
-
-## Metrics ###
-
-{% if SYNAPSE_REPORT_STATS.lower() == "yes" %}
-enable_metrics: True
-report_stats: True
-{% else %}
-enable_metrics: False
-report_stats: False
-{% endif %}
-
-## API Configuration ##
-
-room_invite_state_types:
-    - "m.room.join_rules"
-    - "m.room.canonical_alias"
-    - "m.room.avatar"
-    - "m.room.name"
-
-{% if SYNAPSE_APPSERVICES %}
-app_service_config_files:
-{% for appservice in SYNAPSE_APPSERVICES %}    - "{{ appservice }}"
-{% endfor %}
-{% else %}
-app_service_config_files: []
-{% endif %}
-
-macaroon_secret_key: "{{ SYNAPSE_MACAROON_SECRET_KEY }}"
-expire_access_token: False
-
-## Signing Keys ##
-
-signing_key_path: "/data/{{ SYNAPSE_SERVER_NAME }}.signing.key"
-old_signing_keys: {}
-key_refresh_interval: "1d" # 1 Day.
-
-# The trusted servers to download signing keys from.
-perspectives:
-  servers:
-    "matrix.org":
-      verify_keys:
-        "ed25519:auto":
-          key: "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"
-
-password_config:
-   enabled: true
-
-{% if SYNAPSE_SMTP_HOST %}
-email:
-   enable_notifs: false
-   smtp_host: "{{ SYNAPSE_SMTP_HOST }}"
-   smtp_port: {{ SYNAPSE_SMTP_PORT or "25" }}
-   smtp_user: "{{ SYNAPSE_SMTP_USER }}"
-   smtp_pass: "{{ SYNAPSE_SMTP_PASSWORD }}"
-   require_transport_security: False
-   notif_from: "{{ SYNAPSE_SMTP_FROM or "hostmaster@" + SYNAPSE_SERVER_NAME }}"
-   app_name: Matrix
-   # if template_dir is unset, uses the example templates that are part of
-   # the Synapse distribution.
-   #template_dir: res/templates
-   notif_template_html: notif_mail.html
-   notif_template_text: notif_mail.txt
-   notif_for_new_users: True
-   riot_base_url: "https://{{ SYNAPSE_SERVER_NAME }}"
-{% endif %}
-
-cas_config:
-  enabled: true
-  server_url: "https://matrix.hackerspace.pl/_cas"
-  service_url: "https://matrix.hackerspace.pl"
diff --git a/app/matrix/log.config b/app/matrix/log.config
new file mode 100644
index 0000000..58b9844
--- /dev/null
+++ b/app/matrix/log.config
@@ -0,0 +1,29 @@
+version: 1

+

+formatters:

+  precise:

+   format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s- %(message)s'

+

+filters:

+  context:

+    (): synapse.util.logcontext.LoggingContextFilter

+    request: ""

+

+handlers:

+  console:

+    class: logging.StreamHandler

+    formatter: precise

+    filters: [context]

+

+loggers:

+    synapse:

+        level: WARNING

+

+    synapse.storage.SQL:

+        # beware: increasing this to DEBUG will make synapse log sensitive

+        # information such as access tokens.

+        level: WARNING

+

+root:

+    level: WARNING

+    handlers: [console]
\ No newline at end of file
diff --git a/app/matrix/prod.jsonnet b/app/matrix/prod.jsonnet
index ac3e71f..447fb99 100644
--- a/app/matrix/prod.jsonnet
+++ b/app/matrix/prod.jsonnet
@@ -1,11 +1,8 @@
 # matrix.hackerspace.pl, a matrix/synapse instance
 # This needs a secret provisioned, create with:
-#    kubectl -n matrix create secret generic synapse --from-literal=postgres_password=$(pwgen 24 1)
+#    kubectl -n matrix create secret generic synapse --from-literal=postgres_password=$(pwgen 24 1) --from-literal=macaroon_secret_key=$(pwgen 32 1) --from-literal=registration_shared_secret=$(pwgen 32 1)
 #    kubectl -n matrix create secret generic oauth2-cas-proxy --from-literal=oauth2_secret=...
 #    kubectl -n matrix create secret generic appservice-irc-freenode-registration --from-file=registration.yaml=<(kubectl logs -n matrix $(kubectl get pods -n matrix --selector=job-name=appservice-irc-freenode-bootstrap --output=jsonpath='{.items[*].metadata.name}') | tail -n +4 | sed -r 's/(.*aliases:.*)/      group_id: "+freenode:hackerspace.pl"\n\1/')
-#
-#    TODO: /appservices/*/registration.yaml needs to be copied into /data/appservices/*.yaml manually
-#    kubectl exec -n matrix synapse-7b69cd5b6c-6686j -- sh -c 'mkdir /data/appservices ; cp /appservices/irc-freenode/registration.yaml /data/appservices/freenode-irc.yaml'
 
 local kube = import "../../kube/kube.libsonnet";
 local postgres = import "../../kube/postgres.libsonnet";
@@ -19,8 +16,8 @@
         serverName: "hackerspace.pl",
         storageClassName: "waw-hdd-paranoid-2",
 
-        synapseImage: "matrixdotorg/synapse:v0.99.4",
-        riotImage: "bubuntux/riot-web:v1.1.2",
+        synapseImage: "informatic/synapse:v1.2.1-env-conf-rev2", // https://github.com/Informatic/synapse/tree/env_config (to be upstreamed...)
+        riotImage: "bubuntux/riot-web:v1.3.2",
         casProxyImage: "registry.k0.hswaw.net/informatic/oauth2-cas-proxy:0.1.4"
     },
 
@@ -62,7 +59,8 @@
     synapseConfig: kube.ConfigMap("synapse") {
         metadata+: app.metadata("synapse"),
         data: {
-            "homeserver.yaml": importstr "homeserver.yaml.j2",
+            "homeserver.yaml": importstr "homeserver.yaml",
+            "log.config": importstr "log.config",
         },
     },
 
@@ -116,22 +114,16 @@
                                 http: { containerPort: 8008 },
                             },
                             env_: {
-                                SYNAPSE_SERVER_NAME: cfg.serverName,
-                                SYNAPSE_REPORT_STATS: "no",
-                                SYNAPSE_NO_TLS: "1",
-                                SYNAPSE_ALLOW_GUEST: "yes",
+                                SYNAPSE_CONFIG_PATH: "/config/homeserver.yaml",
 
-                                POSTGRES_HOST: "postgres",
-                                POSTGRES_USER: app.postgres.cfg.username,
-                                POSTGRES_PORT: "5432",
-                                POSTGRES_DB: app.postgres.cfg.database,
-                                POSTGRES_PASSWORD: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
+                                SYNAPSE_macaroon_secret_key: { secretKeyRef: { name: "synapse", key: "macaroon_secret_key" } },
+                                SYNAPSE_registration_shared_secret: { secretKeyRef: { name: "synapse", key: "registration_shared_secret" } },
+                                SYNAPSE_database__args__password: { secretKeyRef: { name: "synapse", key: "postgres_password" } },
                             },
                             volumeMounts_: {
                                 data: { mountPath: "/data" },
                                 config: {
-                                    mountPath: "/conf/homeserver.yaml",
-                                    subPath: "homeserver.yaml",
+                                    mountPath: "/config",
                                 },
                             } + {
                                 [k]: { mountPath: "/appservices/%s" % [k] }
@@ -226,6 +218,15 @@
                         url: "https://%s" % [cfg.domain],
                         domain: "%s" % [cfg.serverName],
                     },
+                    ircService+: {
+                        servers+: {
+                            "irc.freenode.net"+: {
+                                ircClients+: {
+                                    maxClients: 150,
+                                },
+                            },
+                        },
+                    },
                 },
             },
         },
@@ -265,7 +266,7 @@
         local bridge = self,
         local cfg = bridge.cfg,
         cfg:: {
-            image: "registry.k0.hswaw.net/informatic/matrix-appservice-irc:0.11.2",
+            image: "registry.k0.hswaw.net/informatic/matrix-appservice-irc:0.12.0",
             metadata: {},
             config: std.native("parseYaml")(importstr "appservice-irc.yaml")[0],
             storageClassName: app.cfg.storageClassName,