Running a Couchbase Edge Server

Shipped

View as Markdown

This is the concrete server-side companion to Sync. It gives you a working Couchbase Edge Server you can run in Docker and point the app at. For what actually replicates, how secrets are kept out of the sync stream, and the in-app connection form, read the Sync page — this page is just the server.

Remember the version rule from that page: Bring Your LM is Couchbase Lite 3.x, and Couchbase Edge Server is a 3.x-protocol product. Pin the image to a 1.x release, as below — there is no Edge Server for the newer Couchbase Lite 4.x line yet.

Build the image

Couchbase publishes Edge Server as a Debian package; this Dockerfile installs it onto a slim base and runs it against a mounted config file.

FROM debian:bookworm-slim

ARG CBES_VERSION=1.0.1
ARG CBES_DEB_URL=https://packages.couchbase.com/releases/couchbase-edge-server/${CBES_VERSION}/couchbase-edge-server_${CBES_VERSION}_amd64.deb

RUN apt-get update \
    && apt-get install -y --no-install-recommends curl ca-certificates \
    && curl -fsSL -o /tmp/cbes.deb "${CBES_DEB_URL}" \
    && apt-get install -y --no-install-recommends /tmp/cbes.deb \
    && rm -f /tmp/cbes.deb \
    && apt-get purge -y curl \
    && apt-get autoremove -y \
    && rm -rf /var/lib/apt/lists/*

USER couchbase
WORKDIR /opt/couchbase-edge-server/etc
EXPOSE 59840

CMD ["/opt/couchbase-edge-server/bin/couchbase-edge-server", "config.json"]

Build it:

docker build -t couchbase-edge-server:1.0.1 .

The config file

Save this next to the Dockerfile as config.json. It defines one database, byllm, syncing bidirectionally, and lists every collection the app replicates. The list must cover them all — a collection the app pushes but the server doesn't serve will 404. Don't add the server's own _default._default; the app deliberately doesn't sync it.

{
  "interface": "0.0.0.0:59840",
  "users": "/opt/couchbase-edge-server/etc/users.json",
  "enable_anonymous_users": false,
  "logging": { "console": true },
  "databases": {
    "byllm": {
      "path": "/opt/couchbase-edge-server/var/databases/byllm.cblite2",
      "create": true,
      "enable_client_writes": true,
      "enable_client_sync": "bidirectional",
      "collections": [
        "_default.memories",
        "_default.tools",
        "_default.api_providers",
        "_default.bots",
        "_default.conversations",
        "_default.conversation_messages",
        "_default.image_blobs",
        "_default.image_blob_chunks",
        "_default.settings",
        "_default.workspaces",
        "_default.jobs",
        "_default.devices",
        "_default.key_offers",
        "_default.embedded_model_bundles",
        "_default.elicitations"
      ]
    }
  }
}

The users file

Save this as users.json. Each user needs a bcrypt password hash and the replicate role. The username and password here are what you type into the app's sync settings.

{
  "alice": {
    "password": "$2a$12$REPLACE_WITH_A_BCRYPT_HASH",
    "roles": ["replicate"]
  }
}

Generate the hash with Apache's htpasswd (from apache2-utils) and drop the user: prefix it prints, leaving just the $2a$... / $2y$... string:

htpasswd -nbBC 12 alice 'your-strong-password'

If you'd rather run an open server on a trusted network, set "enable_anonymous_users": true in config.json, drop the "users" line and the users.json mount, and turn Anonymous access on in the app instead. Prefer real users for anything reachable beyond your own machine.

Run it

Mount the two config files read-only and keep the database on a named volume so it survives restarts:

docker run -d \
  --name couchbase-edge-server \
  --restart unless-stopped \
  -p 59840:59840 \
  -v "$PWD/config.json:/opt/couchbase-edge-server/etc/config.json:ro" \
  -v "$PWD/users.json:/opt/couchbase-edge-server/etc/users.json:ro" \
  -v cbes-data:/opt/couchbase-edge-server/var/databases \
  couchbase-edge-server:1.0.1

Or, with a docker-compose.yml:

services:
  couchbase-edge-server:
    build: .
    image: couchbase-edge-server:1.0.1
    container_name: couchbase-edge-server
    ports:
      - "0.0.0.0:59840:59840"
    volumes:
      - cbes-data:/opt/couchbase-edge-server/var/databases
      - ./config.json:/opt/couchbase-edge-server/etc/config.json:ro
      - ./users.json:/opt/couchbase-edge-server/etc/users.json:ro
    restart: unless-stopped

volumes:
  cbes-data:

Point the app at it

In the app, open Settings, then Sync, enable it, and set the endpoint to your host, port 59840, and the database name byllm:

ws://<host>:59840/byllm

Fill in the username and password from users.json. On a plain LAN ws:// is fine; over the internet, terminate TLS at a reverse proxy and use wss:// — the endpoint carries all your synced data.

wss://cbe.example.com/byllm

Behind a reverse proxy

For remote access, put the container behind a proxy that terminates HTTPS on a hostname and forwards to 59840. With Traefik, labels on the container do it:

labels:
  traefik.enable: "true"
  traefik.http.routers.cbe.rule: "Host(`cbe.example.com`)"
  traefik.http.routers.cbe.entrypoints: "websecure"
  traefik.http.services.cbe.loadbalancer.server.port: "59840"

The app then connects with wss://cbe.example.com/byllm.

Keep the collection list current

When a future version of the app adds a new collection, this server's collections list has to grow to match, or that new data silently won't sync. The list above is the complete set the current app replicates.