Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

OSS Sync and Share

HikariTishHikariTish91 downloads

Self-hosted sync and share for Obsidian: Markdown + attachments + .obsidian config, LWW-based multi-device sync, lightweight blog publishing, and collaboration editing.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates16

Self-hosted Obsidian sync & share — Markdown, attachments and collaboration in one binary.

English | 中文

Overview

OSS Sync is a self-hosted alternative to Obsidian Sync. It consists of a Go (Gin) backend and a TypeScript Obsidian plugin. Data stays on your own server: files, versions, shares and collaboration are all managed by you.

  • Vault-based: one account can own multiple Vaults.
  • Device-aware: each Obsidian client has a stable client_id with pending / approved / revoked states.
  • Offline-first: local edits are queued, merged with three-way merge, and synced with revision-based CAS.
  • Durable queue: pending ordinary Vault uploads are written to .oss-sync-state.json before transfer and resume after Obsidian restarts.

Features

  • Markdown, attachments and optional .obsidian config sync
  • Create / modify / delete / rename with full and incremental manifest checks
  • Revision-based conflict detection with “keep local / keep remote / keep both / ordered merge”
  • Recycle bin with restore / permanent delete / retention
  • File history: gzip snapshot, line diff, restore to any version
  • Sharing: single file or folder, public URL, allow-copy toggle, GFM + wikilinks
  • Blog: two built-in themes (default, papertrail), public index /, per-vault /b/:vaultId
  • Collaboration on Markdown: invite / accept / revoke, real-time via SSE (fallback to long polling)
  • Vault-scoped sync strategy: user_choice / short_poll / long_poll
  • Console themes and blog themes as ZIP uploads
  • Device onboarding starts with a device name; approval and per-Vault authorization are separate, and the authorized Vault list refreshes automatically in plugin settings
  • WordPress-style server extensions: WASM compatibility plus administrator-trusted executable plugins with dynamic hooks, routes, middleware, admin pages, tasks, migrations, dependencies, and host RPC
  • Public Go SDK: github.com/helantianshen/oss-sync/pkg/ossplugin for building trusted extensions without hand-written JSON Lines
  • SQLite by default, PostgreSQL optional; periodic storage reconciliation

Architecture

cmd/server        # HTTP entry
configs/          # dev / prod YAML
internal/
  auth            # register, login, JWT, device auth
  syncapi         # Vault revision, upload/download, rename/delete
  vaults          # Vault CRUD, members, settings
  devices         # device state, vault authorization, cursor
  collaboration   # invite, accept, content write, events
  history/recycle # snapshots, restore, retention
  blog            # themes, public pages
  serverplugin    # WASM and trusted executable plugins with namespaced routes
  webui           # console pages, admin
plugin/src        # Obsidian plugin

Sync uses only HTTP. Short polling wait=0 or long polling wait=30 per Vault. Collaboration uses an account-level channel: SSE over HTTPS (or app://obsidian.md with CORS), long polling over plain LAN HTTP.

Quick Start

Prerequisites

  • Go 1.25+
  • Node 20+, npm
  • Obsidian 1.4+

Run backend

go run ./cmd/server

First registered user automatically becomes admin. Afterwards use that admin account to create others.

Listens on http://localhost:8080 by default, data in data/. Health:

curl http://localhost:8080/healthz
curl http://localhost:8080/readyz

Config via OSS_ENV=dev|prod → configs/config.dev.yaml / configs/config.prod.yaml, overridable by env: OSS_SERVER_HOST, OSS_SERVER_PORT, OSS_DB_DRIVER, OSS_DB_DSN, OSS_STORAGE_DIR, etc.

Postgres example:

export OSS_DB_DRIVER=postgres
export OSS_DB_DSN='postgres://user:[email protected]:5432/oss?sslmode=disable'
go run ./cmd/server

Docker

One-command install or upgrade on a Linux server:

curl -fsSL https://raw.githubusercontent.com/helantianshen/oss-sync/main/install.sh | sudo bash

The official bootstrap script asks for the host port, GitHub Release source, deployment path, and a total project storage limit. The source can be the accelerated URL, GitHub official, or a custom HTTPS URL prefix. It downloads both the latest amd64/arm64 container archive and its checksums.txt through the selected source, verifies SHA-256, and imports it with docker load. It detects Docker and offers to install it with Docker's official installer. Leave the port blank to choose one randomly from 10000-25565 while skipping common service ports. New installations keep persistent data under /opt/oss-sync/data; the application-wide storage limit rejects further sync writes when reached, and 0 means unlimited.

After installation, run the global oss or oss-sync command to update or uninstall OSS Sync, inspect runtime and storage usage, start, stop or restart it, and change the project capacity or mapped port. Each update asks which source to use, so the accelerated URL can be changed without reinstalling. Uninstalling removes the container and commands while retaining project data by default.

Running the same install command again downloads the latest Release and recreates the container while reusing its port, deployment path, and capacity setting. Legacy oss-data volumes remain in place and are not migrated automatically. Non-interactive installs can set OSS_PORT, OSS_RELEASE_PROXY=official (or a custom HTTPS URL prefix), OSS_INSTALL_DIR, OSS_STORAGE_LIMIT_GB, and OSS_INSTALL_DOCKER=1. For the global manager, set OSS_RELEASE_SOURCE=official, OSS_RELEASE_SOURCE=proxy, or OSS_RELEASE_PROXY=https://example.com/ to select the source for an update. OSS_IMAGE remains an advanced override for a complete registry image such as ghcr.io/helantianshen/oss-sync-server:<version>.

The default SQLite installation does not pull PostgreSQL. If Docker Hub dependencies are added manually, a complete 1Panel mirror reference such as docker.1panel.live/library/postgres:17 can be used without changing the Release download source or the Docker daemon configuration.

Source development can still build through Docker Compose:

Build and start a complete SQLite-backed environment with Docker Compose:

docker compose up -d --build
docker compose logs -f backend

The service is available at http://localhost:8080, and persistent data is stored in the oss-data named volume. Set OSS_PORT=9090 to change the host port and OSS_STORAGE_MAX_TOTAL_SIZE_MB to apply an application-wide data-directory limit.

To build and run only the backend image:

docker build -t oss-sync-backend .
docker run --rm -p 8080:8080 \
  -v oss-data:/app/data \
  oss-sync-backend

Container deployments can update in place from Admin → System → Server update. The image keeps the server binary in a writable runtime directory; after a verified replacement, the process exits and Docker's restart policy starts the new binary. Rebuilding or replacing the image remains the way to apply image-level changes. Removing the container keeps the named volume; docker compose down -v deletes its data and must be used with care.

Build plugin

Regular users can install OSS Sync and Share directly from Obsidian Community Plugins. The following steps are only for source development:

cd plugin
npm ci
npm run build
# outputs plugin/manifest.json, main.js, styles.css
# copy to vault: <vault>/.obsidian/plugins/oss-sync/

Reload Obsidian → Enable Obsidian Sync & Share → Set the device name → Enter a server URL including http:// or https:// → Sign in. Approve the device separately in the web console, then grant Vault access. The open settings page refreshes the authorized Vault list every three seconds. The plugin keeps a local .oss-sync-state.json (v3) at Vault root; it is never uploaded and stores the durable pending-operation queue.

Plugins, blog templates, and console themes

The extension model has one simple rule:

  • Plugins own functionality: settings, routes, hooks, data, admin pages, tasks, and integrations.
  • Blog templates own public-page structure and style: template.html, style.css, optional theme.js, and theme.json capabilities.
  • Console themes own console appearance: theme.css, images, and fonts.

Templates and themes must not contain functional settings. Do not add settings.json to a blog template. Declare settings in a plugin; OSS Sync renders them in the top-level Plugin settings menu and stores values per Vault.

Fastest plugin workflow

  1. Copy examples/server-plugin-echo.
  2. Change the plugin ID and handlers.
  3. Build the executable and ZIP it with manifest.json.
  4. Upload it from Admin settings → Plugins.
cd examples/server-plugin-echo
go build -o plugin.exe .
Compress-Archive manifest.json,plugin.exe my-plugin.zip

Use the public Go SDK at github.com/helantianshen/oss-sync/pkg/ossplugin; it handles the JSON-lines process protocol. The short in-console guide covers settings, hooks, routes, pages, tasks, migrations, and host services. The complete reference is docs/server-plugins.md.

Executable plugins run on the server, so their binary must match the server platform. This does not require separate plugin records: one ZIP may contain plugin.exe, plugin, and plugin-arm64, with windows-amd64, linux-amd64, and linux-arm64 entries in manifest.json. OSS Sync automatically selects the matching entry. For the simplest setup, build only the platform used by your server.

Fastest template or theme workflow

Blog template:

my-template.zip
├── template.html
├── style.css
├── theme.js
├── theme.json
└── plugin.zip   # optional functionality

Console theme:

my-console-theme.zip
├── theme.css
├── images/
├── fonts/
└── plugin.zip   # optional functionality

To associate functionality, place the already-built plugin ZIP at the package root as plugin.zip. Uploading the template or theme automatically installs, enables, and associates the plugin. No additional association form is required. The web console includes concise Template guide, Console theme guide, and Plugin guide pages with copyable minimal examples.

Configuration

Env Description
OSS_ENV dev or prod
OSS_SERVER_HOST / PORT listen address
OSS_DB_DRIVER / DSN sqlite or postgres
OSS_STORAGE_DIR file storage root
OSS_ALLOW_ANONYMOUS_REGISTRATION initial register switch
OSS_WEB_SESSION_TTL_HOURS web console session lifetime in hours; default 24
OSS_DEVICE_JWT_TTL_HOURS plugin device token lifetime in hours; default 720 (30 days)
OSS_DEVICE_STALE_DAYS stale device threshold
OSS_RECONCILE_INTERVAL_HOURS storage check interval
OSS_UPDATE_DOWNLOAD_SOURCE server update source: official, proxy, or custom
OSS_UPDATE_DOWNLOAD_PROXY HTTPS URL prefix used when the source is custom

Vault settings (per Vault, admin can force):

  • sync_mode: user_choice | short_poll | long_poll
  • recycle bin days, storage quota, upload size

Server updates use download_source and download_proxy from the update section in configs/config.dev.yaml or configs/config.prod.yaml. The Admin → System → Server update panel can override them for the current check and update. The selected source is used for both release metadata and the binary download, which allows updates when the server cannot reach GitHub directly.

Development

# backend
go test ./...
go test -race ./...
go vet ./...

# plugin
cd plugin
npm exec tsc -- --noEmit
npm test
npm run build

Project conventions: Go with gofumpt + golangci-lint, TypeScript strict, uv/pnpm not required, no emoji in UI, CSS via console.css tokens, no inline styles.

Deployment

  • Put a reverse proxy with HTTPS in front of the Go binary.
  • Back up data/ (SQLite file or Postgres dump) and the JWT secret stored in DB.
  • After initial users are created, turn off open registration in Admin → System.
  • Monitor /readyz; alert on non-200 or repeated reconcile failures.

Security

  • Passwords are bcrypt-hashed, never logged.
  • JWT is HS256 with per-deployment random secret.
  • Sessions: web uses 24-hour HttpOnly Secure SameSite cookies + CSRF; plugin uses a 30-day device-bound Bearer JWT. Expired plugin tokens are removed locally and require a new login.
  • All mutating web requests require CSRF; all sync/collab requests require approved device + vault authorization.
  • Server plugins accept WASM packages or administrator-trusted executable packages. WASM modules receive no WASI, filesystem, network, database, or environment access and use the legacy ABI. Executable packages declare platform entrypoints and communicate over a persistent bidirectional JSON-lines protocol; they can register arbitrary hooks, routes, middleware, admin pages, tasks, migrations, and dependencies, call host data/services through RPC, and inherit the server account's filesystem, network, database, environment, and command-execution permissions. The executable host model is intentionally comparable to WordPress plugin freedom.
  • Enabled plugins may declare host-rendered settings; OSS Sync adds them to the top-level Plugin settings menu and stores values per Vault without allowing plugin HTML or JavaScript injection. Theme-linked settings such as Papertrail remain available outside the current Vault page and automatically select an accessible matching Vault.
  • ABI v1 exposes blog/HTML content filters, theme render filters, administrator pages, and Obsidian editor commands. Comment filtering is reserved until the server has a comment entity and renderer; arbitrary JavaScript injection remains outside the host API.

License

MIT — see LICENSE.

HealthExcellent
ReviewRisks
About
Host a self‑managed Obsidian sync server to sync Markdown, attachments and optional .obsidian config across multiple vaults and devices while keeping files and versions on your server. Manage revisions with three‑way merges and revision-based CAS, use a recycle bin and file history, share files/folders via public URLs, publish blogs, and collaborate in real time via invites and SSE.
SyncingCollaborationPublishing
Details
Current version
0.1.10
Last updated
Yesterday
Created
2 months ago
Updates
16 releases
Downloads
91
Compatible with
Obsidian 1.4.0+
Platforms
Desktop, Mobile
License
MIT
Report bugRequest featureReport plugin
Author
HikariTishHikariTishhelantianshen
GitHubhelantianshen
  1. Community
  2. Plugins
  3. Syncing
  4. OSS Sync and Share

Related plugins

Relay

Collaborate in real time with live cursors. Share folders. Manage access to updates.

Self-hosted LiveSync

Sync vaults securely to self-hosted servers or WEBRTC.

Fast Note Sync

Real-time sync of your vaults across server, mobile, and web; shareable with anyone; supports REST and MCP integrations to build your personal AI knowledge base.

Share Note

Instantly share/publish a note, with the full theme and content exactly like you see in Obsidian. Data is shared encrypted by default, and only you and the person you send it to have the key.

Google Drive Sync

Syncs a vault into Google Drive for cross-platform use (works for iOS).

YAOS

Simple real-time sync powered by your own Cloudflare Worker.

Sync Engine

The extensible vault synchronization engine: Fast · Free · Reliable. Supports WebDAV, S3, and Google Drive.

Nutstore Sync

Sync your vault with Nutstore (坚果云) using WebDAV protocol.

OneDrive Sync

Sync your Obsidian vault with OneDrive Personal/Consumer

Wechat Converter

将 Markdown 转换为微信公众号排版,并支持一键发送到微信公众号(支持自定义 CSS和公众号贴图)、飞书、小红书、知乎、微博、CSDN等20+平台。