k1tbyte40 downloadsSync your vault end-to-end encrypted through your own S3, WebDAV or Google Drive storage, with conflict resolution, file history, shared folders and live editing.

Features · Quick start · Privacy · Relay
MDSync syncs your vault through an S3 bucket, a WebDAV server or Google Drive. There is no MDSync server: your devices talk straight to your storage, and everything they upload is encrypted on the device with a key derived from your passphrase. Sync is manual until you turn on automatic sync, so you can review each change before it leaves the device. An optional relay, a Cloudflare Worker you deploy to your own account, adds instant sync, live editing, shared folders and share links.
Sync
syncignore.md, patterns per device, symlinks and a size limit.History
Real time (needs the relay)
Setup and upkeep
RESET to confirm).Give each vault its own bucket prefix. MDSync refuses a prefix that already holds another vault.
Set up the first device alone and let its first sync finish. That sync creates the vault's key. On storage without conditional writes (Google Drive, some WebDAV and S3-compatible servers), two devices starting at the same moment can each create one, and files encrypted by one become unreadable to the other.
Cloudflare R2 by hand. Its free tier (10 GB, 1 million write and list requests and 10 million read requests a month) covers most vaults, downloads cost nothing, and it supports the conditional writes MDSync relies on. Enable R2 on your Cloudflare account, create a bucket, and create an API token with Object Read & Write limited to that bucket. R2 shows the access key ID and secret only once. In MDSync pick S3-compatible and set Endpoint to https://<ACCOUNT_ID>.r2.cloudflarestorage.com (https://<ACCOUNT_ID>.eu.r2.cloudflarestorage.com for a bucket created in the EU jurisdiction), leave Region as auto, and fill in the bucket and the token's keys. The same Cloudflare account can host the relay.
| Backend | Fields | Notes |
|---|---|---|
| S3-compatible | Endpoint, region, bucket, prefix, access key, optional path-style URLs | Required to own a shared folder. |
| WebDAV | Base URL, path, username, password | |
| Google Drive | Folder name, auth server URL | Needs your own relay for the sign-in. Best effort: Drive has no conditional writes, so two devices writing the same new object at once can leave two files with one name. |
The panel has four tabs: Changes, History, Timeline and Deleted.
Changes lists local changes, remote changes and conflicts, with a path filter. Open any file for a side-by-side diff (combined on narrow screens or on request). In a text file you can revert a single local change or accept a single remote one, then apply your choices. Binary files show the size change instead, with Show differences anyway where the file can be read as text.

In Settings → MDSync → Sync you can turn on:
A conflict is a file changed both here and on the remote. For each one you can Keep local, Accept remote, Keep both versions (the remote copy lands next to yours as todo (conflict from Phone 2026-07-05).md) or Merge….
Merge… opens a three-way editor: your version, the result and the remote version side by side. Changes that do not overlap are merged up front, and you review and save. Autosync merges such conflicts on its own and leaves the rest to you.

The gutter marks lines added, changed or removed since the last sync. Click a mark to see the old text and revert that change.

Both sources use gitignore syntax:
syncignore.md in the vault root syncs like a normal note, so every device follows it. A shared folder has its own in its root.drafts/
*.tmp
README.md
Ignoring never deletes anything: a matching file stops syncing, and copies on the remote and other devices stay. To remove a file everywhere, delete it first and then ignore it.
Ignore symlinks (on by default) skips symbolic links and Windows junctions, which Obsidian shows as ordinary folders. Max file size skips anything larger.
Under Obsidian configuration scope you choose what else to sync: core settings, hotkeys, the list of enabled plugins, plugins with their settings, CSS snippets and themes. Every category is off by default and chosen per device. Turning one off deletes nothing. Clear on remote removes a category from the remote without touching local files. MDSync's own plugin folder never syncs.
Every push records what it changed. Versions to keep sets how many pushes history holds; pinned versions are kept until you unpin them.
The History tab lists the open file's past versions. Click one to diff it against the current file, or use its menu to restore it, compare it with the version before, or pin it under a name. A restore always shows the diff first.

The Timeline tab lists every push to the vault with the files it changed. From any of them you can see its changes or put the whole vault back to that point.

The Deleted tab (or MDSync: Restore deleted files) lists files gone from the vault that history still holds: when each went, which device removed it, and how many more pushes the record survives. Restore puts a file back where it was, Restore to… somewhere else. Pin a version to keep a deleted file for good.

These features run through the relay. Turn them on with Real-time sync and Live editing. If the relay is down, devices fall back to periodic sync.
A note open on two devices edits together, keystroke by keystroke, with the other person's cursor. It works between your own devices and with the people in a shared folder. Excalidraw drawings sync the same way (Excalidraw plugin 2.x).
Two people in one note: typing at once, cursors with names, text tinted by author, then one push and one pull.

Excalidraw: two people draw on one canvas, each seeing the other's pointer and shapes.

The note header shows who else has the note open, as coloured initials. Click one to follow that person: your tab opens the notes they open and keeps their cursor in view. The file explorer shows headcounts on shared folders and a dot on files others changed that you have not opened yet. On desktop, the status bar shows the relay state.
Turn off Show my open note to others to stay online without showing where you are.
Who is where: people in the explorer and the note header, and a dot on what someone else changed.

Following: one person follows another from note to note, their view going where the other types.

Share a folder from its menu in the file explorer. Owning a share needs S3-compatible storage.
obsidian://mdsync-share link and a password. Send them separately.A read-only invite pulls changes but can never push. From the share's window you can see who is in it, revoke a person, pause the share on this device or on all your devices, and stop sharing. When a share ends, its files stay and sync with your vault again. Renaming a shared folder renames it on your other devices too.
Invite: share a folder from the explorer, send the link and password, the guest joins it.

Read-only invite: the lock, the owner's edits arriving live, a note deleted elsewhere, revoking access.

Publish one note as a link anyone can open in a browser with nothing installed, from its menu in the file explorer (MDSync: Share link) or with Share this note as a link.

A link is a copy: later edits do not reach it until you update it. Anyone who has the link (and the passphrase) can read the note and pass it on.
Settings → MDSync → Connection → Export setup creates an encrypted link and QR code with your main sync settings, storage credentials included. It leaves out the cached passphrase and display preferences. The link is encrypted with your passphrase, so the new device needs the same passphrase and confirms the import before anything is applied.

MDSync has no telemetry. It connects only to:
api.cloudflare.com), only when the setup wizard deploys the relay or creates R2 storage for you. The token you paste can edit Workers, KV and R2 on that account. If the account has no workers.dev address yet, the wizard registers a random one.raw.githubusercontent.com), only when you open Show me how in the setup wizard, to play a short clip of creating the Cloudflare token.You need an account with your storage provider. The relay needs a Cloudflare account, and Google Drive needs your own Google Cloud OAuth client.
Storage credentials, share keys, share links, the relay secret and the Cloudflare token are stored in the plugin's data.json on each device, encrypted with a key kept in Obsidian's keychain for that vault, outside the vault folder. A copy of the vault (a backup, git, a cloud folder) carries none of them; on a copied or moved vault, import a setup link from another device. Diagnostics logs stay on the device and never sync.
The Cloudflare token. The wizard keeps it on the device where you paste it, to update the relay later, and never syncs or exports it. The R2 storage the wizard creates uses S3 keys derived from this token, so they can read and write every R2 bucket on the account, including buckets MDSync did not create. Deleting the token in Cloudflare stops sync. For keys limited to one bucket, set up R2 by hand as the manual setup under Quick start describes.
What the relay sees. It never sees file contents, file names or keys: live edits and presence travel encrypted under each space's key. It does see a hash of your storage identity, a device id per connection, and when each sync and note switch happens. For a shared folder with participants, it keeps your S3 access key in its storage to sign requests for them, plus the names you invited people by. With Google Drive, it exchanges your sign-in for tokens and sees your Drive refresh token.
Share links. Creating one sends a rendered copy of that note to your relay, encrypted on your device. The relay stores the ciphertext, a fingerprint of the passphrase check, the view limit and the expiry, and counts views. It never sees the key (it stays in the part of the link after #, which browsers never send), the passphrase, or the text. The page a recipient opens is served by your relay and decrypts in their browser. Your other devices get the links, with their keys, through your storage, encrypted with the vault key.
<prefix>/manifest.json.enc encrypted file list
<prefix>/history.json.enc encrypted change log, one entry per push
<prefix>/salt.bin
<prefix>/keys.json vault key wrapped by your passphrase
<prefix>/objects/<sha256>.enc encrypted file contents
<prefix>/pins/<id>.json.enc full file list of a pinned version
<prefix>/spaces/<id>.json.enc shared folder records
<prefix>/links/<id>.json.enc share links, with their keys
<prefix>/shares/<id>/... each shared folder's own storage
The relay is packages/relay: one Cloudflare Worker that handles instant sync, live editing, invites to shared folders, share links and the Google Drive sign-in. It fits in the Workers free tier.
From MDSync (recommended). Select Deploy relay in Settings → MDSync → Connection → Relay server, or Deploy to my Cloudflare in the setup wizard, and paste a Cloudflare API token. MDSync uploads the relay and connects to it. When a new MDSync version brings a newer relay, the same button reads Update relay.
From GitHub Actions.
CLOUDFLARE_API_TOKEN (the Edit Cloudflare Workers template is enough), CLOUDFLARE_ACCOUNT_ID and RELAY_SECRET.https://<your-relay>/auth, and enable the Google Drive API.GDRIVE_CLIENT_ID and GDRIVE_CLIENT_SECRET as secrets: on a relay deployed from MDSync, in the Cloudflare dashboard under the worker's Settings → Variables and Secrets (updates from MDSync keep them); on a fork, to its repository secrets, then run Deploy Relay again.While the OAuth consent screen is in testing mode, Google expires refresh tokens after 7 days. Publish it to stay signed in.
pnpm install
pnpm dev # watch build
pnpm build
pnpm lint
pnpm typecheck
pnpm test
The plugin lives in packages/plugin, the relay in packages/relay, the page share links open in packages/viewer (built into the relay's static assets), and the format both share in packages/protocol.