
Deploy Obsidian LiveSync CouchDB v3.5.2.1 | Admin Password Survives Every Redeploy
Obsidian sync on CouchDB — provisioned at boot, password survives redeploys
Just deployed
/opt/couchdb/data
Deploy and Host Obsidian LiveSync CouchDB on Railway
A CouchDB 3.5.2.1 sync server for the Obsidian Self-hosted LiveSync plugin — real-time, end-to-end-encrypted sync of your vault across desktop and mobile, on infrastructure you own, instead of a subscription.
It deploys already provisioned. The admin password is generated once by Railway and stays the same for the life of the deployment, the CouchDB settings the plugin requires are already applied, and the databases already exist. There is no setup script to run and nothing to create by hand before the plugin will connect.
About Hosting
Self-hosting Obsidian sync is really two jobs: run CouchDB, and configure it exactly the way LiveSync needs. The second job is where it goes wrong, and it is the part this template does for you.
The settings are upstream's, not hand-picked. The plugin's own documentation
(docs/setup_own_server.md) makes provisioning a required step — install Deno, then run
couchdb-init.sh against your server. Everything that script applies, from
utils/couchdb/provision.ts,
is baked into this image: single-node mode, require_valid_user on [chttpd] and
[chttpd_auth], the WWW-Authenticate challenge, CORS enabled with the
app://obsidian.md and capacitor://localhost origins and credentials = true, a 4 GB
max_http_request_size and a 50 MB max_document_size. You do not run the script — the
deploy comes up already in that state.
The databases are created on first boot. A single node needs _users, _replicator and
_global_changes, and LiveSync needs a vault database. All four exist when the deploy
finishes:
["_global_changes","_replicator","_users","obsidiannotes"]
Point the plugin at obsidiannotes and it connects. There is no step where you open Fauxton
and create a database before anything works.
Your admin password survives redeploys. This is the part worth reading carefully if you
are comparing templates. A CouchDB container keeps its [admins] section in
/opt/couchdb/etc/local.d/, which lives in the image — not in /opt/couchdb/data, which is
the mounted volume. So anything that generates a password at first boot and assumes the
volume remembers it is wrong, and the mistake only shows up on the second deploy. Railway
redeploys whenever you change a variable, update the image, or restart the service.
This template never generates a password in the container. COUCHDB_PASSWORD is a Railway
${{secret(32)}}: generated once when you deploy, stored as a project variable you can read
in the dashboard at any time, and applied identically on every boot afterwards. Verified by
redeploying against a populated volume — the same password still authenticates, the vault
data is still there, and nothing else does.
Mobile works because Railway terminates TLS. Obsidian on iOS and Android requires a valid
certificate, which normally means a reverse proxy, a tunnel, or Let's Encrypt by hand. Your
Railway domain is HTTPS already, and capacitor://localhost — the mobile app's CORS origin —
is in the allowed list.
Cost. One always-on service plus a volume; CouchDB is light, and Railway bills by usage. Both CouchDB and the LiveSync plugin are free and open source.
Why Deploy Obsidian LiveSync CouchDB on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
For this service specifically, Railway supplies the two things self-hosted Obsidian sync otherwise makes you build: a valid HTTPS certificate on a public domain, which is what mobile Obsidian demands, and a persistent volume for the vault. What this template adds on top is the CouchDB configuration and provisioning, so the plugin connects on the first attempt, and credentials that behave predictably across the redeploys a hosting platform performs routinely.
Common Use Cases
- Sync a vault across desktop, laptop and phone in real time, with proper conflict resolution rather than the file-level conflicts iCloud and Dropbox produce on Obsidian's many small writes
- Replace an Obsidian Sync subscription with infrastructure you control, keeping end-to-end encryption
- Keep notes on your own server for work with confidentiality requirements, where a vendor-hosted sync service is not an option
- Sync large vaults with attachments, using the raised request and document size limits LiveSync expects
Configuration
| Variable | Notes |
|---|---|
COUCHDB_PASSWORD | Pre-filled with ${{secret(32)}}. The admin password — readable in the Railway variables panel, stable across every redeploy. |
COUCHDB_SECRET | Pre-filled with ${{secret(32)}}. Session-cookie secret, so _session cookies stay valid across a redeploy. |
Nothing else is asked of you. The admin username (admin), the database name
(obsidiannotes) and the whole LiveSync configuration are baked into the image rather than
published as deploy-form fields, so there are no blank required boxes to fill in and no
settings to look up.
Volume mount path is /opt/couchdb/data, mounted for you.
After deploying
- Copy
COUCHDB_PASSWORDfrom the service's Variables tab (username isadmin). - In Obsidian, install the Self-hosted LiveSync community plugin.
- Point it at your Railway HTTPS domain, database
obsidiannotes, with those credentials. - Set a vault encryption passphrase in the plugin, then use its Copy setup URI to configure your phone and other devices.
Dependencies for Obsidian LiveSync CouchDB Hosting
- A Railway account
- A persistent volume for the vault data (included in this template)
- The Self-hosted LiveSync community plugin installed in Obsidian (free)
- A public HTTPS domain, which Railway provides automatically
Deployment Dependencies
- Obsidian Self-hosted LiveSync plugin
- Upstream server setup documentation
- Apache CouchDB documentation
- Wrapper image source
- Railway volumes documentation
Implementation Details
The image is couchdb:3.5.2.1 plus a Railway entrypoint. CouchDB has no $PORT support, so
the entrypoint writes Railway's injected port into [chttpd] before the server starts, then
hands off to the stock CouchDB entrypoint — which repairs ownership of the mounted volume as
root and drops to the couchdb user — and provisions the databases once the server answers.
require_valid_user is enabled as upstream's provisioner specifies, together with
require_valid_user_except_for_up. That second setting matters on Railway: the platform's
healthcheck is an unauthenticated GET /_up, and require_valid_user on its own answers
that with 401 and fails the deploy. With the exemption, /_up returns 200 while every
other path still requires authentication.
System databases are created with three idempotent PUT requests rather than
POST /_cluster_setup, because that call also rewrites bind_address and port in the live
configuration and would move the listener off Railway's port during boot.
Frequently Asked Questions
Do I have to run couchdb-init.sh? No. Everything it applies is already in the image, and
the databases it would create are created at boot.
Where do I find my password? The service's Variables tab, COUCHDB_PASSWORD. It is
not printed to the deploy log, and it does not change when you redeploy.
Will a redeploy break my sync or lose my notes? No. Vault data is on the volume, and the admin credentials come from the Railway variable on every boot rather than being regenerated inside the container.
Does mobile Obsidian work? Yes. Mobile requires HTTPS, which your Railway domain provides,
and the capacitor://localhost CORS origin it connects from is allowed.
Can I change the database name or admin username? They are baked to keep the deploy form
empty, but you can add LIVESYNC_DATABASE or COUCHDB_USER as service variables to override
them, or create additional databases through Fauxton at /_utils.
Is my vault encrypted? Set a passphrase in the LiveSync plugin and it encrypts end-to-end, so the server stores ciphertext. CouchDB itself is reachable only with the admin credentials.
How do I add my other devices? Use the plugin's Copy setup URI, which packages the connection settings into a single link you open on the other device.
Template Content