Skip to content

Latest commit

 

History

History
117 lines (91 loc) · 4.38 KB

File metadata and controls

117 lines (91 loc) · 4.38 KB
name mobile-p2p-sync-ios
summary Couchbase Lite peer-to-peer sync for iOS/macOS (Swift) — URLEndpointListener, passive/active peer setup, TLS modes (anonymous, self-signed, CA cert), basic auth, certificate pinning, delta sync, local database-to-database replication
description Couchbase Lite peer-to-peer sync for iOS/macOS (Swift) — URLEndpointListener, passive/active peer setup, TLS modes (anonymous, self-signed, CA cert), basic auth, certificate pinning, delta sync, local database-to-database replication
compatibility Couchbase Lite iOS/macOS 4.x Enterprise Edition (Swift). P2P requires EE; local DB replication is available in CE.
metadata
last_verified handoff
2026-05
condition skill
user is on Android or Kotlin
mobile-p2p-sync-android
condition skill
user asks about sync or replication setup
mobile-sync-ios
condition skill
user asks about conflict resolution
mobile-conflict-resolution-ios
condition skill
user asks about iOS CRUD or queries
mobile-ios

Platform-agnostic concepts: shared/mobile/p2p-sync-concepts.md

Peer-to-Peer Sync — Couchbase Lite iOS/macOS

P2P sync runs directly between devices over a local network — no Sync Gateway required. Requires Enterprise Edition.

Architecture

Device A (passive — listener)          Device B (active — initiator)
  URLEndpointListener                    Replicator
  └── listens on TCP port                └── connects to Device A's URL
        ↕ WebSocket (ws:// or wss://)

Passive peer (listener)

import CouchbaseLiteSwift

var listenerConfig = URLEndpointListenerConfiguration(collections: [collection])
listenerConfig.port       = 4984
listenerConfig.disableTLS = true
listenerConfig.authenticator = ListenerPasswordAuthenticator { username, password in
    username == "device-b" && password == "secret"
}

let listener = URLEndpointListener(config: listenerConfig)
try listener.start()

let listenerURL = "ws://\(getLocalIPAddress()):\(listener.port!)/db"

Active peer (initiator)

let target = URLEndpoint(url: URL(string: "ws://192.168.1.10:4984/db")!)

var replConfig = ReplicatorConfiguration(target: target)
replConfig.addCollection(collection)
replConfig.replicatorType = .pushAndPull
replConfig.continuous     = false
replConfig.authenticator  = BasicAuthenticator(username: "device-b", password: "secret")

let replicator = Replicator(config: replConfig)
let token = replicator.addChangeListener { change in
    if change.status.activity == .stopped {
        print("Sync complete: \(change.status.error?.localizedDescription ?? "ok")")
    }
}
replicator.start()

TLS with self-signed certificate

// Passive peer — generate a self-signed cert
let attrs = [certAttrCommonName: "MyDevice"]
let identity = try TLSIdentity.createIdentity(
    forServer: true, attributes: attrs, expiration: nil, label: "my-listener-cert")

var listenerConfig = URLEndpointListenerConfiguration(collections: [collection])
listenerConfig.tlsIdentity = identity
listenerConfig.disableTLS  = false
// Active peer — pin the listener's certificate
let listenerCert: SecCertificate = /* retrieve out-of-band */
var replConfig = ReplicatorConfiguration(target: target)
replConfig.pinnedServerCertificate = listenerCert

Delta sync

Delta sync is enabled by default in EE when both peers support it. No configuration required.

Local database-to-database replication

let sourceDB = try Database(name: "source", config: dbConfig)
let targetDB = try Database(name: "target", config: dbConfig)

let target = DatabaseEndpoint(database: targetDB)
var replConfig = ReplicatorConfiguration(target: target)
try replConfig.addCollection(sourceDB.defaultCollection())
replConfig.replicatorType = .push
replConfig.continuous     = false

let replicator = Replicator(config: replConfig)
replicator.start()

Troubleshooting

  • Connection refused: verify both devices are on the same network; check firewall/ATS settings.
  • TLS handshake failed: ensure the active peer has the correct pinned certificate.
  • 401 Unauthorized: check ListenerPasswordAuthenticator credentials match BasicAuthenticator.
  • Enable .network and .replicator log domains at .debug level to diagnose issues (see mobile-logging-ios).