Server config
The duo example talks to a Duo server over two channels: a websocket for MPC protocol messages (handled by the SDK) and HTTP for fetching the server party's encrypted keyshare during export and for verifiable-backup verification (handled by the app). By default both point at the same public demo host:
| Purpose | Default value |
|---|---|
MPC websocket (WebsocketConfig.url) | wss://demo-server.silencelaboratories.com |
| Cloud verifying key | cfa1ff5424d14eb60614d7ddf65a32243d26ddf7000d10007853d7336395efe4 |
| Server HTTP API | https://demo-server.silencelaboratories.com |
You'll typically swap these for one of three reasons: pointing at your own dev server, running locally for hacking, or moving to a production deployment of your own.
Where the values live
The websocket URL, port, and cloud verifying key are defined in VaultSessionManager — the SDK handles MPC transport and session authentication internally. The server HTTP endpoint is in AppConstants.
- Android
- iOS / macOS
companion object {
private const val DEMO_SERVER_URL = "wss://demo-server.silencelaboratories.com"
private const val DEMO_SERVER_PORT = 8080
private const val CLOUD_VERIFYING_KEY =
"cfa1ff5424d14eb60614d7ddf65a32243d26ddf7000d10007853d7336395efe4"
}
private val websocketConfig = WebsocketConfig(
url = DEMO_SERVER_URL,
port = DEMO_SERVER_PORT,
isSecure = false,
)
object AppConstants {
const val DEMO_SERVER_HTTP_URL = "https://demo-server.silencelaboratories.com" // used by ExportImportViewModel
// ...
}
private static let demoServerUrl = "wss://demo-server.silencelaboratories.com"
private static let demoServerPort = 8080
private static let cloudVerifyingKey =
"cfa1ff5424d14eb60614d7ddf65a32243d26ddf7000d10007853d7336395efe4"
private func createWebsocketConfig() -> WebsocketConfig {
WebsocketConfig(url: Self.demoServerUrl)
}
nonisolated enum AppConstants {
static let DEMO_SERVER_HTTP_URL = "https://demo-server.silencelaboratories.com" // used by ExportImportManager
// ...
}
Pointing at a local Duo server
You'll need a local Duo server first. The simplest path is the Docker setup in the Kotlin Quick Start under "Optional: Run your own Duo Server" — that section walks through docker pull, the docker-compose.yml, and how to find the cloud verifying key in the server logs.
Once your server is running, change three values in the example:
- Vault websocket URL (
VaultSessionManager.<DEMO_SERVER_URL|demoServerUrl>) — point at your local server. - Cloud verifying key (
VaultSessionManager.<CLOUD_VERIFYING_KEY|cloudVerifyingKey>) — copy the hex string the local server prints on startup (Party VK <hex>). The wss handshake fails silently if this doesn't match the server's signing key. - Backup HTTP URL (
AppConstants.DEMO_SERVER_HTTP_URL) — changehttps://...tohttp://...(orhttps://...if your local server has TLS).
- Android
- iOS / macOS
The Android emulator routes localhost to the emulator itself, not the host. Use 10.0.2.2 to reach a server running on the host machine:
companion object {
private const val DEMO_SERVER_URL = "ws://10.0.2.2:8080"
private const val DEMO_SERVER_PORT = 8080
private const val CLOUD_VERIFYING_KEY = "<hex from local server logs>"
}
const val DEMO_SERVER_HTTP_URL = "http://10.0.2.2:8080"
isSecure = false is already set in the existing WebsocketConfig ctor for the demo URL — leave it false for ws://, flip to true for wss://.
For cleartext HTTP on Android, the demo's network_security_config.xml may need to allow 10.0.2.2. If ExportImportViewModel fails the backup fetch with CLEARTEXT communication not permitted, add a <domain-config> exception or temporarily set android:usesCleartextTraffic="true" in AndroidManifest.xml.
For the iOS Simulator and macOS targets, localhost works directly:
private static let demoServerUrl = "ws://localhost:8080"
private static let demoServerPort = 8080
private static let cloudVerifyingKey = "<hex from local server logs>"
static let DEMO_SERVER_HTTP_URL = "http://localhost:8080"
For an ws:// (cleartext) connection you'll need to allow arbitrary loads. Add to Info.plist (or to the build settings via INFOPLIST_KEY_*):
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
If you're running the server on a different machine on your LAN, swap localhost for the host's LAN IP.