Resolve audit findings: correct WorkerEnvelope proto/route/metric/session facts; rewrite auth (ZB.MOM.WW.Auth migration), dashboard (ZB.MOM.WW.Theme), and StyleGuide (foreign-project copy-paste); document alarm subsystem, Ldap options, and gateway alarm broker; fix client CLI flags and package paths.
28 KiB
Gateway Configuration
This document describes every option bound under the MxGateway configuration
section by GatewayOptions.
The gateway binds configuration at startup and validates it with
GatewayOptionsValidator. Startup fails before the server listens when required
paths, timeouts, queue sizes, enum values, or protocol values are invalid.
Configuration Shape
{
"MxGateway": {
"Authentication": {
"Mode": "ApiKey",
"SqlitePath": "C:\\ProgramData\\MxGateway\\gateway-auth.db",
"PepperSecretName": "MxGateway:ApiKeyPepper",
"RunMigrationsOnStartup": true
},
"Ldap": {
"Enabled": true,
"Server": "localhost",
"Port": 3893,
"Transport": "None",
"AllowInsecure": true,
"SearchBase": "dc=zb,dc=local",
"ServiceAccountDn": "cn=serviceaccount,dc=zb,dc=local",
"ServiceAccountPassword": "serviceaccount123",
"UserNameAttribute": "cn",
"DisplayNameAttribute": "cn",
"GroupAttribute": "memberOf"
},
"Worker": {
"ExecutablePath": "src\\ZB.MOM.WW.MxGateway.Worker\\bin\\x86\\Release\\ZB.MOM.WW.MxGateway.Worker.exe",
"WorkingDirectory": null,
"RequiredArchitecture": "X86",
"StartupTimeoutSeconds": 30,
"StartupProbeRetryAttempts": 3,
"StartupProbeRetryDelayMilliseconds": 250,
"PipeConnectAttemptTimeoutMilliseconds": 2000,
"ShutdownTimeoutSeconds": 10,
"HeartbeatIntervalSeconds": 5,
"HeartbeatGraceSeconds": 15,
"MaxMessageBytes": 16777216
},
"Sessions": {
"DefaultCommandTimeoutSeconds": 30,
"MaxSessions": 64,
"MaxPendingCommandsPerSession": 128,
"DefaultLeaseSeconds": 1800,
"LeaseSweepIntervalSeconds": 30,
"AllowMultipleEventSubscribers": false
},
"Events": {
"QueueCapacity": 10000,
"BackpressurePolicy": "FailFast"
},
"Dashboard": {
"Enabled": true,
"AllowAnonymousLocalhost": true,
"RequireHttpsCookie": true,
"SnapshotIntervalMilliseconds": 1000,
"RecentFaultLimit": 100,
"RecentSessionLimit": 200,
"ShowTagValues": false,
"GroupToRole": {
"GwAdmin": "Administrator",
"GwReader": "Viewer"
}
},
"Protocol": {
"WorkerProtocolVersion": 1,
"MaxGrpcMessageBytes": 16777216
},
"Galaxy": {
"ConnectionString": "Server=localhost;Database=ZB;Integrated Security=True;TrustServerCertificate=True;Encrypt=False;",
"CommandTimeoutSeconds": 60,
"DashboardRefreshIntervalSeconds": 30,
"PersistSnapshot": true,
"SnapshotCachePath": "C:\\ProgramData\\MxGateway\\galaxy-snapshot.json"
},
"Alarms": {
"Enabled": false,
"SubscriptionExpression": "",
"DefaultArea": "",
"ReconcileIntervalSeconds": 30
}
}
}
Environment variables use the normal .NET double-underscore form. For example,
MxGateway__Sessions__MaxSessions=20 overrides
MxGateway:Sessions:MaxSessions.
Authentication Options
| Option | Default | Description |
|---|---|---|
MxGateway:Authentication:Mode |
ApiKey |
Selects public gRPC authentication. Supported values are ApiKey and Disabled. Disabled bypasses API-key verification and is for local development only. |
MxGateway:Authentication:SqlitePath |
C:\ProgramData\MxGateway\gateway-auth.db |
SQLite database path for API-key records and audit rows when API-key authentication is enabled. |
MxGateway:Authentication:PepperSecretName |
MxGateway:ApiKeyPepper |
Configuration key used to read the HMAC pepper for API-key secret hashing. The dashboard effective configuration redacts this value. |
MxGateway:Authentication:RunMigrationsOnStartup |
true |
Runs SQLite auth schema migrations at gateway startup when API-key authentication is enabled. |
When Mode is ApiKey, SqlitePath and PepperSecretName must be present.
SqlitePath must be a valid filesystem path.
Ldap Options
The MxGateway:Ldap section configures the dashboard's LDAP login (the gRPC API
uses API keys, not LDAP — see Authentication). The same
section is bound twice: the runtime bind/search is performed by the shared
ZB.MOM.WW.Auth.Ldap provider wired up by AddZbLdapAuth, while the gateway's
own LdapOptions shadow exists only for startup validation, the redacted
effective-config display, and the dev/default values. The two stay
field-compatible so the one section binds onto both. The gateway ships
dev-friendly defaults (plaintext localhost); the shared provider's own defaults
are secure-by-default.
| Option | Default | Description |
|---|---|---|
MxGateway:Ldap:Enabled |
true |
Enables LDAP-backed dashboard login. When false, the rest of the section is not validated and LDAP login is not wired up. |
MxGateway:Ldap:Server |
localhost |
LDAP server host. Required when Enabled. |
MxGateway:Ldap:Port |
3893 |
LDAP server port. Must be a valid port (1–65535). |
MxGateway:Ldap:Transport |
None |
Transport/TLS mode. One of None (plaintext), StartTls (upgrade a plaintext connection to TLS), or Ldaps (TLS from connect). Replaces the former boolean UseTls. |
MxGateway:Ldap:AllowInsecure |
true |
Allows plaintext LDAP connections. Must be true when Transport is None; setting Transport=None with AllowInsecure=false fails validation. |
MxGateway:Ldap:SearchBase |
dc=zb,dc=local |
Search base distinguished name for user lookup. Required when Enabled. |
MxGateway:Ldap:ServiceAccountDn |
cn=serviceaccount,dc=zb,dc=local |
Service account DN used to bind before searching for the logging-in user. Required when Enabled. Redacted in the effective-config display. |
MxGateway:Ldap:ServiceAccountPassword |
serviceaccount123 |
Service account bind password. Required when Enabled. Never logged; redacted in the effective-config display. |
MxGateway:Ldap:UserNameAttribute |
cn |
Attribute matched against the login user name (the dev GLAuth directory keys users by cn, not uid). Required when Enabled. |
MxGateway:Ldap:DisplayNameAttribute |
cn |
Attribute read for the user's display name. Required when Enabled. |
MxGateway:Ldap:GroupAttribute |
memberOf |
Attribute read for the user's group membership. The resulting group names are mapped to dashboard roles by MxGateway:Dashboard:GroupToRole. Required when Enabled. |
When Enabled is true, Server, SearchBase, ServiceAccountDn,
ServiceAccountPassword, UserNameAttribute, DisplayNameAttribute, and
GroupAttribute must be non-blank, Port must be valid, and AllowInsecure
must be true whenever Transport is None. Group-to-role mapping lives in the
dashboard section; see MxGateway:Dashboard:GroupToRole below and
glauth.md.
Worker Options
| Option | Default | Description |
|---|---|---|
MxGateway:Worker:ExecutablePath |
src\ZB.MOM.WW.MxGateway.Worker\bin\x86\Release\ZB.MOM.WW.MxGateway.Worker.exe |
Path to the x86 worker executable launched for each gateway session. The path must be valid and point to a .exe file. |
MxGateway:Worker:WorkingDirectory |
null |
Optional working directory for the worker process. When set, it must be a valid filesystem path. |
MxGateway:Worker:RequiredArchitecture |
X86 |
Required Portable Executable architecture for the worker. Supported values are X86 and X64; MXAccess parity uses X86. |
MxGateway:Worker:StartupTimeoutSeconds |
30 |
Total startup budget for process launch, startup probe, pipe connect, handshake, and worker readiness. |
MxGateway:Worker:StartupProbeRetryAttempts |
3 |
Number of retry attempts for transient worker startup probe failures before pipe connection and handshake continue. |
MxGateway:Worker:StartupProbeRetryDelayMilliseconds |
250 |
Delay between transient startup probe retry attempts. |
MxGateway:Worker:PipeConnectAttemptTimeoutMilliseconds |
2000 |
Per-attempt timeout used by the worker named-pipe connect retry path. The overall pipe connection still stays under the startup budget. |
MxGateway:Worker:ShutdownTimeoutSeconds |
10 |
Grace period for worker shutdown before the gateway treats shutdown as failed and may kill the worker process tree. |
MxGateway:Worker:HeartbeatIntervalSeconds |
5 |
Worker heartbeat send interval and gateway heartbeat check cadence input. |
MxGateway:Worker:HeartbeatGraceSeconds |
15 |
Maximum age of the last worker heartbeat before the gateway faults the worker. This must be greater than or equal to HeartbeatIntervalSeconds. |
MxGateway:Worker:MaxMessageBytes |
16777216 |
Maximum worker IPC frame payload size in bytes. The validator allows values from 1024 through 268435456. |
StartupProbeRetryAttempts, StartupProbeRetryDelayMilliseconds,
PipeConnectAttemptTimeoutMilliseconds, timeout values, heartbeat values, and
MaxMessageBytes must be positive. MaxMessageBytes is intentionally bounded
to avoid accidental large allocations from malformed or oversized frames.
Session Options
| Option | Default | Description |
|---|---|---|
MxGateway:Sessions:DefaultCommandTimeoutSeconds |
30 |
Default timeout used while the gateway waits for a worker command reply when an open-session request does not provide a positive command timeout. |
MxGateway:Sessions:MaxSessions |
64 |
Maximum number of concurrently open gateway sessions. Session opens reserve a slot atomically before worker creation. |
MxGateway:Sessions:MaxPendingCommandsPerSession |
128 |
Maximum number of pending worker commands for one session. Excess commands fail fast instead of queueing indefinitely. |
MxGateway:Sessions:DefaultLeaseSeconds |
1800 |
Initial session lease and refresh duration. Unary client activity extends the lease by this duration. |
MxGateway:Sessions:LeaseSweepIntervalSeconds |
30 |
Hosted monitor interval for closing expired leases. Active event-stream subscribers keep a session from expiring while the stream remains attached. |
MxGateway:Sessions:AllowMultipleEventSubscribers |
false |
Controls whether multiple StreamEvents subscribers may attach to one session. true is rejected until event fan-out is implemented. |
All numeric session options must be greater than zero. The current event stream implementation supports one active subscriber per session; this preserves event ordering and avoids competing consumers.
Event Options
| Option | Default | Description |
|---|---|---|
MxGateway:Events:QueueCapacity |
10000 |
Capacity for bounded per-session event queues used by the gateway worker event channel and the public gRPC event stream queue. |
MxGateway:Events:BackpressurePolicy |
FailFast |
Event backpressure behavior. FailFast faults the session on public stream queue overflow. DisconnectSubscriber disconnects only the slow stream. |
QueueCapacity must be greater than zero. With FailFast, queue overflow
faults the affected worker or session instead of silently dropping MXAccess
events. With DisconnectSubscriber, public gRPC stream overflow terminates only
the affected stream while the MXAccess session remains active.
Dashboard Options
| Option | Default | Description |
|---|---|---|
MxGateway:Dashboard:Enabled |
true |
Enables Blazor Server dashboard route mapping. The dashboard mounts at the host root (/); there is no separate path-base prefix. |
MxGateway:Dashboard:AllowAnonymousLocalhost |
true |
Allows loopback dashboard requests to bypass the dashboard cookie requirement for local development. Remote requests still require dashboard authentication. |
MxGateway:Dashboard:RequireHttpsCookie |
true |
Sets the dashboard auth cookie's secure policy. true keeps CookieSecurePolicy.Always — the cookie is only sent over HTTPS, which matches a production HTTPS deployment. Set to false for plain-HTTP dev deployments to use CookieSecurePolicy.SameAsRequest; the cookie is still flagged Secure on HTTPS requests, but it can round-trip over HTTP. Browsers drop Secure cookies set over HTTP from non-localhost hosts, so leaving this true while serving the dashboard over plain HTTP will break login from any remote browser. |
MxGateway:Dashboard:CookieName |
MxGatewayDashboard |
Dashboard auth cookie name. Leave unset (null/blank) to use the default. Override it to give a distinct name to a gateway that shares a hostname with another gateway instance: browser cookies are scoped by host+path but not by port, so two instances on the same host would otherwise clobber each other's dashboard session under a shared cookie name. Changing it signs out existing dashboard sessions on next deploy. |
MxGateway:Dashboard:SnapshotIntervalMilliseconds |
1000 |
Dashboard snapshot refresh interval used by the snapshot SignalR hub and the pages that subscribe to it. |
MxGateway:Dashboard:RecentFaultLimit |
100 |
Maximum number of fault summaries projected into each dashboard snapshot. |
MxGateway:Dashboard:RecentSessionLimit |
200 |
Maximum number of session summaries projected into each dashboard snapshot. |
MxGateway:Dashboard:ShowTagValues |
false |
Reserved display control for tag values. The dashboard does not show full tag values by default. |
MxGateway:Dashboard:GroupToRole |
(empty) | LDAP group → dashboard role mapping. Keys are LDAP group names (short CN or full DN — leading-RDN match). Values must be Administrator (read/write, API-key CRUD) or Viewer (read-only). A user whose LDAP groups don't intersect this map cannot sign in; with no mapping at all, only the loopback bypass admits anyone. |
SnapshotIntervalMilliseconds must be greater than zero. RecentFaultLimit
and RecentSessionLimit must be greater than or equal to zero.
GroupToRole values are validated at startup; invalid role names fail
validation. Emptiness is allowed (a closed deployment that admits no LDAP
users) but practical deployments populate at least one Admin group.
Authorization policies
Three authorization policies are registered out of these options:
MxGateway.Dashboard.Viewer— gates the Razor component routes. Satisfied by either dashboard role (Administrator or Viewer), byAllowAnonymousLocalhoston loopback, or byAuthentication.Mode = Disabled.MxGateway.Dashboard.Admin— gates write-capable surfaces (API-key CRUD). Satisfied only by the Administrator role (same environmental bypasses).MxGateway.Dashboard.HubClients— attached to the SignalR hubs. Accepts either the dashboard cookie scheme or theMxGateway.Dashboard.HubTokenbearer scheme (used by SignalR's WebSocket upgrade path where the HttpOnly cookie can't be forwarded).
SignalR hubs
When the dashboard is enabled, three hubs are mapped under /hubs/*:
GET /hubs/snapshot— pushesDashboardSnapshotwhenever the snapshot service produces a new one. Drives every page that inheritsDashboardPageBase; replaces the earlier polling loop.GET /hubs/alarms— re-broadcasts theAlarmFeedMessagestream from the central alarm monitor to all connected clients (group__alarms__).GET /hubs/events— per-session MxEvent feed. Clients callSubscribeSession(sessionId)to joinsession:{id}. Events are mirrored from the corresponding gRPCStreamEventscall as a fire-and-forget side-effect; the dashboard only sees events while a gRPC client is also subscribed to that session.
GET /hubs/token (cookie-only) mints a 30-minute data-protected bearer
token for the calling user; the Blazor pages use it via
DashboardHubConnectionFactory to authenticate the SignalR connection.
Protocol Options
| Option | Default | Description |
|---|---|---|
MxGateway:Protocol:WorkerProtocolVersion |
1 |
Worker IPC protocol version expected by the gateway and worker. This must match GatewayContractInfo.WorkerProtocolVersion. |
MxGateway:Protocol:MaxGrpcMessageBytes |
16777216 |
Public gRPC max send and receive message size in bytes. The same default is used by official clients. The validator allows values from 1024 through 268435456. |
The protocol option is exposed for diagnostics and explicit deployment configuration, not for compatibility negotiation. A mismatch fails validation at startup.
Galaxy Options
| Option | Default | Description |
|---|---|---|
MxGateway:Galaxy:ConnectionString |
Server=localhost;Database=ZB;Integrated Security=True;TrustServerCertificate=True;Encrypt=False; |
SQL Server connection string for the Galaxy Repository (ZB) used by the GalaxyRepository browse RPCs. Override in production via MxGateway__Galaxy__ConnectionString. |
MxGateway:Galaxy:CommandTimeoutSeconds |
60 |
Per-command SQL timeout for all Galaxy browse RPCs. |
MxGateway:Galaxy:DashboardRefreshIntervalSeconds |
30 |
Interval between background refreshes of the dashboard Galaxy summary cache. SQL is hit at most once per interval regardless of dashboard render rate. |
MxGateway:Galaxy:PersistSnapshot |
true |
Persists the latest successful Galaxy browse dataset to disk. When true, the cache reloads that snapshot at startup so clients can still browse last-known data while the Galaxy database is unreachable. The restored data is served with Stale status until a live query confirms it. |
MxGateway:Galaxy:SnapshotCachePath |
C:\ProgramData\MxGateway\galaxy-snapshot.json |
File path for the persisted Galaxy browse snapshot. Ignored when PersistSnapshot is false. The snapshot is written atomically (temp file plus rename). |
See Galaxy Repository Browse for the RPC surface and behavior.
Alarm Options
| Option | Default | Description |
|---|---|---|
MxGateway:Alarms:Enabled |
false |
Gates the gateway's always-on central alarm monitor. When true, the gateway opens one gateway-owned worker session dedicated to alarms, caches the active-alarm set, and fans it out to every client through the StreamAlarms RPC — no client opens its own session to see alarms. |
MxGateway:Alarms:SubscriptionExpression |
(empty) | AVEVA alarm-subscription expression the monitor subscribes on startup, in canonical \\<machine>\Galaxy!<area> form. The literal Galaxy provider is correct regardless of the Galaxy database name. When empty and Enabled is true, the gateway falls back to \\<MachineName>\Galaxy!<DefaultArea> if DefaultArea is set. |
MxGateway:Alarms:DefaultArea |
(empty) | Area name used to compose a default subscription when SubscriptionExpression is empty. If both are empty while Enabled is true, the monitor faults with a configuration diagnostic. |
MxGateway:Alarms:ReconcileIntervalSeconds |
30 |
How often the monitor reconciles its in-process alarm cache against the worker's authoritative active-alarm snapshot, catching transitions the live poll-and-diff feed missed. Floored at 5 seconds. |
The alarm monitor is independent of client sessions: AcknowledgeAlarm and
StreamAlarms are session-less RPCs served by the monitor.
Host Endpoints and Transport Security (Kestrel)
The listening endpoints are not part of the MxGateway section. The gateway
uses the stock ASP.NET Core host (WebApplication.CreateBuilder) with no
ConfigureKestrel call in code, so endpoints come entirely from the standard
Kestrel configuration section. On the deployed hosts these values are supplied
as NSSM environment variables (Kestrel__Endpoints__...), not from
appsettings.json.
Two named endpoints are bound:
| Endpoint name | Purpose | Protocol requirement |
|---|---|---|
Http |
Public gRPC API (sessions, invoke, events, Galaxy browse) | HTTP/2 |
Dashboard |
Blazor dashboard and SignalR hubs | HTTP/1.1 (HTTP/2 optional) |
Both endpoints share one routing pipeline; the names only select which TCP port serves which traffic. The gRPC endpoint must negotiate HTTP/2, which drives the protocol settings below.
Plaintext (current deployments)
Both running hosts (10.100.0.48 and wonder-app-vd03) serve the gRPC port in
cleartext HTTP/2 (h2c). Because cleartext HTTP/2 has no ALPN to negotiate
the protocol, the gRPC endpoint must be pinned to Http2 with prior knowledge:
Kestrel__Endpoints__Http__Url=http://0.0.0.0:5120
Kestrel__Endpoints__Http__Protocols=Http2
Kestrel__Endpoints__Dashboard__Url=http://0.0.0.0:5130
In this mode all client↔gateway traffic — including the
authorization: Bearer mxgw_... API key and any WriteSecured / AuthenticateUser
payloads — crosses the network unencrypted. This is acceptable only on a
trusted/isolated network segment. Prefer TLS for anything else.
TLS
To encrypt the gRPC channel, give the Http endpoint an https:// URL and a
certificate. Over TLS, ALPN negotiates HTTP/2, so the explicit Protocols=Http2
pin is no longer required (the default Http1AndHttp2 works for gRPC over TLS).
appsettings.json form:
{
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "https://0.0.0.0:5120",
"Certificate": {
"Path": "C:\\ProgramData\\MxGateway\\certs\\gateway.pfx",
"Password": "<pfx-password>"
}
},
"Dashboard": {
"Url": "https://0.0.0.0:5130",
"Certificate": {
"Path": "C:\\ProgramData\\MxGateway\\certs\\gateway.pfx",
"Password": "<pfx-password>"
}
}
}
}
}
Equivalent NSSM environment-variable form (how config is delivered on the hosts — see [server deploy mechanics in the project notes]):
Kestrel__Endpoints__Http__Url=https://0.0.0.0:5120
Kestrel__Endpoints__Http__Certificate__Path=C:\ProgramData\MxGateway\certs\gateway.pfx
Kestrel__Endpoints__Http__Certificate__Password=<pfx-password>
Kestrel__Endpoints__Dashboard__Url=https://0.0.0.0:5130
Kestrel__Endpoints__Dashboard__Certificate__Path=C:\ProgramData\MxGateway\certs\gateway.pfx
Kestrel__Endpoints__Dashboard__Certificate__Password=<pfx-password>
Certificate sourcing options (any standard ASP.NET Core form is accepted):
| Form | Keys |
|---|---|
| PFX file | Certificate:Path (+ Certificate:Password if encrypted) |
| PEM pair | Certificate:Path (cert) + Certificate:KeyPath (private key) |
| Windows cert store | Certificate:Subject, Certificate:Store (e.g. My), Certificate:Location (LocalMachine), Certificate:AllowInvalid |
The certificate's CN/SAN must cover the host name clients dial (or clients must
set a server-name override — see below). The dashboard endpoint can keep its own
certificate independent of the gRPC endpoint; pair this with
MxGateway:Dashboard:RequireHttpsCookie (true) for production HTTPS.
Automatic self-signed certificate
mxaccessgw is an internal tool with no PKI to issue certificates, so requiring
an operator to supply one before TLS works pushed deployments toward plaintext.
To avoid that, the gateway fills in a self-signed certificate when an HTTPS
endpoint is configured without one.
Trigger. At startup the gateway inspects Kestrel:Endpoints:*. If any
endpoint has an https:// URL and no Certificate subsection of its own, and no
Kestrel:Certificates:Default is set, the gateway generates (or loads) a
persisted self-signed certificate and wires it in as the HTTPS default via
ConfigureHttpsDefaults. All-plaintext deployments are untouched: when no HTTPS
endpoint is configured, no certificate or key material is generated or written.
Generated certificate. ECDSA P-256, serverAuth EKU, validity ≈
ValidityYears (default 10 years, with one day of clock-skew slack before
notBefore). SANs cover localhost, the machine name (and its FQDN when
resolvable), each entry in AdditionalDnsNames, and the loopback addresses
127.0.0.1 and ::1.
MxGateway:Tls:* options. All optional; the zero-config path needs none of
them.
| Option | Default | Purpose |
|---|---|---|
Tls:SelfSignedCertPath |
C:\ProgramData\MxGateway\certs\gateway-selfsigned.pfx |
Where the generated certificate is persisted |
Tls:ValidityYears |
10 |
Lifetime of the generated certificate (validated 1–100) |
Tls:AdditionalDnsNames |
[] |
Extra DNS SANs (e.g. a load-balancer name) |
Tls:RegenerateIfExpired |
true |
Replace an expired persisted certificate instead of failing |
ValidityYears is validated by GatewayOptionsValidator (range 1–100); the
"HTTPS endpoint configured but no certificate available" fail-fast lives in the
bootstrap/provider, because the validator only sees the MxGateway section, not
Kestrel:Endpoints.
Persistence. The PFX is written with an empty export password — a random
in-memory password could not be reused across restarts, which the
persist-and-reuse model requires. The private key is instead protected at rest by
filesystem permissions: a restrictive ACL on Windows (SYSTEM + Administrators,
inherited ACEs stripped) on the certs directory and file, and mode 0600 on
non-Windows. The write is atomic (hardened temp file, then move). The persisted
certificate is reused across restarts (stable thumbprint, so CA-pinning clients
keep working) and regenerated only when it is missing, expired (and
RegenerateIfExpired is true), or unreadable/corrupt. If the directory is not
writable or the ACL cannot be applied, the gateway fails fast with a diagnostic
naming the path rather than falling back to an in-memory certificate.
Logging. On generate or load, the gateway logs the certificate thumbprint,
SAN list, and notAfter at Information. The PFX bytes, export password, and
private key are never logged.
Operator override. The generated certificate is only the HTTPS default. To
use a real certificate, configure one explicitly — either per endpoint via
Kestrel:Endpoints:<name>:Certificate (Path/Subject/Thumbprint, etc., as
in the table above) or globally via Kestrel:Certificates:Default. An
explicitly-configured certificate takes precedence, and the gateway then writes
no self-signed material.
Client side
Each official client opts into TLS explicitly. For the .NET client
(MxGatewayClientOptions):
| Option | Effect |
|---|---|
UseTls (default false) |
Enables TLS. Requires an https:// endpoint; an https:// endpoint without UseTls fails validation, and vice versa. |
CaCertificatePath |
Pins a custom root (self-signed / private CA) using CustomRootTrust chain validation instead of the OS trust store; the .NET client also enforces the certificate hostname/SAN match on this path. |
RequireCertificateValidation (default false) |
Forces OS/system-trust verification on a TLS connection with no pinned CA. Leave false for the lenient default. |
ServerNameOverride |
SNI / certificate host name override when the dialed host differs from the certificate CN/SAN. |
To pair with the auto-generated self-signed certificate above, the clients are
lenient by default: a TLS connection with no pinned CA accepts whatever
certificate the gateway presents. Pin CaCertificatePath to verify, or set
RequireCertificateValidation to force system-trust verification without
pinning. The other language clients expose the equivalent options; the exact
behavior differs per stack — Python uses trust-on-first-use and Rust is pin-only.
See each client README for the as-built behavior.
Gateway↔worker IPC
Transport security here applies only to the public gRPC channel. The
gateway↔worker link is a per-session named pipe
(mxaccess-gateway-{gatewayPid}-{sessionId}), not a network socket. It is not
TLS-encrypted and does not need to be: it never leaves the local Windows host and
is secured by the OS pipe ACL. See Worker Frame Protocol.