Bidirectional Obsidian vault sync to Synology Drive
Project description
obsidian-sync
obsidian-sync keeps a local Obsidian vault synchronized with a Synology Drive folder in near real-time.
Primary use case:
- macOS local vault -> Synology Drive folder:
/Users/den/Library/CloudStorage/SynologyDrive-M/obsidian-sync - Windows Obsidian opens the same Synology folder (for example
C:\Users\<user>\SynologyDrive\obsidian-sync)
Features
- Bidirectional sync (
source_vault <-> synology_vault) - Real-time watch mode + periodic reconciliation
- Single-instance lock (prevents concurrent sync writers)
- First-run safe behavior with backups before overwrite/delete
- Conflict policies (
latest,source,target,manual) + conflict history/restore commands - Snapshot history and deleted-file recovery commands
- Activity log of sync operations (copy/delete/conflict/restore/error)
- Batch conflict resolver (
resolve-conflicts) - Device-state excludes by default (
workspace.json, caches, plugin temp files) - Fine-grained vault settings sync toggles (
.obsidiansettings categories) - Selective attachment-type sync toggles (images/audio/videos/PDF/other)
- Rules engine (folder glob, extension, markdown tag, per-device profile)
- Rename/move mirroring across sides
- Delta patch sync for large files (partial block updates)
- Optional encrypted cloud vault mode (
vault_encryption_enabled) - Optional encryption for backups/snapshots/conflict copies (passphrase via env var or CLI flag)
- Health command, integrity audit, optional webhook alerts
- Multi-vault watcher orchestration (
watch-all) - SQLite state tracking for deterministic updates/deletes
- Windows-safe filename collision detection (case-only conflicts)
Install (macOS)
cd /Users/den/Desktop/obsidian-sync
python3 -m venv .venv
source .venv/bin/activate
pip install .
Install from PyPI (after you publish):
pip install obsidian-synology-sync
Install with encryption support:
pip install 'obsidian-synology-sync[crypto]'
Quick Setup (New Users)
Note: scripts/macos/setup_new_user.sh and scripts/windows/setup_new_user.ps1 are repository files. If you installed only via pip, clone this repository to use these setup helpers.
Passphrase (required for encrypted mode)
The passphrase is user-defined. It is not auto-generated by obsidian-sync or Synology.
All devices must use the exact same value.
Recommended for manual runs:
obsidian-sync --config /path/to/obsidian-sync.toml watch --passphrase 'your-strong-passphrase'
obsidian-sync --config /path/to/obsidian-sync.toml watch --passphrase-file ~/.obsidian-sync-passphrase
--passphrase-file reads UTF-8 text and ignores one trailing newline.
Set manually on Windows:
setx OBSIDIAN_SYNC_PASSPHRASE "your-strong-passphrase"
Set manually on macOS:
export OBSIDIAN_SYNC_PASSPHRASE='your-strong-passphrase'
Read current value:
[Environment]::GetEnvironmentVariable("OBSIDIAN_SYNC_PASSPHRASE","User")
echo "$OBSIDIAN_SYNC_PASSPHRASE"
macOS user setup (encrypted cloud vault + auto-start)
cd /Users/den/Desktop/obsidian-sync
pip install 'obsidian-synology-sync[crypto]==0.2.3'
scripts/macos/setup_new_user.sh \
--source "/ABSOLUTE/PATH/TO/YOUR/LOCAL/OBSIDIAN-VAULT" \
--target "/Users/den/Library/CloudStorage/SynologyDrive-M/obsidian-sync" \
--config "/Users/den/Desktop/obsidian-sync/obsidian-sync.toml" \
--passphrase "your-strong-passphrase"
What this does:
- creates config if missing
- enables encrypted cloud-vault mode
- installs/restarts launchd auto-start job
- runs one immediate sync
Windows user setup (encrypted cloud vault + auto-start)
cd C:\path\to\obsidian-sync
pip install "obsidian-synology-sync[crypto]==0.2.3"
powershell -ExecutionPolicy Bypass -File .\scripts\windows\setup_new_user.ps1 `
-SourceVault "C:\Users\<user>\ObsidianLocalVault" `
-SynologyVault "C:\Users\<user>\SynologyDrive\obsidian-sync" `
-ConfigPath "C:\Users\<user>\obsidian-sync.toml" `
-Passphrase "your-strong-passphrase"
What this does:
- creates config if missing
- enables encrypted cloud-vault mode
- sets passphrase env var and creates a logon scheduled task
- starts watcher immediately
Initialize
obsidian-sync init \
--source "/ABSOLUTE/PATH/TO/YOUR/OBSIDIAN-VAULT" \
--target "/Users/den/Library/CloudStorage/SynologyDrive-M/obsidian-sync" \
--windows-path "C:\\Users\\<user>\\SynologyDrive\\obsidian-sync"
This creates:
- Config:
obsidian-sync.toml - State DB:
.obsidian-sync-state/state.db
Run
One-time sync:
obsidian-sync sync-now
One-time sync with encrypted mode passphrase flag:
obsidian-sync sync-now --passphrase 'your-strong-passphrase'
Preview only:
obsidian-sync sync-now --dry-run
Continuous sync:
obsidian-sync watch
Continuous sync with passphrase file:
obsidian-sync watch --passphrase-file ~/.obsidian-sync-passphrase
Continuous sync for multiple vault configs:
obsidian-sync watch-all --configs /path/a.toml /path/b.toml
Status:
obsidian-sync status
List conflict history:
obsidian-sync conflicts
Restore a conflict copy:
obsidian-sync restore-conflict <ID>
obsidian-sync restore-conflict <ID> --side source
Batch resolve open conflicts:
obsidian-sync resolve-conflicts --policy latest
obsidian-sync resolve-conflicts --policy source
List snapshots:
obsidian-sync snapshots
obsidian-sync snapshots --path "Projects/plan.md"
List deleted-file recoveries:
obsidian-sync deleted-files
Restore a snapshot/deleted record:
obsidian-sync restore-snapshot <SNAPSHOT_ID>
obsidian-sync restore-snapshot <SNAPSHOT_ID> --side target
Show activity log:
obsidian-sync activity --limit 100
obsidian-sync activity --path "Projects/plan.md"
Health + integrity audit:
obsidian-sync health
obsidian-sync audit
obsidian-sync audit --repair
How Windows sync works
Recommended setup:
- Use Synology Drive client on Windows.
- Keep
obsidian-sync watchrunning on both devices. - Open Obsidian on each device at its local
source_vault.
Mode behavior:
- Plain mode (
vault_encryption_enabled = false): you can open the Synology local folder directly as a vault. - Encrypted cloud-vault mode (
vault_encryption_enabled = true): do not open Synology folder directly. Open localsource_vaultand letobsidian-syncdecrypt/encrypt between local vault and Synology.
Backup and conflict behavior
- Before overwrite/delete, existing files are backed up under:
<synology_vault>/.obsidian-sync-backups/
- If both sides changed before sync:
- A
.conflict-...copy is created for the losing side. - Newer file (mtime) wins for the main path.
- Conflict entries are stored and can be listed with
obsidian-sync conflicts. - Restores are supported with
obsidian-sync restore-conflict.
- A
Device-state excludes (default)
By default, device-specific noise is excluded from sync:
.obsidian/workspace.json.obsidian/workspaces.json.obsidian/cache/**.obsidian/plugins/*/cache/**.obsidian/plugins/*/tmp/**
You can disable this in obsidian-sync.toml by setting:
[sync]
exclude_device_state = false
Fine-Grained Sync Controls
obsidian-sync.toml supports the following feature toggles:
[sync]
# Vault configuration
sync_main_settings = true
sync_appearance_settings = true
sync_themes_and_snippets = true
sync_enabled_plugins = true
sync_hotkeys = true
# File type selection
sync_images = true
sync_audio = true
sync_videos = true
sync_pdfs = true
sync_other_types = true
# Conflict + performance
conflict_policy = "latest" # latest|source|target|manual
delta_sync_enabled = true
delta_min_file_size_bytes = 8388608
delta_chunk_size_bytes = 1048576
delta_max_diff_ratio = 0.5
vault_encryption_enabled = false
encryption_enabled = false
encryption_passphrase_env = "OBSIDIAN_SYNC_PASSPHRASE"
encryption_kdf_iterations = 600000
# Integrity + alerts
integrity_audit_interval_seconds = 3600.0
integrity_auto_repair = false
alerts_webhook_url = ""
alerts_on_conflict = true
alerts_on_error = true
health_stale_after_seconds = 300.0
Example: disable videos and PDFs:
[sync]
sync_videos = false
sync_pdfs = false
Enable encrypted backups/snapshots/conflict copies:
[sync]
encryption_enabled = true
encryption_passphrase_env = "OBSIDIAN_SYNC_PASSPHRASE"
Then export the passphrase before running sync:
export OBSIDIAN_SYNC_PASSPHRASE='your-strong-passphrase'
obsidian-sync watch
Or pass it directly for that run:
obsidian-sync watch --passphrase 'your-strong-passphrase'
obsidian-sync watch --passphrase-file ~/.obsidian-sync-passphrase
Main vault files remain plain for Obsidian compatibility; encrypted mode applies to recovery artifacts stored under .obsidian-sync-backups.
Encrypted Cloud Vault Mode
If you want Synology Drive files encrypted at rest (instead of plain .md), enable:
[sync]
vault_encryption_enabled = true
encryption_passphrase_env = "OBSIDIAN_SYNC_PASSPHRASE"
Behavior:
- Local
source_vaultstays plaintext (Obsidian opens this directly). - Synology
synology_vaultstores encrypted files as*.osync.enc. - Run
obsidian-syncon every device (macOS/Windows) with the same passphrase (env var or CLI flag) so each device can decrypt to its local vault.
Recovery and Activity
snapshotsincludes version-like copies captured during sync and backup events.deleted-filesshows deleted note/attachment recoveries.restore-snapshotrestores any snapshot or deleted entry to source/target.activityshows a durable log of sync operations and restore actions.
Rules Engine
Use [sync] and profile blocks to control selection by path/extension/tag:
[sync]
device_profile = "windows"
rules_include_globs = ["Projects/**", "Inbox/**"]
rules_exclude_globs = ["Archive/**"]
rules_include_extensions = [".md", ".canvas", ".pdf"]
rules_exclude_extensions = [".tmp"]
rules_include_tags = ["work"]
rules_exclude_tags = ["private"]
[profiles.windows]
rules_exclude_globs = [".obsidian/plugins/heavy-plugin/**"]
Rules are merged from [sync] + [profiles.<device_profile>].
Scope Note
This project implements local/Synology-based equivalents of Obsidian Sync workflow features. Hosted service features from Obsidian's cloud product are out of scope here:
- Obsidian account authentication and hosted relay infrastructure
- Shared vault invite/permission management UI
- Cloud-managed end-to-end key exchange and recovery UX
Auto-start on login
macOS (launchd):
scripts/macos/setup_new_user.sh \
--source "/ABSOLUTE/PATH/TO/YOUR/LOCAL/OBSIDIAN-VAULT" \
--target "/Users/den/Library/CloudStorage/SynologyDrive-M/obsidian-sync" \
--config "/Users/den/Desktop/obsidian-sync/obsidian-sync.toml" \
--passphrase "your-strong-passphrase"
Windows (Task Scheduler):
powershell -ExecutionPolicy Bypass -File .\scripts\windows\setup_new_user.ps1 `
-SourceVault "C:\Users\<user>\ObsidianLocalVault" `
-SynologyVault "C:\Users\<user>\SynologyDrive\obsidian-sync" `
-ConfigPath "C:\Users\<user>\obsidian-sync.toml" `
-Passphrase "your-strong-passphrase"
Build and publish (pip distributable)
Build and validate distributions:
cd /Users/den/Desktop/obsidian-sync
scripts/release/build_dist.sh
Upload:
# TestPyPI first
scripts/release/publish.sh testpypi
# Production PyPI
scripts/release/publish.sh pypi
twine uses TWINE_USERNAME and TWINE_PASSWORD (or keyring) for authentication.
Notes
- Avoid storing two files that differ only by case (for Windows compatibility).
- Keep file names and paths stable between macOS and Windows.
- For very large vaults, first sync may take time.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file obsidian_synology_sync-0.2.3.tar.gz.
File metadata
- Download URL: obsidian_synology_sync-0.2.3.tar.gz
- Upload date:
- Size: 37.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d15dd6a940c2f2c1e0096cd41efa11d06691a4ef1546e9453e472e46e2bd1c93
|
|
| MD5 |
61752c7f49848b845e3b105097488990
|
|
| BLAKE2b-256 |
2fd8ef7fa8a55592248d22da9157c24c98cb24b045ec8b78a668bdf251a9987c
|
File details
Details for the file obsidian_synology_sync-0.2.3-py3-none-any.whl.
File metadata
- Download URL: obsidian_synology_sync-0.2.3-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5178713fb1c2f6ab984c458ee587d0ab29b34f7f621506e9017ee5649a1f5307
|
|
| MD5 |
ab74f387fc2551547d35faa1d8a785a1
|
|
| BLAKE2b-256 |
657de8acdd2ba84e1ce4544df98e646eda51021e7e04e69965c83da6e8a4ecb0
|