Running Entrosity Matrix
Entrosity Matrix runs next to Entrosity Hub, Axis, Edge and Sphere on the
same host. It is optional per host: the compose profile matrix holds its
services, and the deploy scripts start them only when deploy/.env has
MATRIX_ENABLED=true (Enabling Matrix on a host).
Matrix needs no port besides 443: connectors connect out to it over
HTTPS and WebSocket.
| Part | Where |
|---|---|
Web app (entrosity-matrix.frontend) | https://hub.entrosity.com/matrix/, served by Caddy from the web image |
API (entrosity-matrix.backend, image ghcr.io/entrosity/matrix-backend) | https://hub.entrosity.com/matrix/api/…; Caddy strips /matrix, so the backend serves /api/v1 (browsers), /api/connector/v1 (connectors) and /api/releases/v1 (connector installers: CI uploads, expiring download links) |
| Database | Its own PostgreSQL database (matrix), migrated by the backend |
| Sign-in | Entrosity Hub, product matrix |
Services
deploy/docker-compose.prod.yml of entrosity-infra, profile matrix:
| Service | Image | What it does |
|---|---|---|
matrix-db-init | postgres:18-alpine | Creates the matrix database (owner rmm) once. |
matrix-migrate | matrix-backend | Runs migrate up as the owner, and enables the matrix_app login with MATRIX_APP_DATABASE_PASSWORD. |
matrix | matrix-backend | matrix-server serve, one replica: connectors hold a WebSocket to it, the web app an event stream, and re-enable schedules run in its job queue. API on :8080 behind Caddy; metrics on :9095 (internal). Health check: matrix-server healthcheck. Memory limit MATRIX_MEMORY (384m), GOMEMLIMIT from MATRIX_GOMEMLIMIT (300MiB). |
The web service (Caddy) serves Matrix too:
| Path | Goes to |
|---|---|
/matrix/ | The web app (from the matrix-frontend image, built into the web image); /matrix redirects to /matrix/ |
/matrix/api/* | matrix:8080, with /matrix stripped; responses are not buffered (WebSocket, event stream) |
While Matrix is not enabled on a host there is no matrix service and
/matrix/api/* answers 502; the Hub does not link to Matrix until the
product is enabled.
The backend binary is matrix-server:
matrix-server serve run the HTTP API and job workers (default)
matrix-server migrate [cmd] database migrations: up | down [N] | version | force N
(up also sets the matrix_app login password when
MATRIX_APP_DATABASE_PASSWORD is set)
matrix-server healthcheck exit 0 when this server is ready (/readyz), for
container health checks
matrix-server release-keygen print a new connector release signing key pair
matrix-server import-stop-internet import the stop-internet panel's room rights and history
matrix-server version print the version
On the Hub, the product matrix (roles tenant_admin, teacher,
viewer) is registered by the Hub's migration 0008 disabled and in
beta, and enabled by migration 0009 (Rollout). The Hub must
know Matrix's token: PLATFORM_PRODUCT_TOKENS includes matrix:<token>,
the same value as MATRIX_PLATFORM_TOKEN. In production both come from
PLATFORM_PRODUCT_TOKEN_MATRIX in deploy/.env.
Configuration reference
The backend is configured only through MATRIX_* environment variables
(entrosity-matrix.backend/internal/config). Invalid values stop it at
start with a list of every problem. The RETENTION section accepts one or
two underscores: MATRIX_RETENTION_JOB_DAYS =
MATRIX_RETENTION__JOB_DAYS.
Server
| Variable | Default | Meaning |
|---|---|---|
MATRIX_ENV | dev | dev, test or prod. prod refuses the development example secrets and logs JSON. |
MATRIX_PUBLIC_URL | http://localhost:8085 | Matrix's public address including the /matrix prefix the proxy strips (https://hub.entrosity.com/matrix). Connectors are given <MATRIX_PUBLIC_URL>/api/connector/v1/ws, and the install commands shown with new enrollment tokens use it as SERVER_URL. |
MATRIX_HTTP_ADDR | :8085 | API listener (production: :8080). |
MATRIX_METRICS_ADDR | :9095 | Internal listener for Prometheus /metrics. Never expose it publicly; empty disables it. |
MATRIX_INTERNAL_ADDR | :8086 | Internal API for Entrosity Axis's screen wall: GET /internal/v1/screen-rooms (a tenant's rooms with their computers, or a teacher's granted rooms). Served only when MATRIX_AXIS_TOKEN is set. Never expose it publicly (compose: network only, not in Caddy). |
MATRIX_AXIS_TOKEN | empty (off) | Bearer token Axis uses there (at least 32 characters; Axis's RMM_MATRIX_AXIS_TOKEN). In compose, one MATRIX_AXIS_TOKEN in .env (openssl rand -hex 32) turns the screen wall on for both services. |
MATRIX_LOG_LEVEL | info | debug, info, warn or error. |
MATRIX_CORS_ORIGINS | http://localhost:5178 | Allowed browser origins, comma separated, no wildcards or paths (production: https://hub.entrosity.com). |
MATRIX_TRUSTED_PROXIES | none | CIDRs or IPs allowed to set X-Forwarded-For (production: the compose network 172.30.0.0/24). The client IP recorded with each change comes from it. |
MATRIX_API_RATE_PER_SECOND, MATRIX_API_RATE_BURST | 20, 60 | Web API rate limit per client IP (a school behind one NAT address shares it). |
MATRIX_ENROLL_RATE_PER_MINUTE | 60 | Connector enrollments per client IP. |
MATRIX_CONNECTOR_DOWNLOAD_URL | none | Where the connector MSI can be downloaded; shown with new enrollment tokens while no connector release is stored (Connector releases). |
Database
| Variable | Default | Meaning |
|---|---|---|
MATRIX_DATABASE_URL | none (required) | Connection URL. Production connects as matrix_app. |
MATRIX_DATABASE_ROLE | matrix_app | Role the pool switches to after connecting (SET ROLE), so row-level security applies even when connecting as the owner. Empty when the login already is the application role and cannot switch. |
MATRIX_DATABASE_MAX_CONNS | 20 | Pool size. |
MATRIX_DATABASE_STATEMENT_TIMEOUT | 30s | Upper bound for any statement. |
MATRIX_APP_DATABASE_PASSWORD | none | Read by migrate up: enables the matrix_app login with this password. |
Secrets
| Variable | Meaning |
|---|---|
MATRIX_JWT_SECRET | Required. At least 32 bytes, raw or base64. Signs the one-minute live-update stream tokens (POST /auth/sse-token). Users' access tokens come from the Hub. |
MATRIX_JWT_SECRET_OLD | The previous secret during a rotation (still verifies). |
MATRIX_CREDENTIALS_KEY | Required. Exactly 32 bytes, base64: encrypts the FortiGate API tokens in the database (AES-256-GCM; the firewall's ID is bound to its ciphertext, so a ciphertext copied to another firewall does not decrypt). |
MATRIX_CREDENTIALS_KEY_OLD | The previous key during a rotation: it still decrypts; tokens stored after the rotation use the current key. |
With MATRIX_ENV=prod, values containing dev-only (the development
examples) are refused.
Without MATRIX_CREDENTIALS_KEY (or with a different one) no FortiGate
token can be decrypted: connectors that restart or receive a new
configuration cannot sign in to their firewalls until every token has been
stored again. Keep a copy of deploy/.env with the backups, apart from
them.
Sign-in on Entrosity Hub
| Variable | Default | Meaning |
|---|---|---|
MATRIX_PLATFORM_URL | none (required) | The Hub's public origin (https://hub.entrosity.com): the issuer of product tokens and where browsers sign in. |
MATRIX_PLATFORM_INTERNAL_URL | none (required) | The Hub's internal API, reached directly and not through the proxy (compose: http://platform:8081): signing keys and the access snapshot. |
MATRIX_PLATFORM_TOKEN | none (required) | Matrix's bearer token on the Hub's internal API, at least 32 characters; matrix:<token> in the Hub's PLATFORM_PRODUCT_TOKENS. |
MATRIX_PLATFORM_SYNC_INTERVAL | 30s | How often Matrix pulls users, organizations and roles from the Hub (at least 1s). |
Matrix settings
| Variable | Default | Meaning |
|---|---|---|
MATRIX_REPORT_STALE_AFTER | 90s | A firewall's rooms are stale (shown as not current, changes refused with snapshot_stale) when its last report is older than this or 2.5 × the firewall's report interval, whichever is longer, when its connector is offline, or when it does not report online. At least 15s. |
MATRIX_CHANGE_LIMIT_USER | 10 | Change requests per user per minute (each room of a bulk change counts). Beyond: 429 rate_limited, recorded as refused. |
MATRIX_CHANGE_LIMIT_TENANT | 30 | Change requests per tenant per minute. |
Connector updates
| Variable | Default | Meaning |
|---|---|---|
MATRIX_RELEASE_SIGNING_KEY | none | Signs connector releases: an Ed25519 key, base64 of the 32-byte seed or the 64-byte private key. Its public half is the RELEASE_PUBLIC_KEY connectors are built with. Empty disables uploads and self-updates (uploads answer 503 releases_disabled). An invalid value stops the server. |
MATRIX_RELEASE_TOKEN | none | CI's bearer token for uploading connector builds (POST /api/releases/v1/connector), at least 32 characters. Empty: every upload answers 401. |
MATRIX_CONNECTOR_UPDATE_CHANNEL | stable | What connectors are updated to (and what Download connector offers): stable (tagged releases only) or dev (development builds and tagged releases). |
Retention windows
| Variable | Default | Meaning |
|---|---|---|
MATRIX_RETENTION_JOB_DAYS | 90 | Finished connector jobs. Tenants may override it (7–730). |
MATRIX_RETENTION_AUDIT_DAYS | 365 | Audit log. Tenants may override it (30–3650). |
0 or unset keeps the default. The change history is not purged.
Host settings
In production the compose file fixes most of the above
(MATRIX_PUBLIC_URL=https://${PLATFORM_DOMAIN}/matrix,
MATRIX_CORS_ORIGINS, the listeners, the trusted proxies,
MATRIX_PLATFORM_INTERNAL_URL=http://platform:8081). deploy/.env
(deploy/.env.prod.example lists them) sets the rest:
| Variable | Meaning |
|---|---|
MATRIX_ENABLED | true runs the matrix profile. Default false. |
MATRIX_APP_DATABASE_PASSWORD | The matrix_app login's password. Required when enabled. |
MATRIX_JWT_SECRET, MATRIX_JWT_SECRET_OLD | As above. The first is required when enabled. |
MATRIX_CREDENTIALS_KEY, MATRIX_CREDENTIALS_KEY_OLD | As above. The first is required when enabled. |
PLATFORM_PRODUCT_TOKEN_MATRIX | Matrix's token on the Hub: becomes MATRIX_PLATFORM_TOKEN and the matrix: entry of the Hub's PLATFORM_PRODUCT_TOKENS. Required when enabled. |
MATRIX_RELEASE_SIGNING_KEY, MATRIX_RELEASE_TOKEN | Connector self-updates, as above. Optional: empty turns them off (Enable connector self-updates). |
MATRIX_CONNECTOR_DOWNLOAD_URL, MATRIX_LOG_LEVEL | As above. |
MATRIX_BACKEND_IMAGE | Default ghcr.io/entrosity/matrix-backend. |
MATRIX_MEMORY, MATRIX_GOMEMLIMIT | Memory limits: 384m, 300MiB. |
Generating the secrets
openssl rand -base64 32 # MATRIX_JWT_SECRET, MATRIX_CREDENTIALS_KEY (exactly 32 bytes)
openssl rand -hex 32 # MATRIX_APP_DATABASE_PASSWORD, PLATFORM_PRODUCT_TOKEN_MATRIX, MATRIX_RELEASE_TOKEN
The database password ends up inside a connection URL, so use a value
without /, + or = (hex). The product token must be at least 32
characters. Never commit these values or paste them into tickets.
Enabling Matrix on a host
- Generate the secrets and set
MATRIX_APP_DATABASE_PASSWORD,MATRIX_JWT_SECRET,MATRIX_CREDENTIALS_KEYandPLATFORM_PRODUCT_TOKEN_MATRIXindeploy/.env. - Set
MATRIX_ENABLED=true. - Deploy (the next
deployrun, ordeploy/scripts/upgrade.sh).
With MATRIX_ENABLED=true, deploy/scripts/lib.sh adds --profile matrix to every compose command, and refuses to run while
MATRIX_APP_DATABASE_PASSWORD, MATRIX_JWT_SECRET,
MATRIX_CREDENTIALS_KEY or PLATFORM_PRODUCT_TOKEN_MATRIX is empty.
upgrade.sh then pulls the Matrix images and, after the Hub, runs
matrix-migrate and restarts matrix (and waits until it is healthy).
The Hub is recreated with matrix:<token> in its product tokens. The
deploy workflow's final check also waits for /matrix/api/v1/healthz
on hosts with MATRIX_ENABLED=true.
Rollout
Matrix reaches users in this order; each step needs the previous one:
- Shared protocol tagged.
proto/matrix(andJobProgress.Detail) live inentrosity-shared-go: tag a release containing them, and bumpentrosity-matrix.backendandentrosity-matrix-connectorto that tag (until then they build only with a localgo.work, and CI fails). - Images published.
ghcr.io/entrosity/matrix-backend:mainandghcr.io/entrosity/matrix-frontend:mainexist (their CI onmain); the connector's MSI is built by its release workflow. - Infrastructure. Push the
entrosity-infrachange that adds Matrix (compose profile, Caddy routes, web image, scripts, deploy workflow), then set up the host as above withMATRIX_ENABLED=true, and deploy. The Hub's migration 0008 has registered the product disabled: nobody sees it yet. - Enabled, in beta. Deploy the Hub release with migration 0009, which enables the product. It stays in beta: only platform admins see and open it, and they can enable it for organizations.
- Released. A platform admin chooses Release to organizations (Products in beta).
The deploy workflow pulls matrix-backend:main and builds the web image
with matrix-frontend:main on every run, whether the host enables
Matrix or not. Push the entrosity-infra change only after both images
have been published, or every deploy fails
(Continuous deployment). Migration 0009
belongs in a Hub release deployed after step 3: before it, the launcher
would link to a Matrix that does not answer.
Rolling out allowed sites
Allowed sites need
migration 0003_allowed_sites (applied by matrix-migrate with the new
backend) and connectors that announce the sites capability. Backend and
connectors can be updated in any order:
- Old connectors with the new backend keep working as before. They
get no
matrix.sites.setjobs; the app says The connector of this firewall does not support allowed sites yet, a save answers409 connector_outdated, and their reports without sites keep working. - New connectors with the previous backend keep working too: they
report the lists, which that backend ignores, and their check shows the
new warnings (
sites_not_set_up:) until the groups are set up. - Guard files are unchanged. Site writes are off until
matrix-connector guard set <id> --site-writes on. The scope does not change, so no firewall has to be accepted again. - Nothing happens on the FortiGate until its administrator runs the
setup CLI: without the groups, Matrix writes nothing, and the new
switch
site_writes_enabled(off) only takes effect once the groups exist.
Removing the Entrosity services
The Entrosity services (the locked Matrix Entrosity services group,
MATRIX_SERVICE_DOMAINS, the firewalls' services_enabled and the
matrix.services.sync jobs) were removed: while a room's internet is off,
only the sites teachers and admins list are reachable. Migration
0004_remove_entrosity_services drops firewalls.services_enabled,
firewall_snapshots.services and the one-open-sync index, deletes open
matrix.services.sync jobs and cancels their pending changes; the history
keeps its services entries.
- Deploy the frontend first (or together with the backend): the new
API refuses
services_enabledin a firewall update (422), which the previous frontend sends when a firewall is saved. The new frontend works with the previous backend. - Old connectors with the new backend keep working: the apply no
longer carries
services_enabled/service_domains, so they keep the group empty and are never sent a sync; a leftover sync would be refused at authorization (services_removed). Theservicesin their reports are ignored; their check may still showservices_not_set_up:orservices_out_of_sync:warnings, which no longer matter (update the connector). - New connectors with the previous backend keep working too: they
ignore the service fields of the apply, never write the group, report
no
services(so that backend never sends a sync) and fail amatrix.services.syncas an unsupported job type.allow_service_writesin an existingguard.jsonis ignored; no firewall has to be accepted again. - Remove
MATRIX_SERVICE_DOMAINSfrom the deployment's environment (the server no longer reads it). - On FortiGates set up earlier, an admin can remove the empty group (Troubleshooting → Removing the old Entrosity services group).
Connector releases
Matrix keeps the connector's installers and rolls them out: CI uploads every build, Matrix signs it, connectors that can update themselves are offered the newest one, and tenant admins download it from Download connector (Connectors → Updates).
Enable connector self-updates
-
Generate the Ed25519 key pair once:
docker compose -f docker-compose.prod.yml --env-file .env --profile matrix run --rm --no-deps matrix release-keygenopenssl rand -hex 32 # MATRIX_RELEASE_TOKENrelease-keygenprintsMATRIX_RELEASE_SIGNING_KEY(the server's secret) andRELEASE_PUBLIC_KEY(for connector builds). Keep the signing key as secret as the other keys. -
In the host's
deploy/.envsetMATRIX_RELEASE_SIGNING_KEYandMATRIX_RELEASE_TOKEN, and optionallyMATRIX_CONNECTOR_UPDATE_CHANNEL. -
In the
entrosity-matrix-connectorrepository set the secretsRELEASE_PUBLIC_KEY(compiled into the connector) andMATRIX_RELEASE_TOKEN(the same token), and the variableRELEASE_PUBLISH_ENABLED=true.MATRIX_RELEASE_API(a variable) changes the target, defaulthttps://hub.entrosity.com/matrix/api/releases/v1. -
Redeploy. The next connector build is uploaded and offered.
-
Connectors installed before this were built without the public key and cannot update themselves: install the new version on each of them once.
Connectors accept only releases signed with the key their build contains.
With another key (a lost or replaced seed), every update fails with
signature_invalid until each connector has been reinstalled by hand with
a build that contains the new public key.
Publishing
CI uploads each MSI with scripts/publish-release.sh of the connector
repository:
| Build | Version | Channel |
|---|---|---|
Tag vX.Y.Z (release.yml) | X.Y.Z | stable |
Tag vX.Y.Z-suffix | X.Y.Z-suffix | dev |
Every push to main (dev-release.yml) | a -dev pre-release version | dev |
The upload is POST /api/releases/v1/connector?version=…&channel=…¬es=…
with Authorization: Bearer $MATRIX_RELEASE_TOKEN and the raw MSI as the
body (at most 64 MiB). Matrix signs its manifest (component
matrix-connector: version, SHA-256 and size) and keeps the newest
ten releases.
| Answer | Meaning |
|---|---|
| 201 | Stored. |
401 unauthorized | Wrong or missing token, or MATRIX_RELEASE_TOKEN is not set. |
409 release_exists | This version is already published (the script treats it as done). |
422 validation | Not a semantic version, a channel other than stable or dev, or an empty or too large body. |
503 releases_disabled | MATRIX_RELEASE_SIGNING_KEY is not set. |
Offering updates
Every 5 minutes (releases.rollout) and when a connector says hello,
Matrix offers the newest release of MATRIX_CONNECTOR_UPDATE_CHANNEL to
online connectors that announce the update capability, run an older
version, have no update job open and were not offered the same version
within the last hour. The offer is an update_agent job with download
links valid 2 hours (GET /api/connector/v1/releases/{releaseID}/msi?t=…,
authorized by the link itself). What the connector does:
Matrix connector → Self-update.
Background jobs
The backend runs its jobs in PostgreSQL (River):
| Job | When | What |
|---|---|---|
realtime.sweep | Every 30 seconds | Marks connectors silent for 3 minutes offline; expires overdue connector jobs and resends unacknowledged ones. An expired write job becomes Unconfirmed when the connector had taken it, Error when it never had. |
matrix.stale | Every 30 seconds | Finds firewalls whose rooms became stale (or current again) and notifies the open web apps (matrix.rooms). |
schedule.fire | At each re-enable time | Marks the schedule firing and sends the room's enable as a system change. While the connector is offline or the firewall stale it retries (30 seconds, doubling up to 15 minutes); 24 hours after the time the schedule is failed. |
schedule.sweep | Every minute | Queues overdue pending schedules again (for example after the server was down). |
releases.rollout | Every 5 minutes | Offers the newest connector release (Offering updates). Does nothing without MATRIX_RELEASE_SIGNING_KEY. |
retention.cleanup | Daily | See Retention. |
Besides, every connector report (matrix.report) updates the rooms (a
room missing from a successful report becomes no longer on the
firewall), the address groups and allowed sites when they changed, and
the firewall's status, FortiOS version and guard state, and notifies the
web apps. Matrix never creates a write job again on its own: a failed
or unconfirmed change stays as it is until a person acts. The only system
writes are the automatic re-enables.
Retention
A daily retention.cleanup job deletes old data in batches of 10,000
rows:
| Data | Kept |
|---|---|
| Finished connector jobs | The tenant's override (settings.retention.job_days, 7–730), else MATRIX_RETENTION_JOB_DAYS. |
| Audit log | The tenant's override (settings.retention.audit_days, 30–3650), else MATRIX_RETENTION_AUDIT_DAYS. |
| Enrollment tokens | 30 days after they expired or were revoked. |
| Hub sessions ended, used step-up tokens | Once no longer needed. |
Change history (change_events) | Kept (not purged). |
matrix_retention_rows_deleted_total{category} counts what was removed.
Database and migrations
Matrix has its own database. Migrations are embedded in the binary
(entrosity-matrix.backend/db/migrations) and applied by migrate up:
| Migration | Adds |
|---|---|
0001_init | Matrix's copy of the Hub's tenants, users and roles (tenants, users, tenant_memberships, Hub sync state, ended sessions, used step-up tokens), sites, the append-only audit_log, enrollment_tokens, connectors, jobs, connector_releases, and row-level security with the matrix_app role. |
0002_matrix | firewalls (the configuration, the sealed token token_enc with credentials_version, the write switches and what the connector last reported), rooms, firewall_snapshots (address groups), room_grants, the append-only change_events (the history), address_operations, bulk_actions, room_schedules, rate_buckets (change limits), and on jobs the columns linking a job to its firewall, policy, room, bulk action, schedule and address operation, with at most one open room switch per policy and one open address job per firewall. |
0003_allowed_sites | Allowed sites: on firewalls the switches site_writes_enabled (default off) and services_enabled (default on); on firewall_snapshots the reported lists and services group (sites, sites_hash, sites_fetched_at, services); the change kinds sites and services; at most one open matrix.sites.set per firewall and list (the list is kept in jobs.room_code: shared or the room code) and one open matrix.services.sync per firewall. The down migration drops them. |
0004_remove_entrosity_services | Removes the Entrosity services: drops firewalls.services_enabled, firewall_snapshots.services and the index of open matrix.services.sync jobs, deletes the open ones and cancels their pending changes. The history keeps its services entries (the kind stays allowed). The down migration restores the columns (services_enabled off for existing firewalls) and the index. |
- Tenant isolation: every tenant table has a row-level security
policy (
FORCE); the server runs asmatrix_app(NOBYPASSRLS). - Append-only history: a trigger refuses to change or delete a
finished
change_eventsrow; only a pending row gets its result and steps. - FortiGate tokens are stored only encrypted (
token_enc) and are never part of a job, an event or the audit log.
Backups and restore
deploy/scripts/backup.sh dumps the matrix database whenever it exists,
next to the others: backups/db/matrix-<timestamp>.dump (pg_dump -Fc,
checked by reading it back), pruned with the other dumps after the
retention days.
deploy/scripts/restore.sh with MATRIX_ENABLED=true stops matrix,
restores the matrix-… dump of the same backup run when there is one (it
recreates the database and the matrix_app role), runs matrix-migrate,
and starts matrix again.
The dump holds the FortiGate tokens encrypted with
MATRIX_CREDENTIALS_KEY: a restore needs the same key. The dump also holds
the history (user e-mail addresses and client IPs): protect backups like
the database. After a restore, rooms are brought up to date by the next
connector reports; changes made after the backup are not in the restored
history.
Import from the stop-internet panel
matrix-server import-stop-internet --tenant <id> --firewall <id> --users users.csv --export export.json imports the single-school panel Matrix
replaces into one tenant and firewall: teachers' allowed rooms become
room rights, and its history (room switches, IP changes, new computers)
becomes change history with source stop-internet. Users are matched by
e-mail through users.csv (username,email) and must already exist in
Matrix. It is idempotent. The step-by-step procedure, including a
read-only export from the panel's SQLite database:
Moving from the old panel.
Monitoring
GET /healthz(liveness) andGET /readyz(readiness: the database answers; it also reports whether the copy of the Hub's data is current,staleafter 5 minutes, without failing) on the API listener. Publicly:https://hub.entrosity.com/matrix/api/v1/healthz.- Prometheus metrics on
MATRIX_METRICS_ADDR(:9095; the Prometheus jobmatrixindeploy/monitoring/prometheus.yml), among themmatrix_ws_connections,matrix_connectors_online,matrix_firewalls_online(enabled firewalls reported online),matrix_jobs_total{type,status},matrix_job_dispatch_seconds,matrix_http_request_duration_seconds,matrix_platform_syncs_total,matrix_platform_sync_age_seconds,matrix_sse_subscribers,matrix_retention_rows_deleted_total,matrix_river_queue_depthandmatrix_db_pool_connections. - Logs are JSON in
prod. A refused write-time authorization is logged atinfo(connector write refused, with the job and the reason); it is also a step of the change in the history. - Watch Schedules → Failed re-enables in the tenants: a failed re-enable leaves a room off.
Local development
The development stack of entrosity-infra runs Matrix next to the Hub
(Development setup):
deploy/.env.examplehas a Matrix block (MATRIX_*on :8085, metrics on :9095, development secrets,MATRIX_PUBLIC_URL=http://localhost:5175/matrix), and the Hub'sPLATFORM_PRODUCT_TOKENSincludes thematrixtoken.- Create the database once:
docker compose -f deploy/docker-compose.yml exec postgres createdb -U rmm matrix. - In
entrosity-matrix.backend(with a localgo.workusing../entrosity-shared-gountil the shared tag exists):make migrate, thenmake dev(API on :8085). - In
entrosity-matrix.frontend: its dev server on :5178. - Open
http://localhost:5175/matrix/. The Hub's dev server proxies/matrix/apito :8085 (prefix stripped) and/matrixto :5178. - For rooms, run a connector with the simulator:
matrix-connector enroll --server http://localhost:5175/matrix --token <token>, thenmake devinentrosity-matrix-connector(Trying Matrix with the simulator).