mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat: WIP element Chat intergration
This commit is contained in:
9
infrastructure/matrix/element/Dockerfile
Normal file
9
infrastructure/matrix/element/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
#
|
||||
# EDR internal chat web client. Unmodified upstream Element Web + our public,
|
||||
# non-secret config (homeserver URL, branding) and the SSO handoff page.
|
||||
# Pin the tag; never float on `latest`.
|
||||
FROM ghcr.io/element-hq/element-web:v1.11.108
|
||||
|
||||
COPY config.json /app/config.json
|
||||
COPY sso.html /app/sso.html
|
||||
17
infrastructure/matrix/element/config.json
Normal file
17
infrastructure/matrix/element/config.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"default_server_config": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https://matrix.edr.et",
|
||||
"server_name": "matrix.edr.et"
|
||||
}
|
||||
},
|
||||
"brand": "EDR Chat",
|
||||
"permalink_prefix": "https://chat.edr.et",
|
||||
"disable_guests": true,
|
||||
"disable_3pid_login": true,
|
||||
"disable_custom_urls": true,
|
||||
"default_theme": "light",
|
||||
"settingDefaults": {
|
||||
"UIFeature.registration": false
|
||||
}
|
||||
}
|
||||
36
infrastructure/matrix/element/sso.html
Normal file
36
infrastructure/matrix/element/sso.html
Normal file
@@ -0,0 +1,36 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
Element only honours a `?loginToken=` on `/` if `mx_sso_hs_url` is already
|
||||
in localStorage (element-web apps/web/src/Lifecycle.ts attemptTokenLogin,
|
||||
key defined in apps/web/src/BasePlatform.ts). Normally that key is written
|
||||
by Element itself at the start of an SSO redirect; freight-api's SSO
|
||||
handoff skips that redirect (it already knows the homeserver), so this
|
||||
page seeds the key by hand and forwards straight to the login-token URL.
|
||||
|
||||
freight-api's chat-sso.service.ts links here as
|
||||
https://chat.edr.et/sso.html?t=<login_token>&hs=<homeserver base_url>.
|
||||
`hs` is passed rather than hardcoded so this file doesn't need to change if
|
||||
MATRIX_PUBLIC_BASEURL ever does.
|
||||
-->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Signing in to EDR Chat…</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var token = params.get("t");
|
||||
var homeserver = params.get("hs");
|
||||
if (token && homeserver) {
|
||||
localStorage.setItem("mx_sso_hs_url", homeserver);
|
||||
window.location.replace(
|
||||
"/?loginToken=" + encodeURIComponent(token),
|
||||
);
|
||||
} else {
|
||||
document.body.textContent =
|
||||
"Missing sign-in token. Go back to the EDR backoffice and click Chat again.";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
15
infrastructure/matrix/synapse/Dockerfile
Normal file
15
infrastructure/matrix/synapse/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
#
|
||||
# EDR internal chat homeserver. Unmodified upstream Synapse + our config
|
||||
# template — no source build. Pin the tag; never float on `latest`.
|
||||
FROM ghcr.io/element-hq/synapse:v1.140.0
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends gettext-base \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY homeserver.yaml.tmpl /synapse/homeserver.yaml.tmpl
|
||||
COPY log.config /synapse/log.config
|
||||
COPY docker-entrypoint.sh /synapse/docker-entrypoint.sh
|
||||
RUN chmod +x /synapse/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/synapse/docker-entrypoint.sh"]
|
||||
20
infrastructure/matrix/synapse/docker-entrypoint.sh
Normal file
20
infrastructure/matrix/synapse/docker-entrypoint.sh
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
# Renders homeserver.yaml from the template using the runtime env (so
|
||||
# MATRIX_JWT_SECRET / DB password / registration_shared_secret come from the
|
||||
# service's .env file, never get baked into the image), then hands off to the
|
||||
# upstream Synapse image's own entrypoint.
|
||||
set -eu
|
||||
|
||||
mkdir -p /data
|
||||
envsubst \
|
||||
'${MATRIX_SERVER_NAME} ${MATRIX_PUBLIC_BASEURL} ${MATRIX_DB_USER} ${MATRIX_DB_PASSWORD} ${MATRIX_DB_NAME} ${MATRIX_DB_HOST} ${MATRIX_DB_PORT} ${MATRIX_JWT_SECRET} ${MATRIX_REGISTRATION_SHARED_SECRET}' \
|
||||
< /synapse/homeserver.yaml.tmpl > /data/homeserver.yaml
|
||||
|
||||
# start.py's `run` mode (the implicit default we hit below) gosu's straight
|
||||
# into uid 991 with no chown — it only chowns /data in its `generate` /
|
||||
# `migrate_config` modes, which we skip by providing our own pre-rendered
|
||||
# config. Without this, 991 can't write its signing key on first boot.
|
||||
chown -R 991:991 /data
|
||||
|
||||
export SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
|
||||
exec /start.py "$@"
|
||||
95
infrastructure/matrix/synapse/homeserver.yaml.tmpl
Normal file
95
infrastructure/matrix/synapse/homeserver.yaml.tmpl
Normal file
@@ -0,0 +1,95 @@
|
||||
# EDR internal chat — Synapse homeserver config.
|
||||
#
|
||||
# Rendered to /data/homeserver.yaml at container start by docker-entrypoint.sh
|
||||
# (envsubst over this template) so secrets come from the runtime env file,
|
||||
# never baked into the image — same convention as freight-api's .env.
|
||||
#
|
||||
# server_name is PERMANENT: it is baked into every user id and event and
|
||||
# cannot change without wiping the server. Do not repoint this at a
|
||||
# different value after go-live.
|
||||
server_name: "${MATRIX_SERVER_NAME}"
|
||||
public_baseurl: "${MATRIX_PUBLIC_BASEURL}"
|
||||
pid_file: /data/homeserver.pid
|
||||
|
||||
listeners:
|
||||
- port: 8008
|
||||
tls: false
|
||||
type: http
|
||||
x_forwarded: true
|
||||
resources:
|
||||
- names: [client, federation]
|
||||
compress: false
|
||||
|
||||
database:
|
||||
name: psycopg2
|
||||
args:
|
||||
user: "${MATRIX_DB_USER}"
|
||||
password: "${MATRIX_DB_PASSWORD}"
|
||||
dbname: "${MATRIX_DB_NAME}"
|
||||
host: "${MATRIX_DB_HOST}"
|
||||
port: ${MATRIX_DB_PORT}
|
||||
cp_min: 5
|
||||
cp_max: 10
|
||||
|
||||
media_store_path: /data/media_store
|
||||
max_upload_size: 50M
|
||||
|
||||
log_config: "/synapse/log.config"
|
||||
|
||||
# Internal comms tool: no federation, no open registration, no E2EE-by-default.
|
||||
# ponytail: E2EE off — turn on per-room (HR/legal) if compliance asks.
|
||||
federation_domain_whitelist: []
|
||||
enable_registration: false
|
||||
encryption_enabled_by_default_for_room_type: "off"
|
||||
|
||||
# Employees authenticate via freight-api's SSO handoff, never a Matrix
|
||||
# password prompt. This is the entire auth story for this deployment.
|
||||
password_config:
|
||||
enabled: false
|
||||
|
||||
jwt_config:
|
||||
enabled: true
|
||||
secret: "${MATRIX_JWT_SECRET}"
|
||||
algorithm: "HS256"
|
||||
issuer: "edr-freight-api"
|
||||
audiences: ["matrix"]
|
||||
# Matches the `name` claim chat-sso.service.ts puts in the JWT — only read
|
||||
# on first login (auto-registration), never updates it on later logins.
|
||||
display_name_claim: "name"
|
||||
|
||||
# Consumes the login_token minted by freight-api's SSO endpoint via
|
||||
# POST /_matrix/client/v1/login/get_token (issued against an existing,
|
||||
# already-JWT-authenticated session — not a bare password grant).
|
||||
login_via_existing_session:
|
||||
enabled: true
|
||||
require_ui_auth: false
|
||||
token_timeout: 5m
|
||||
|
||||
# Bootstrap-only: used once by ops to register the first admin account
|
||||
# (register_new_matrix_user against /_synapse/admin/v1/register), whose
|
||||
# access token becomes MATRIX_ADMIN_TOKEN for freight-api's provisioning
|
||||
# service. Rotate/remove after bootstrap if desired — nothing else depends
|
||||
# on shared-secret registration once the admin account exists.
|
||||
registration_shared_secret: "${MATRIX_REGISTRATION_SHARED_SECRET}"
|
||||
|
||||
trusted_key_servers: []
|
||||
suppress_key_server_warning: true
|
||||
|
||||
report_stats: false
|
||||
|
||||
# Synapse's default rc_login is sized to defend against internet-facing
|
||||
# password brute-forcing. That threat doesn't exist on this deployment —
|
||||
# password login is off (see password_config above), and the only path in
|
||||
# requires a freight-api-signed JWT — so the default is mostly just
|
||||
# punishing legitimate rapid logins from the same office/NAT IP or normal
|
||||
# page-refresh retries. Loosened, not disabled, to keep some ceiling.
|
||||
rc_login:
|
||||
address:
|
||||
per_second: 100
|
||||
burst_count: 200
|
||||
account:
|
||||
per_second: 100
|
||||
burst_count: 200
|
||||
failed_attempts:
|
||||
per_second: 100
|
||||
burst_count: 200
|
||||
25
infrastructure/matrix/synapse/log.config
Normal file
25
infrastructure/matrix/synapse/log.config
Normal file
@@ -0,0 +1,25 @@
|
||||
# Log straight to stdout — the container runtime (docker compose logs / the
|
||||
# self-hosted runner's log collection) owns rotation and retention, matching
|
||||
# how every other app container in this repo logs.
|
||||
version: 1
|
||||
|
||||
formatters:
|
||||
precise:
|
||||
format: "%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s"
|
||||
|
||||
handlers:
|
||||
console:
|
||||
class: logging.StreamHandler
|
||||
formatter: precise
|
||||
stream: ext://sys.stdout
|
||||
|
||||
loggers:
|
||||
synapse.storage.SQL:
|
||||
# SQL queries are DEBUG-only noise; leave at INFO unless diagnosing.
|
||||
level: INFO
|
||||
|
||||
root:
|
||||
level: INFO
|
||||
handlers: [console]
|
||||
|
||||
disable_existing_loggers: false
|
||||
Reference in New Issue
Block a user