Cloud Sync¶
Pairs two Glassy instances. Cloud Sync keeps a self-hosted appliance and another Glassy instance — the hosted cloud for its owner, or a private VPS in a Zero Reliance Pair — in step. Rows travel both ways, media is pulled from the origin, and health stays visible in the panel.
Cloud Sync is the bridge between Glassy instances you control. The sending appliance and the receiving peer exchange supported rows using a per-peer sync token. Media routes check ownership on the serving peer. The local missing-media scan is instance-wide, so health counters must not be interpreted as a per-account inventory on a multi-user server.
What syncs¶
| Type | Notes |
|---|---|
| Notes | Includes images metadata (images_json); the image files transfer separately (see Media below) |
| Documents, Folders | Full row sync |
| Bookmarks, collections, highlights | Full row sync |
| Voice recordings | Metadata + transcript sync as rows; the audio file transfers separately |
| Conversations (threads + messages) | Full row sync |
| Pinned tags | Full row sync |
| Custom backgrounds | Rows sync (beta.40+); the three image renditions transfer as media |
What never syncs, by design: derived data (embeddings, full-text indexes — each side rebuilds them locally), ephemeral data (presence, typing, AI usage), secrets (BYOK API keys stay on the instance that holds them), and profile media (avatars/banners are account-level, not synced rows).
Pairing¶
The sender runs the sync cycles. In a Zero Reliance Pair that is the home appliance; in an appliance-to-cloud setup it is also the appliance.
- On the receiving instance, open Settings → Cloud Sync and generate that instance's sync token. Cloud and self-hosted instances both expose the control; the self-hosted receiver exists specifically for this.
- On the sending appliance, open Settings → Cloud Sync, paste the token into Pair token, enter the receiver in Syncs to, and choose Save Cloud Sync settings. No restart is needed.
- The scheduler resolves both values every cycle. Its fast check runs every ~10 seconds while changes are pending; the full cycle runs every ~5 minutes. Cycles are single-flight — manual Sync now joins a running cycle instead of racing it.
For a scripted/bootstrap install, GLASSY_SYNC_TOKEN remains the recovery path
and is read at boot. A token saved in Settings wins from its next cycle.
Direction is configured on the sender. Each side honors its own persisted type toggles and conflict policy when it applies what arrives — a type disabled on the receiving side is skipped on arrival. Conflict resolution is last-write-wins per row by default, and deletes travel as tombstones.
Media transfer (beta.40+)¶
Rows are small; files are not — so media moves on its own schedule:
- Voice audio streams from the origin when a recording's metadata arrives without its file.
- Note images and custom-background renditions are downloaded individually for references already present in local rows. Missing files are retried on later eligible pull cycles. The server exposes a size/SHA-256 manifest, but the current downloader does not consume it or verify checksums.
- This is appliance-side download, not general two-way file replication. Back up appliance-origin media separately.
- Mixed-version pairings are safe: an older origin simply answers 404 and the appliance retries next cycle.
Reading the health panel¶
Settings → Cloud Sync shows the truth, not a guess:
- Pending changes — your outbox, by type. Dead-lettered changes (repeated delivery failures) are held for inspection and recoverable: fix the cause, then Retry now re-arms them.
- Media missing (amber) — voice and note-image references missing on this instance. Persistent counts can indicate connectivity, permission, version, or file-availability problems; they do not prove permanent loss. Background renditions are not included in this counter.
- Per-type status — partial failures surface per type, never hidden behind an aggregate green.
Recovery¶
- Reset a type: re-snapshots one content type (full export, no cursor) — the fix for a stuck or partial type.
- Retry dead-letter: re-arms delivery for rows that exhausted retries.
- Conflicts: LWW keeps the newest write; both sides converge on the next cycle.
Troubleshooting¶
| Symptom | Cause / fix |
|---|---|
| Panel shows no peer | No credential resolves, or INSTANCE_ID is not self_hosted — automated scheduling only starts on appliances |
| Amber media warning that never drains | Check peer connectivity, credentials, version, disk space, and source-file availability. The count alone does not prove data loss. Restore or re-upload a file if available; do not delete notes merely to hide the warning |
| Changes pending forever | Check the per-type status for a dead-letter entry; fix the cause and Retry now |
| 401s from the origin | Token revoked or rotated — regenerate on the receiving instance and save the new Pair token on the sender |