Server config
In trio, mobile talks to "first" server, over a single websocket endpoint. The "second" server is used in inter-server communication, during keygen and recovery, hence not exposed to mobile. By default the endpoint points at the public demo:
| Purpose | Default value |
|---|---|
MPC websocket (WebsocketConfig.url) | trio-server.demo.silencelaboratories.com (port 443, TLS) |
| Cloud verifying key | 9c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e |
You'll typically swap these for one of three reasons: pointing at your own dev servers, running locally for hacking, or moving to a production deployment of your own.
Unlike duo, trio does not call an HTTP endpoint for export — session.export(keyId) runs entirely over the websocket, so there is no DEMO_SERVER_HTTP_URL to configure.
Where the values live
The websocket URL, port, and cloud verifying key are all defined in VaultSessionManager.
- Android
- iOS / macOS
companion object {
private const val DEMO_SERVER_URL = "trio-server.demo.silencelaboratories.com"
private const val DEMO_SERVER_PORT = 443
private const val CLOUD_VERIFYING_KEY =
"9c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e"
}
private val websocketConfig = WebsocketConfig(
url = DEMO_SERVER_URL,
port = DEMO_SERVER_PORT,
isSecure = true,
)
private static let demoServerUrl = "trio-server.demo.silencelaboratories.com"
private static let cloudVerifyingKey =
"9c4c79e942bbc3ff1d6ace7256404d701498056978cc4638c35832acdf821b1e"
private func createWebsocketConfig() -> WebsocketConfig {
WebsocketConfig(url: Self.demoServerUrl, port: 443, isSecure: true)
}
Configuring the WebsocketConfig endpoint
WebsocketConfig accepts the endpoint two ways — the demo config above uses the host-plus-parts form so the TLS scheme is explicit:
- Android
- iOS / macOS
// Full URL — used verbatim; port and isSecure are ignored.
WebsocketConfig(url = "wss://your-server.com")
// Host + parts — the scheme and port are composed from isSecure and port.
WebsocketConfig(url = "your-server.com", port = 443, isSecure = true) // -> wss://your-server.com:443
WebsocketConfig(url = "10.0.2.2", port = 8080, isSecure = false) // -> ws://10.0.2.2:8080 (local dev)
// Optional token, sent as the first message once connected (e.g. a JWT).
WebsocketConfig(url = "wss://your-server.com", authenticationToken = "<jwt>")
// Full URL — used verbatim; port and isSecure are ignored.
WebsocketConfig(url: "wss://your-server.com")
// Host + parts — the scheme and port are composed from isSecure and port.
WebsocketConfig(url: "your-server.com", port: 443, isSecure: true) // -> wss://your-server.com:443
WebsocketConfig(url: "localhost", port: 8080, isSecure: false) // -> ws://localhost:8080 (local dev)
// Optional token, sent as the first message once connected (e.g. a JWT).
WebsocketConfig(url: "wss://your-server.com", authenticationToken: "<jwt>")
port and isSecure (default true) apply only when url has no scheme; a full ws:///wss:// URL is used as-is.
Pointing at local Trio servers
Trio runs two server processes (first and second) instead of duo's one. The full local-setup walkthrough — Docker compose file, environment variables, and the script that prints the cloud verifying key — is in Get started with Trio Servers. Read that first; it ends with both containers up and a verifying key in the logs.
Once your local servers are running, change two values in the example — mobile only ever connects to the first server:
- Vault websocket URL (
VaultSessionManager.<DEMO_SERVER_URL|demoServerUrl>) — point at your localfirstendpoint and setisSecure = falsefor a plaintextws://connection. - Cloud verifying key (
VaultSessionManager.<CLOUD_VERIFYING_KEY|cloudVerifyingKey>) — copy the hex string thefirstserver prints on startup. The handshake fails silently if this doesn't match.
- Android
- iOS / macOS
The Android emulator routes localhost to the emulator itself, so use 10.0.2.2 to reach servers on your host machine:
private const val DEMO_SERVER_URL = "10.0.2.2"
private const val DEMO_SERVER_PORT = 8080
private const val CLOUD_VERIFYING_KEY = "<hex from first server logs>"
// ...
private val websocketConfig = WebsocketConfig(url = DEMO_SERVER_URL, port = DEMO_SERVER_PORT, isSecure = false)
For the iOS Simulator and macOS targets, localhost reaches your machine directly:
private static let demoServerUrl = "localhost"
private static let cloudVerifyingKey = "<hex from first server logs>"
// ...
WebsocketConfig(url: Self.demoServerUrl, port: 8080, isSecure: false)
A ws:// (cleartext) connection needs App Transport Security to allow it. Add to Info.plist (or via INFOPLIST_KEY_* build settings):
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
On a physical device, swap localhost for your machine's LAN IP (e.g. 192.168.1.100).