S
Store

Self-Hosting the Sync Server

Deploy a Store sync server with Docker, configure TLS, and connect devices.

Overview

The Store sync server is an optional component that acts as a relay for device-to-device replication. Devices push and pull changes through the server instead of connecting directly. Self-hosting gives you full control over where sync data is stored.

Docker deployment

The sync server is distributed as a Docker image:

docker run -d \
  --name store-sync \
  -p 8787:8787 \
  -v store-data:/data \
  -e STORE_ADAPTER=sqlite \
  -e STORE_PATH=/data/sync.db \
  -e STORE_AUTH_SECRET=your-secret-here \
  ghcr.io/cuitty/store-sync:latest

For production deployments, use Docker Compose:

# docker-compose.yml
services:
  store-sync:
    image: ghcr.io/cuitty/store-sync:latest
    ports:
      - "8787:8787"
    volumes:
      - store-data:/data
    environment:
      STORE_ADAPTER: postgres
      DATABASE_URL: postgresql://store:pass@db:5432/store
      STORE_AUTH_SECRET: ${STORE_AUTH_SECRET}
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    volumes:
      - pg-data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: store
      POSTGRES_USER: store
      POSTGRES_PASSWORD: ${DB_PASSWORD}

volumes:
  store-data:
  pg-data:

TLS configuration

In production, always terminate TLS. The sync server does not handle TLS directly. Place it behind a reverse proxy like Caddy, nginx, or Cloudflare Tunnel.

# Caddyfile
sync.example.com {
    reverse_proxy store-sync:8787
}

Clients connect using the HTTPS URL:

const remote = {
  id: "sync-bridge",
  adapter: "cuitty.storage.bridge",
  endpoint: "https://sync.example.com",
  authRef: "secret://store/device-token",
};

Authentication

The sync server validates device tokens on every request. Generate tokens using the CLI:

cui store server token create --device "alice-laptop"
cui store server token create --device "alice-phone"
cui store server token list
cui store server token revoke <token-id>

Resource requirements

  • CPU: 1 vCPU handles approximately 1,000 sync operations per second.
  • Memory: 256 MB minimum, 512 MB recommended.
  • Disk: depends on data volume. The SQLite backend works well for small deployments (under 10 GB). For larger volumes, use the Postgres backend.

Health check

The server exposes a health endpoint at /health:

curl https://sync.example.com/health
# {"status":"ok","version":"0.1.0","uptime":86400}