Commit Graph
226 Commits
Author SHA1 Message Date
Thore CimbalandClaude Fable 5 b15a9f578c element: 11 neue Themes - aXion1337 Light plus zehn Paletten
aXion1337 Light ist das exakte helle Gegenstueck zum Lieblingstheme: 'aXion1337
Dark' ist Gruvbox Dark (Farben und die acht Username-Farben sind die
Gruvbox-Palette), also ist Gruvbox Light das stilistische Analogon - gleiche
Rollenverteilung, gleiche Akzentfamilie, nur die Helligkeitsachse gespiegelt.

Dazu zehn benannte Paletten mit vollem Schluesselsatz (24 Farben inkl.
username-colors): Ocean Depths, Sunset Boulevard, Forest Canopy, Modern
Minimalist, Golden Hour, Arctic Frost, Desert Rose, Tech Innovation, Botanical
Garden, Midnight Galaxy - vier davon hell.

Chirurgisch eingefuegt (Lehre vom 2026-07-30): die YAML wurde nicht geparst und
nicht neu serialisiert, nur Text vor der schliessenden Array-Klammer ergaenzt.
Diff-Bilanz 0 entfernte / 427 neue Zeilen, YAML und eingebettetes JSON validiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 d4f3fc4c97 element-web: Bump auf kanonisches CI-Image v0.3.0 (ThreadNet-Web#8)
Exec-Bit + Call-Widget + config.json im frischen Image verifiziert
(docker pull + Inspektion). Ersetzt die Derivat-Linie v0.3.0-clientscan.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 dfe7ff9fc0 element-values: Originalformat wiederhergestellt, Aenderung chirurgisch
Der naechtliche YAML-Redump (9aa42f9/e963203) hatte Kommentare und
Formatierung der Datei zerstoert - semantisch war er korrekt (verifiziert),
aber wartungsfeindlich. Jetzt: Original von c631b0a + exakt die 5 Zeilen
aus ThreadNet-Web#1 (4 Feature-Flags + setting_default). Effektive Config
byte-identisch mit dem bereits deployten Stand.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 11f97b935f element-web: Feature-Defaults an Desktop-Config angeglichen (ThreadNet-Web#1)
Web-Deploy war Teilmenge der Desktop-Defaults: video_rooms, group_calls,
element_call_video_rooms, new_room_decoration_ui + setting_default
feature_group_calls ergaenzt. Discord-Raumliste war schon beidseitig an.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 717638d12c chore(coturn): TURN-Rotation 2026-08-01 uebernommen (kanonischer Weg via git.lab)
Automatischer Rotations-PR (Gitea #46) darf seit der Topologie-Umstellung
nicht mehr auf dem Mirror gemergt werden - Branch vom Mirror geholt und
hier kanonisch gemergt; der Push-Mirror traegt den Stand zurueck.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
turn-secret-rotation 60248bfd92 chore(coturn): automated TURN shared-secret rotation
Scheduled rotation (Issue #38). New secret generated, re-encrypted with
the scoped rotation age key, checksum/rotated-at annotations bumped so
Flux restarts coturn + synapse-main on merge. Please review and merge.
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 228807fcc8 monitoring: doppelten node-exporter entfernt (gitops#45)
Das prometheus-node-exporter-HelmRelease (hostNetwork) kollidierte auf
dem Host mit dem etablierten systemd-Exporter auf Port 9100 und konnte
seit Anlage nie binden (4883 Restarts, CrashLoopBackOff). Host-Metriken
kommen weiterhin vom systemd-Dienst, den CFGMON direkt via 10.0.0.2:9100
scrapt - das DaemonSet haette sie nur dupliziert. Alloy-Scrape auf den
verwaisten Service ebenfalls entfernt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore CimbalandClaude Fable 5 6f761da1a4 monitoring: Alloy-Synapse-Scrape auf den echten Metrics-Port 9001 korrigiert
Der Service matrix-stack-synapse-main exponiert 8008/9093/8080/9001
(synapse-metrics = 9001) - Port 9000 existiert nicht, der Scrape war
seit Anlage tot. Aufgedeckt durch den ersten TargetDown-Alarm des neuen
Alertings (gitops#32) direkt nach dem Deploy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKhFj1S3UdD6xL2fbWPeYj
2026-08-01 12:00:00 +00:00
Thore Cimbal 5ca8f00d58 feat: deploy full ThreadNet-Web rebuild with client-side content scanning
First full rebuild deployed to production (previous releases used the
widgets/element-call/-only patch workaround, fixed but not cut over in
Issue #12). Includes the new client-side scan hooks (DecryptFile.ts,
ContentMessages.ts) that cover encrypted rooms, which the server-side
Synapse module (Issue #19) structurally cannot see.
2026-07-29 12:00:00 +00:00
Thore Cimbal 7b19586179 feat: deploy client-side ClamAV scan service for encrypted rooms
Synapse's own media-scanning module (Issue #19) can never see E2EE
attachment content - a structural limit, not a bug. This adds a small
standalone HTTP wrapper around the same ClamAV instance, reachable
from browser JS at /_scan, so the ThreadNet-Web client fork can scan
plaintext both before encrypting/uploading and after downloading/
decrypting - covering both directions regardless of room encryption.
Auth via Synapse's own /whoami endpoint, no separate auth system.
2026-07-29 12:00:00 +00:00
Thore Cimbal 7ac584d27b fix: use Twisted networking instead of asyncio in ClamAV module
Synapse runs on Twisted's reactor, not asyncio's event loop - the
original asyncio.open_connection/wait_for calls failed immediately
with "RuntimeError: no running event loop", silently fail-opening
every scan (confirmed live: EICAR test file passed through unscanned).
Rewritten using twisted.internet.endpoints.HostnameEndpoint/
connectProtocol and a custom Protocol for the INSTREAM conversation.
2026-07-29 12:00:00 +00:00
Thore Cimbal 9db1ee6f45 feat: real media antivirus scanning via custom Synapse module (Issue #19)
Deploys ClamAV and a small stdlib-only Synapse spam-checker module
implementing check_media_file_for_spam over clamd's INSTREAM protocol.
Unlike the originally-considered matrix-content-scanner proxy (which
needs client-side cooperation neither Element Web nor Element X
provide), this hooks Synapse's own module API directly - transparent
to every client for unencrypted media. No custom Synapse image needed:
the module is mounted via a ConfigMap onto PYTHONPATH using the ESS
chart's extraVolumes/extraVolumeMounts/extraEnv support. Fails open on
scanner errors so a ClamAV outage can't block all uploads.
2026-07-29 12:00:00 +00:00
Thore Cimbal bb51047e1d feat: enable experimentalRustCrypto for Draupnir management room
Testing E2EE support for the management room per user request - marked
"not considered production safe" upstream, verifying no regressions
before deciding to keep it.
2026-07-29 12:00:00 +00:00
Thore Cimbal f58add72ae fix: pass explicit --draupnir-config path (v3.x dropped auto-discovery)
Confirmed by extracting dist/config.js from the actual image - v3.x's
getConfigPath() only checks --draupnir-config/--mjolnir-config CLI
flags, no longer NODE_CONFIG_DIR/node-config auto-discovery.
2026-07-29 12:00:00 +00:00
Thore Cimbal 5e16719bfe fix: pin Draupnir to v3.1.0 instead of v2.9.0
initialManager's automatic management-room creation (no manual room
setup needed) only works on v3.1.0+ - v2.9.0 crashed on first startup
trying to join a room that was never created.
2026-07-29 12:00:00 +00:00
Thore Cimbal 7cd177f744 feat: deploy Draupnir moderation bot (Issue #18)
Bot account registered via mas-cli, compatibility token issued and
stored via sops. Adds an explicit NetworkPolicy allow-rule since
Draupnir needs to reach Synapse's client-server API in-namespace,
which the existing default-deny policy would otherwise silently block.
2026-07-29 12:00:00 +00:00
Thore Cimbal 23c66c97b8 revert: roll back VP9/AV1 codec test (Issue #11)
Real testing (Safari + Firefox, fresh rejoins) confirmed VP9 selection
always falls back to VP8 - our fork's buildPublishOptions() forces
simulcast:true unconditionally, which breaks LiveKit's SVC negotiation
path that vp9/av1 require. This is the same failure mode originally
suspected in the 2026-07-28 incident; the "LiveKit handles this
automatically" assumption from doc research did not hold up in
practice. Reverting to the known-safe VP8/H.264/H.265 SFU allow-list
and widget image. Root cause documented in Issue #11 for a future,
scoped fix (conditional simulcast vs. scalabilityMode per codec).
2026-07-29 12:00:00 +00:00
Thore Cimbal 9fa88bda5c test: deploy VP9/AV1-enabled element-call widget (Issue #11)
Patches the re-enabled VP9/AV1 codec dropdown (threadnet-call) onto the
existing v0.1.0 base image. Test-only tag - to be reverted or made
permanent depending on real call test results.
2026-07-29 12:00:00 +00:00
Thore Cimbal 105194d450 feat: enable VP9/AV1 codecs at LiveKit SFU (Issue #11 test)
Appends video/VP9 and video/AV1 to the SFU's room.enabled_codecs
allow-list via matrixRTC.sfu.additional, keeping all currently
negotiated codecs unchanged. Opt-in test per Issue #11 - codecs
become selectable, not the new default.
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 174c58001b fix(element-call): limit codec dropdown to codecs the SFU actually supports
Live-verified via matrix-rtc-sfu logs: VP9 gets silently rejected and
falls back to VP8 (SFU's enabledPublishCodecs is [VP8, H264, H265], no
VP9/AV1). Dropdown now only offers those three; also fixed
screenShareCodec's default which was "vp9" (fork commit ac99cc65 in
threadnet-call).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 5f7fd8bc46 i18n(element-call): add German translations for camera/screen share settings
The MediaQualitySettings labels moved into the Video tab had no German
translations at all (en/app.json had all 10 keys, de/app.json had none) -
fork commit f13c4b43 in threadnet-call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 13385b68f2 feat(element-call): expose camera/screen share quality settings in Video tab
Moved from behind the Developer-mode toggle into the regular Video
settings tab (fork commit f61650c0 in threadnet-call) - these are just
resolution/framerate/bitrate/codec pickers, not actually developer-only
functionality, just accidentally buried where most users would never
find them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 2932ffffc3 fix(matrix-stack): shorten HelmRelease reconcile interval to 1m
Live-tested Issue #38's rotation: after merging the automated rotation
PR, coturn restarted quickly (Kustomization-level, 1m interval), but
synapse-main lagged behind since it depends on this separate HelmRelease
with its own 5m interval - a real (self-healing, but avoidable) window
where coturn had the new TURN secret and Synapse still had the old one,
which would reject each other's credentials/relayed media. Matching the
interval to production-apps's 1m tightens that window without needing
any new automation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
turn-secret-rotation 802e09cd9c chore(coturn): automated TURN shared-secret rotation
Scheduled rotation (Issue #38). New secret generated, re-encrypted with
the scoped rotation age key, checksum/rotated-at annotations bumped so
Flux restarts coturn + synapse-main on merge. Please review and merge.
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 debf980d5f fix(turn-rotation): add hostAliases for private-network Gitea access
Job hung indefinitely on git clone - public-internet reachability to
rohana.axion1337.de from inside pods is currently down (related to
Issue #41's firewall/private-network findings), and the node-level
/etc/hosts workaround only helps containerd's image pulls, not processes
running inside pods (they resolve via CoreDNS + their own /etc/hosts, not
the node's). hostAliases routes this job's git/API traffic over the
private Hetzner network directly - verified working with a real pod.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore Cimbal d742c99ba5 chore: set Gitea PAT for TURN secret rotation job 2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 ac7e65100d feat(coturn): add automated TURN shared-secret rotation CronJob
Closes issue #38's automation half (architecture fix + first rotation
already landed in earlier commits this session). Monthly CronJob
(rohana.axion1337.de/sorb/axion-secret-rotation:v1 - alpine + git/sops/
jq/age) that:

- generates a new secret
- re-encrypts coturn-secret.yaml and synapse-turn-secret.yaml using the
  scoped rotation-only age key (added as an additional recipient in an
  earlier commit) - never touches the repo's master sops-age key
- bumps the turn-secret-checksum (HelmRelease annotation) and rotated-at
  (coturn Deployment annotation) so merging actually restarts both
  consumers, reusing the existing checksum-annotation pattern already in
  this repo rather than inventing a new mechanism
- opens a Pull Request rather than pushing straight to main - a human
  reviews and merges, keeping a checkpoint before production picks up new
  credentials while still automating the tedious coordination work

Needs a Gitea PAT (repo write scope) filled into
turn-secret-rotation-secret.yaml's gitea-token key before first use.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 be95bd921c feat(coturn): add scoped age recipient for automated rotation job
Adds a second age recipient (dedicated keypair, private key never touches
the repo) to just these two files, so the upcoming rotation CronJob can
decrypt/re-encrypt them without needing the repo's master sops-age key,
which can decrypt every secret in the repo. Verified: master key still
decrypts both files; the new scoped key can decrypt both files but
correctly cannot decrypt an unrelated secret (authentik-secret.yaml).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore Cimbal 7795f89fc9 docs(coturn): note the one-time manual rollingUpdate fix instead of an ineffective YAML null 2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 9fa947cc21 fix(coturn): explicitly null rollingUpdate field alongside Recreate strategy
Server-side apply left the old RollingUpdate defaults (maxSurge/maxUnavailable)
on the live object from before strategy.type was ever set explicitly, which
the API rejects when combined with type: Recreate. Explicit null clears it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 233b13f972 fix(coturn): use Recreate deployment strategy for hostNetwork pod
Discovered live: the default RollingUpdate strategy tries to schedule the
new pod before removing the old one, which can never succeed for a
hostNetwork Deployment on a single-node cluster (both pods would need the
same node ports 3478/5349 simultaneously). Surfaced by the rotated-at
annotation bump from the previous commit getting stuck in
FailedScheduling. Recreate kills the old pod first, freeing the ports.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 51ea51352b fix(coturn): remove plaintext TURN shared secret, rotate leaked value
Issue #38 discussion surfaced a real bug: the TURN shared secret was
duplicated - correctly SOPS-encrypted in coturn-secret.yaml, but also
hardcoded in plaintext in synapse-values.yaml (a plain, non-SOPS
ConfigMap), visible in git history. Also found turn_user_lifetime is
86400000ms (24h), not "short-lived" as previously assumed - raising the
stakes of the leak somewhat.

Extracted the turn config block into its own dedicated SOPS-encrypted
Secret (synapse-turn-secret.yaml), wired via a second HelmRelease
valuesFrom entry (same pattern already used for ess-mas-values-secret).
Rotated the value while doing this, so the leaked plaintext secret is no
longer live anywhere.

Added checksum/rotated-at annotations (matrix-stack HelmRelease's
existing element-config-checksum patch gets a sibling turn-secret-checksum;
coturn's Deployment pod template gets a rotated-at annotation) so future
rotations actually restart both consumers - Kubernetes doesn't restart
running pods when a referenced Secret's content changes on its own.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 49005ed325 fix(backup): retry pg_dump connection to survive NetworkPolicy sync lag
Live testing showed pg_dump got "Connection refused" immediately at job
start, but a manual pg_isready/psql from an identically-labeled pod a few
seconds later succeeded fine every time. The cluster's NetworkPolicy
controller needs a brief moment to program a brand-new pod's IP into the
target's allowed ingress rules; a job that starts dumping instantly can
race that window. backup.sh now waits for pg_isready before each pg_dump
(up to 15 tries / ~30s) instead of assuming connectivity is ready at
container start.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 ba270bce71 feat(backup): add nightly Borg backups to Hetzner Storage Box
Closes issues #6 and #15 (treated jointly, per combined analysis in their
comments). Two CronJobs, one per namespace, each pushing to its own Borg
repo on the newly booked Storage Box (u641795.your-storagebox.de:23, BX11
1TB) with its own repo passphrase - a leaked passphrase for one doesn't
expose the other:

- matrix: synapse-backup dumps the synapse + matrixauthenticationservice
  DBs (shared postgres, existing chart-generated POSTGRES_ADMIN_PASSWORD)
  and the Synapse media_store PVC (read-only mount)
- authentik: authentik-backup dumps the authentik DB (existing
  authentik-credentials pg-password)

Custom image (rohana.axion1337.de/sorb/axion-backup:v1, postgres:17-alpine
+ borgbackup + openssh-client - matches the live Postgres major version
exactly, unlike Alpine's stock postgresql16-client) pushed as a public
package, same pattern as the existing threadnet-web image (no
imagePullSecret needed).

SSH host key pinned via known_hosts ConfigMap (captured via ssh-keyscan
ahead of time) rather than trusting on first connect in an unattended job.
Retention: 7 daily / 4 weekly / 6 monthly via borg prune. Schedule: 03:00
and 03:15, offset to avoid resource contention.

NetworkPolicy: added each backup job's pod as an allowed source to its
namespace's existing postgres ingress rule (matrix's allow-ingress-postgres,
authentik's allow-ingress-authentik-postgresql from #37). Egress already
unrestricted in both namespaces, so no change needed for the outbound SSH
connection to the Storage Box.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 2c5f77686d fix(authentik): scope authentik-postgresql NetworkPolicy to internal access
Closes issue #37. The Bitnami postgresql subchart's auto-generated
NetworkPolicy restricted the port (5432) but not the source - any pod in
any namespace could reach it, since additive NetworkPolicy rules can't
restrict an existing permissive one, only the chart itself controls it
(hence not touched during the original #10 rollout).

Disabled via postgresql.primary.networkPolicy.enabled: false and replaced
with a scoped policy allowing only authentik-server and authentik-worker
(same namespace) on 5432, matching the pattern already used for the
matrix namespace's postgres access. No metrics exporter is enabled for
this instance, so no monitoring-namespace rule is needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 414ada956a feat(authentik): capture MAS OIDC Provider/Application as a Blueprint
Closes issue #36. The OAuth2 Provider ("Matrix Authentication Service")
and its Application ("matrix" slug) linking Authentik to MAS were
originally clicked together by hand in the UI and existed nowhere as
code - unlike the flow fixes already captured in authentik-blueprints.yaml.
Losing the Authentik DB would have meant re-creating this from scratch,
including a fresh client_secret that MAS would no longer match.

The client_secret is read via !Env from AUTHENTIK_MAS_OIDC_CLIENT_SECRET,
sourced from a new key in the existing SOPS-encrypted authentik-credentials
Secret, rather than inlined into the blueprint ConfigMap (which isn't
itself encrypted). Value used is the actual live secret already in use,
read directly from the running Authentik DB - not a new/rotated one, so
this changes nothing about the current MAS<->Authentik pairing.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore CimbalandClaude Sonnet 5 4a3d7c70a6 fix: restore correct file permissions, stop tracking .DS_Store
Almost every tracked file in the repo had drifted to mode 777 on disk
(only files created fresh this session were unaffected), and a chunk of
that drift had already been committed as spurious +x bits on plain
YAML/Markdown files (authentik.yaml, kustomization.yaml, coturn.yaml,
element-server-suite.yaml, TASKS.md, install.md, etc.) - none of these
need to be executable. Restored to 644 for regular files, 755 only for
actual scripts (postCreateCommand.sh, docker-init.sh, install-hooks.sh,
pre-commit hook, element-setup-linux.sh).

Also found element-setup-macos.command was missing +x despite having a
shebang and being meant for double-click execution on macOS - fixed.

Added .gitignore for .DS_Store and .claude/ and stopped tracking the five
.DS_Store files that had been committed by accident.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 12:00:00 +00:00
Thore Cimbal 79db6a8e49 feat: Try H.264 codec for calls instead of VP8
H.264 uses classic simulcast (like VP8), not SVC, so it's compatible
with the fork's simulcast-shaped publish options without needing a
code fix - unlike VP9/AV1 (see the 2026-07-28 incident notes). Also
tends to be hardware-accelerated on more devices, notably iOS/Safari.
Server-side: LiveKit has no codec restriction configured, supports
H.264 by default.
2026-07-28 12:00:00 +00:00
Thore Cimbal 25d1742d61 fix: Add 720p simulcast middle layer for smoother video quality
User reported visible artifacts/blockiness during calls. Root cause:
without an explicit simulcast_layers config, the fork defaulted to
only [180p, 360p] fallback layers below the 1440p top layer - any
minor network hiccup caused a hard cliff straight to blocky 360p
instead of a graceful step-down. Added a 720p middle rung.

VP9 retry deferred: LiveKit uses SVC for vp9/av1 instead of classic
simulcast, and the fork's buildPublishOptions() always builds
simulcast-shaped layers regardless of codec - likely the real reason
forcing vp9 broke calls entirely. Needs a code fix before retrying.
2026-07-28 12:00:00 +00:00
Thore Cimbal 22a0823b7e fix: Raise matrixRTC authorisation service memory limit (20Mi -> 128Mi)
Chart default of 20Mi request+limit OOM-killed the service today after
~74 days of uptime (3rd OOM over its lifetime), causing intermittent
call setup failures unrelated to the NetworkPolicy work happening in
parallel. 20Mi is razor-thin for a long-running Go service; bumping to
a still-modest 64Mi/128Mi request/limit.
2026-07-28 12:00:00 +00:00
Thore Cimbal 3054037480 fix: Allow synapse-main to reach MAS's port 8080 for token introspection
Second port-config incident from this rollout: synapse calls MAS's
oauth2/introspect endpoint on port 8080 (not 8081 as assumed) for
every single authenticated request (sync, pushrules, capabilities,
etc). The rule only allowed kube-system (Traefik) on 8080, so every
authenticated API call failed with 503 "Unable to introspect the
access token" - all clients showed a lost connection. Patched live
immediately, this commit brings Git back in sync with that patch.
2026-07-28 12:00:00 +00:00
Thore Cimbal 8f1d39b7a8 feat: Default-deny ingress NetworkPolicy for matrix namespace
Ingress-only default-deny plus per-component allow rules, using named
container ports throughout (not Service ports) after the authentik
port-mismatch incident. Traefik -> element-web/element-admin/haproxy
(fronts both matrix.axion1337.chat and well-known)/MAS; synapse <-
haproxy+MAS; postgres <- synapse+MAS; RTC signalling via Traefik, RTC
media NodePorts left open to the internet by design; monitoring scrape
allows for synapse/postgres/rtc-sfu metrics; ACME solver allow. coturn
(hostNetwork) needs nothing - NetworkPolicy doesn't apply to it. Part
of issue #10.
2026-07-28 12:00:00 +00:00
Thore Cimbal edf224e450 fix: Correct authentik-server NetworkPolicy ports (container port, not Service port)
Caused a live 502 immediately after deploy: the rule allowed 80/443
(the Service's external ports), but NetworkPolicy filters on the pod's
actual container port after kube-proxy's DNAT - authentik-server's
Service maps 80->9000 and 443->9443. Confirmed root cause by suspending
Flux reconciliation (it was silently re-applying my manual test
deletions) and testing with the policies truly absent.
2026-07-28 12:00:00 +00:00
Thore Cimbal b32920c48f feat: Default-deny ingress NetworkPolicy for authentik namespace
Ingress-only default-deny (egress untouched) plus explicit allows:
Traefik (kube-system) + MAS (matrix ns) -> authentik-server on 80/443,
and Traefik -> cert-manager's ACME HTTP-01 solver pods on 8089.
authentik-postgresql already has its own Bitnami-chart-managed policy,
left alone. Part of issue #10.
2026-07-28 12:00:00 +00:00
Thore Cimbal 1bb1bc9610 fix: Retry Element Call fork without forced VP9 codec preference
v0.2.0 forced video_codec: vp9, which broke calls entirely (no audio/
video transmitted, despite server logs showing the codec regression
fallback to VP8 working). Root cause not fully confirmed. This build
keeps the 1440p/60fps/bitrate defaults but leaves video_codec unset
(defaults to vp8) to isolate whether the codec preference itself was
the trigger.
2026-07-27 12:00:00 +00:00
Thore Cimbal 37aea0254b revert: Roll back Element Call fork image - calls broken (no audio/video)
User reports calls transmit neither video nor audio with
v0.2.0-elementcall-mediaquality. Rolling back to known-good v0.1.0
while investigating; likely the video_codec: vp9 preference, not the
resolution/framerate bump.
2026-07-27 12:00:00 +00:00
Thore Cimbal af73cf770b feat: Element Call fork with 1440p/60fps + VP9 defaults
Bumps elementWeb image to a build with the embedded Element Call
widget replaced by our own fork (rohana.axion1337.de/sorb/threadnet-call,
based on emmick4/element-call:livekit / upstream PR #3736), raising
default call quality to up to 1440p/60fps camera (VP9) and 1440p/30fps
screen share. These are seeded defaults users can still adjust in
Settings, not hard-enforced caps.
2026-07-27 12:00:00 +00:00
Thore Cimbal 09e4225de5 fix: Replace broken netstat liveness probe on coturn with tcpSocket check
coturn started up cleanly every time (all TCP/UDP listeners on 3478/5349
opened fine per logs) but was killed every ~10s because the liveness
probe ran "netstat -uln", which doesn't exist in coturn/coturn:latest
(sh: netstat: not found) - 36000+ restarts over 88 days for a healthy
process. Switched to a tcpSocket probe against the TCP listener coturn
already opens on 3478, no in-container tooling required.
2026-07-27 12:00:00 +00:00
Thore Cimbal c0cb864ca2 docs: Add security.html with Passkey/TOTP self-service setup links
Neither Element Web's config.json nor MAS's branding config expose a
generic custom-link mechanism, and /if/user/ is blocked for type=external
Matrix accounts, so the working Authentik MFA setup flows had nowhere to
be discoverable. Added a docs/setup/security.html page, following the
exact existing pattern (ConfigMap -> initContainer cp -> nginx), linked
from index.html's Support section.
2026-07-27 12:00:00 +00:00
Thore Cimbal 235306a840 fix: Set Brand.default_application so "/" doesn't dead-end at /if/user/
Several dead ends (TOTP/WebAuthn setup after an anonymous visit bounces
through login and lands on "/") trace back to Brand.default_application
being unset, which falls back to /if/user/ - blocked for type=external
Matrix accounts. Set it to the matrix Application. Only changes the bare
"/" fallback; explicit URLs like /if/admin/ are unaffected.
2026-07-27 12:00:00 +00:00