Build your own Obsidian Sync

Build your own Obsidian Sync as versioned vault files and conflict copies. End-to-end encryption and automatic merge remain the other product.

  • teardown
  • vibe-coding
  • scope

You can build your own Obsidian Sync. Start with versioned vault files and conflict copies. The catalog calls Obsidian Sync that loop.

You pay $5–$10 a month. The verdict is “Hard, but it’s yours”.

Last time I wrote about how to host a SaaS clone on Cloudflare. That was a regular backlog post. This one is a teardown.

Build your own Obsidian Sync as files

The Obsidian Sync page splits the work into three rows.

The first row is 2 days. Versioned file storage, restore, basic sync. That is a vault, a device, a file path, and a history you can roll back. You can vibe-code this.

The second row is 1 week. End-to-end encryption, conflict copies, selective sync. Still your notes. A passphrase the server never sees, a second file when two devices edit offline, a folder you leave on the laptop.

The third row is 1 month and up. Automatic merge, vault sharing, mobile edge cases. Skip that row.

If you tell an agent to “clone Obsidian Sync”, it aims at the third row. The useful v1 is the first one.

Here is the shape of the data.

const vault = {
  id: 'vault-pressroom',
  name: 'Pressroom',
}

const device = {
  id: 'laptop-studio',
  vaultId: 'vault-pressroom',
  name: 'Studio laptop',
}

const file = {
  id: 'file-on-call-1',
  vaultId: 'vault-pressroom',
  path: 'handbook/on-call.md',
  version: 14,
  contentHash: '9f3c1a88',
  updatedAt: '2026-10-25T17:12:00.000Z',
}

A file with a path, a version number, and a hash. Restore is the previous blob.

The audience line on the page is one Obsidian user syncing a private vault between a laptop, desktop, and phone.

The same v1 also replaces iCloud or a private git remote if what you wanted was “the note I typed on the phone is on the laptop”. Notion is the workspace cousin at $12–$24 a person a month. I wrote about how Notion works on October 17. Day One is the dated journal at $4.17–$6.25. Roam Research is the daily-notes graph at $13.75–$15.

Obsidian the editor is free and local. Sync is the paid add-on. Their pricing page starts Sync at $4 a month billed annually. The March 2024 plan note also lists $5 a month billed monthly for Standard. The catalog’s $5–$10 band sits on that monthly Standard next to Plus.

How does Obsidian Sync work

Obsidian publishes the security model and enough of the wire format that you can decrypt a message yourself. I am summarizing those pages and the verification post, not reconstructing today’s cluster.

The security page splits a vault into two copies. The local vault stays plaintext on disk. The remote vault is encrypted. When you create that remote vault you pick end-to-end encryption (the default) or standard encryption. End-to-end means the password stays on your devices. Obsidian says they cannot read the notes. Lose the password and they cannot recover the remote vault either. Standard encryption keeps a key on their servers, the same class of setup they compare to Dropbox or iCloud without Advanced Data Protection.

The algorithms are public. Key derivation is scrypt with a per-vault salt. The cipher is AES-256 in Galois/Counter Mode. Their verification guide walks the rest. You type a vault password, or you let their managed server generate one. That password is not your account password. The app derives a 32-byte base key with scrypt (N = 32768, r = 8, p = 1). Encryption version 3 then runs HKDF-SHA256 with the info string ObsidianAesGcm. Older vaults use the scrypt output directly. The blob on the wire is a 12-byte IV, ciphertext, and a 16-byte GCM tag.

The same guide opens DevTools, finds the WebSocket to sync-xx.obsidian.md, copies a binary message as Base64, and decrypts it with your password and salt. If the plaintext comes back, the server never needed the key. Treat “every 2026 vault is encryption version 3” as an educated guess. The post was updated on 5 September 2025 to support both 0 and 3.

The host is also public. Sync runs on DigitalOcean in Singapore, Frankfurt, San Francisco, and Sydney, or an automatic pick from your IP at first setup. Debug info prints Host server: wss://sync-xx.obsidian.md. Their FAQ says files sync only while Obsidian is running. A closed phone app does not catch the laptop edit.

A v1 does not need their WebSocket protocol. Put ciphertext in R2. Put the version index in D1. That is the stack on the card. Use TanStack Start if React is your weekday language.

EDIT THE LOCAL FILE Plaintext markdown on disk ENCRYPT ON THE DEVICE scrypt, then AES-256-GCM STORE A VERSION Ciphertext blob plus index PULL ON THE OTHER DEVICE Download while the app is open DECRYPT AND WRITE Same key, local folder Server never sees the note
The public path: edit locally, encrypt on the device, store a version, decrypt on the next machine.

How Obsidian Sync handles conflicts

Their troubleshooting page defines a conflict the way you expect. You edit handbook/on-call.md on the laptop. Before that upload finishes, you also edit it on the phone. Offline time makes this more likely, because more edits pile up between syncs.

What happens next depends on the file type. Markdown uses Google’s diff-match-patch. Other files, including canvases, use last-modified-wins. Settings JSON merges local keys on top of remote keys.

Since Obsidian 1.9.7 you can pick the markdown behavior per device. Automatically merge is the default. It keeps every edit and can leave duplicate sentences you clean up by hand. The other option writes a separate conflict file, which is the v1 on the card. Automatic merge is the third estimate row.

Version history sits next to the conflict. The plans page keeps note history for 1 month on Standard and 12 months on Plus. The FAQ says older attachment versions last two weeks. History counts toward the storage cap, 1 GB on Standard and 10 GB to 100 GB on Plus. Standard is one remote vault and a 5 MB file. Plus is 10 vaults and a 200 MB file.

A v1 restore is “give me version 13 of handbook/on-call.md”. Store each upload as its own object. Do not overwrite the previous blob.

const version = {
  fileId: 'file-on-call-1',
  version: 14,
  deviceId: 'laptop-studio',
  objectKey: 'vault-pressroom/file-on-call-1/14',
  createdAt: '2026-10-25T17:12:00.000Z',
}

const conflict = {
  fileId: 'file-on-call-1',
  path: 'handbook/on-call (conflict 2026-10-25).md',
  fromDeviceId: 'phone-pixel',
  sourceVersion: 13,
  createdAt: '2026-10-25T17:14:00.000Z',
}

When the laptop is at version 14 and the phone uploads a descendant of version 13, write the phone body to the conflict path and leave the laptop file alone. The status view lists conflicted. The card’s non-goal already names automatic merging.

Selective sync is the other 1-week piece. The FAQ says notes, images, and the configuration folder sync by default. PDFs, audio, and video are opt-in. A v1 can skip a folder by path prefix.

End-to-end encryption and vault sharing

The catalog guardrail is the hard half: encrypt content and filenames on the client with a key the server never sees, and say that losing the passphrase loses the vault. WebCrypto can do the AES-GCM half in a Worker or in the desktop app.

export async function encryptNote(plainText, rawKey) {
  const iv = crypto.getRandomValues(new Uint8Array(12))
  const encoded = new TextEncoder().encode(plainText)
  const cipher = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    rawKey,
    encoded
  )
  return { iv, cipher }
}

Derive rawKey from the passphrase with a slow KDF before you call this. scrypt in the browser is awkward. Argon2 or PBKDF2 with a high iteration count is the usual Worker-side stand-in. Skip the “we can reset your password” screen, because that screen means you kept the key.

Obsidian’s security page is honest about what they do not encrypt. File hashes are deterministic, so the same plaintext under the same key and salt makes the same remote hash. That saves bandwidth when a file repeats in history. It also lets an attacker who already controls the server, and who can force you to upload a chosen file, test whether you already stored that file. Path-to-content mapping, which device uploaded, and when, stay readable so the server can route versions. A compromised server could swap one encrypted body under another encrypted path. The bytes stay ciphertext. A v1 that stores path in D1 next to the R2 key has the same leak, so encrypt the path if you promise E2E.

Sharing is the other skip. Their teams page lets you share a vault with up to 20 people. Every collaborator needs their own Sync subscription. A shared E2E vault still needs the encryption password on first join. There is no on-premises Sync server. They point that request at a forum thread. A multi-user live editor is Notion again.

Mobile edge cases are why the third row exists. The FAQ warns that OneDrive or Dropbox “online-only” files look deleted to Sync, and Sync then deletes them from the remote vault. Your v1 hits the same bug if a client reports a missing file as a delete.

2-DAY V1 Versioned files in object storage Restore any previous blob Basic sync between two devices SKIP THIS HALF Automatic merge of markdown Vault sharing and live collab Mobile deletes and edge cases
Ship versions and a restore. Leave merge, sharing, and mobile deletes on the skip row.

An Obsidian Sync alternative for one vault

I would rebuild Sync for the folder I already keep in markdown, where the current “sync” is a USB stick or a git push I forget to run. One vault row, two devices, R2 objects keyed by vaultId/fileId/version, and a D1 index that knows the latest version per path.

Conflict copies come after the first week of two-device use. Encryption comes when I stop trusting the bucket. I would not build a web editor or a shared vault invite.

Host it next to the product, on Workers, R2, and D1, because that is the stack on the card. Put the passphrase in the desktop app, not in an environment variable on the Worker. Use TanStack Start if React is your weekday language.

If the rent is a team wiki with pages and search, that is Notion, 10 hours for nested markdown. If the rent is a private journal with dates, that is Day One, 12 hours for local entries. If the rent is daily notes with backlinks, start on the Roam Research card after the files survive a weekend on two machines.

Start with the first row

Go to Build your own Obsidian Sync. Copy the Astro prompt, or TanStack Start if that is what you write.

Tell the agent the first estimate only: versioned file storage, restore, basic sync. Two days.

If the company already lives in shared vaults, automatic merge, and a phone that edits on the train, keep paying.