Tunnels — reference
This reference covers the env vars conduit-tunnel accepts, the built-in connectors it can run, and the Conduit-managed config model. For first-deploy see the Quickstart; for failure-mode→fix mapping see Troubleshooting.
Env-var contract
Section titled “Env-var contract”The Tunnel takes two env vars — and only two. Everything else (which connectors run, their endpoints and credentials) comes from Conduit over the tunnel, not from the environment.
RELAY_URL (required)
Section titled “RELAY_URL (required)”The WYRE relay endpoint the Tunnel dials. Your Conduit operator provides it alongside your enrollment token.
- Production:
wss://conduit-wss.wyre.ai - Staging:
wss://staging-wss.conduit.wyre.ai - MUST be
wss://— the Tunnel rejects any other scheme at boot (no plain non-TLSws, nohttp://, nohttps://).
ENROLLMENT_TOKEN (required)
Section titled “ENROLLMENT_TOKEN (required)”An identity-only JWT minted by your Conduit operator. It binds only your org identity and carries no capabilities — the Tunnel registers with zero capabilities and comes online empty. Your operator then chooses and configures connectors in Conduit, and Conduit pushes that config down the tunnel.
How to get one: mint it from Connections → Tunnels in Conduit (the “Add Tunnel” panel on the list page), or ask your Conduit operator to mint it via the admin API.
CAPABILITIES — removed (the Tunnel boot-fails if set)
Section titled “CAPABILITIES — removed (the Tunnel boot-fails if set)”There is no CAPABILITIES variable in the Tunnel. Capabilities are no longer declared on the host — they’re managed in Conduit and pushed to the Tunnel.
If CAPABILITIES is present in the environment, the Tunnel fails to boot on purpose and tells you capabilities are managed in Conduit now (pointing you at the legacy container for the old behavior). This is a loud guard, not a silent ignore: it stops a v1 env file from being pasted into a v2 host and quietly doing the wrong thing.
Optional env vars
Section titled “Optional env vars”| Var | Default | Notes |
|---|---|---|
LOG_LEVEL |
info |
One of debug, info, warn, error. Use debug for first-deploy troubleshooting. |
The config model — operator-pushed, encrypted, memory-only
Section titled “The config model — operator-pushed, encrypted, memory-only”Unlike the v1 container, the Tunnel does not read its capability/vendor config from the host. Instead:
- Configured in Conduit. You choose which connectors run and set their endpoints and credentials — from a tunnel’s page under Connections → Tunnels, or the admin API.
- Encrypted at rest. Connector config is encrypted at rest in Conduit with AES-256-GCM.
- Only ever over the TLS tunnel. Config travels down the same WSS tunnel the Tunnel dialed — never over any other channel.
- Memory-only on the Tunnel. The Tunnel holds config in memory and never writes it to disk.
- Self-healing. Because config is memory-only, a restart clears it — but Conduit automatically re-pushes the stored config within ~60s. No manual re-entry.
Built-in connectors
Section titled “Built-in connectors”The Tunnel ships with these built-in connectors. Your operator enables and configures them in Conduit.
A connectivity proof. Returns what you send it — use it to confirm the tunnel is live and requests round-trip end to end before wiring a real system. No configuration beyond enabling it.
Read-only access to a Microsoft SQL Server database. See the SQL Server guide for the full walkthrough.
Read-only by design. The mssql connector never writes. Writes go through the application layer, never raw SQL.
Tools it exposes:
| Tool | What it does |
|---|---|
query |
Runs a single read-only SELECT/WITH statement. Writes and multi-statement batches are refused. Results are capped at 100 rows by default, 1000 max. |
list_tables |
Lists tables available to the connected SQL principal. |
describe_table |
Returns a table’s columns and types. |
Config fields (pushed from Conduit):
| Field | Default | Notes |
|---|---|---|
host |
— | SQL Server hostname or IP. |
port |
1433 |
SQL Server TCP port. |
database |
— | Target database. |
auth |
"sql" |
Authentication mode: "sql" (default) uses user + password below; "integrated" uses Windows Integrated Auth (SSPI) and takes no user/password. Requires a Windows host. |
user |
— | SQL login. Use a scoped read-only principal (see the SQL Server guide). Not used with auth: "integrated". |
password |
— | Password for that login. Stored encrypted in Conduit; pushed over the tunnel; held in memory only. Not used with auth: "integrated". |
encrypt |
"true" |
TLS to SQL Server. "true" validates the server’s certificate against system roots — an on-prem SQL Server with a self-signed cert will fail unless that cert is trusted on the Tunnel host. Use "disable" only for a lab DB with no TLS. |
The mssql connector supports two authentication modes. With auth: "sql" (the default) it connects using the user + password above, stored encrypted in Conduit and held in the Tunnel’s memory only. With auth: "integrated" it uses Windows Integrated Auth (SSPI) and authenticates as its own Windows service identity — no user/password are set. When that service runs under a gMSA (install.ps1 -ServiceAccount 'DOMAIN\gmsa$'), that identity is the gMSA, so no SQL credential is stored anywhere — in Conduit or on the host. Integrated auth requires a Windows host (the driver’s winsspi provider); the Tunnel rejects auth: "integrated" on non-Windows. The integrated-auth mechanism is verified against SQL Server (the Tunnel authenticates as its Windows service identity via SSPI and runs read-only queries); running the service under a gMSA is validated end-to-end (the Tunnel authenticates to SQL Server as DOMAIN\gmsa$ with no stored credential); as with any gMSA, install and authorize it on the host first (Install-ADServiceAccount).
postgres
Section titled “postgres”Read-only access to a PostgreSQL database. Same three tools as mssql (query / list_tables / describe_table), same read-only guarantees, sharing the same query engine.
Config fields (pushed from Conduit):
| Field | Default | Notes |
|---|---|---|
host |
— | PostgreSQL hostname or IP. |
port |
5432 |
PostgreSQL TCP port. |
database |
— | Target database. |
user |
— | Login role. Use a scoped read-only role. |
password |
— | Password for that role. Stored encrypted in Conduit; pushed over the tunnel; held in memory only. |
sslmode |
"require" |
TLS mode. Use "disable" only for a lab DB with no TLS. |
Read-only access to a MySQL / MariaDB database. Same three tools and read-only guarantees as mssql/postgres.
Config fields (pushed from Conduit):
| Field | Default | Notes |
|---|---|---|
host |
— | MySQL/MariaDB hostname or IP. |
port |
3306 |
MySQL TCP port. |
database |
— | Target database. |
user |
— | Login. Use a scoped read-only user. |
password |
— | Password for that user. Stored encrypted in Conduit; pushed over the tunnel; held in memory only. |
tls |
"preferred" |
One of preferred (TLS if offered), true (require), skip-verify, or false (plaintext — lab only). |
mcp-proxy
Section titled “mcp-proxy”Fronts any local MCP server the Tunnel host can run — for example the Veeam MCP server. The Tunnel launches the configured command, performs the MCP handshake once, and forwards that server’s tools/list and tools/call over the tunnel. This is how an existing MCP server reaches Conduit without a rewrite. The command is operator-configured and runs as the Tunnel’s own unprivileged (DynamicUser) service identity.
Config fields (pushed from Conduit):
| Field | Default | Notes |
|---|---|---|
command |
— | The executable to run the local MCP server (e.g. node). |
args |
[] |
Arguments to that command (e.g. the server’s entry-point path). |
env |
{} |
Environment for the child process — where the server’s own credentials go (e.g. PRODUCT_NAME, WEB_URL, ADMIN_USERNAME, ADMIN_PASSWORD for the Veeam server). |
cwd |
— | Optional working directory for the child. |
On-prem raw-protocol example: IQMS / DELMIAworks. mcp-proxy isn’t just for
HTTP-fronted local servers — it’s the right path for any local MCP server,
including one that itself speaks a raw non-HTTP protocol on the customer’s LAN.
iqms-mcp talks directly to an on-prem
Oracle DB (EnterpriseIQ/DELMIAworks), which is almost never reachable from
Conduit’s cloud over the open internet — exactly the case this connector type
exists for. Run it via npx on the Tunnel host, next to the customer’s Oracle
network, with the three credentials iqms-mcp’s own README documents for its
“Local (stdio)” mode:
"iqms": { "type": "mcp-proxy", "command": "npx", "args": ["-y", "github:WYRE-AI/iqms-mcp"], "env": { "IQMS_ORACLE_USER": "eiq_ro", "IQMS_ORACLE_PASSWORD": "...", "IQMS_ORACLE_CONNECT_STRING": "host:port/service_name" }}Conduit’s hosted iqms vendor entry (a containerUrl-based connection,
documented alongside its own credential fields) still exists for the rare
customer whose Oracle instance genuinely is reachable from the internet — but
for the typical on-prem case, this tunnel path is the one that actually works.
http-bridge
Section titled “http-bridge”Carries on-prem vendor connections (guide): when an org connection is saved with the Via Tunnel deployment, Conduit’s cloud vendor integration sends its API calls down the tunnel and this built-in re-issues them locally against the vendor server on your network, then relays the response back.
Unlike the other built-ins, you never configure http-bridge in the
Add-connection modal — its config is derived, not authored:
- Its host allowlist is synced automatically from the org’s Via-Tunnel connections — one entry per connected vendor server, added on save and removed when a connection is deleted or switched back to Cloud. The bridge refuses any URL not on the list (scheme, host, port, and path-prefix all match component-wise), so the tunnel cannot be used to reach anything an org admin didn’t wire up.
- Each entry may carry a
caCertPem— a private CA to trust for that one host (this is how internal-PKI vendor servers work), and, as an API-only last resort for appliances with unexportable certificates, a per-hostinsecureSkipVerify. - Responses are capped at 10 MiB; redirects are returned to the cloud side, not followed on the LAN; hop-by-hop headers are stripped both ways.
Named instances (more than one of a connector)
Section titled “Named instances (more than one of a connector)”A connector’s config key is its slug — the slug__tool prefix clients see. By default the slug also names the built-in. To run several instances of one built-in (e.g. two Veeam MCP servers), add a type field: the slug becomes a free-form name and type selects the built-in.
{ "veeam-vbr": { "type": "mcp-proxy", "command": "node", "args": ["/opt/vbr-mcp/build/index.js"], "env": { "PRODUCT_NAME": "vbr" } }, "veeam-one": { "type": "mcp-proxy", "command": "node", "args": ["/opt/vone-mcp/build/index.js"], "env": { "PRODUCT_NAME": "vone" } }}Their tools surface as veeam-vbr__… and veeam-one__…. Omit type and the slug is the type ({"postgres": {…}} → the postgres built-in).
Observability
Section titled “Observability”- Live logs:
sudo journalctl -u conduit-tunnel -f - Registered (empty):
tunnel registered (v2, zero capabilities until config push)— the Tunnel is online and waiting for config. - Config applied:
config applied connectors=[...]— the operator’s config arrived and the listed connectors are live.
Service management
Section titled “Service management”The Tunnel runs as a systemd service (see Quickstart for the unit). Common operations:
sudo systemctl status conduit-tunnel # is it running?sudo systemctl restart conduit-tunnel # restart (config re-pushes within ~60s)sudo journalctl -u conduit-tunnel -f # follow logsOn restart the Tunnel re-registers empty, then Conduit re-pushes the stored config automatically — you’ll see the tunnel registered line followed by config applied.
Legacy: v1 Docker container
Section titled “Legacy: v1 Docker container”The v1 conduit-onprem-gateway Docker container is still supported for already-deployed sites. It uses the older model: a required CAPABILITIES env var whose slugs must byte-for-byte match the capabilities baked into the enrollment token (case-sensitive, no normalization). Its config lives in the host .env, not in Conduit.
If you’re running the v1 container, keep to that flow — the full legacy deploy (compose file, .env, cosign verify) is in Quickstart → Legacy: v1 Docker container. New deployments should use the Tunnel documented above.

