---
title: "Deploy Obsidian LiveSync CouchDB | (Just Updated) Admin Password Survives Every Redeploy"
category: "Storage"
url: https://railway.com/deploy/obsidian-livesync-couchdb-v3521-or-admin
---

# Deploy Obsidian LiveSync CouchDB | (Just Updated) Admin Password Survives Every Redeploy

**[Deploy Obsidian LiveSync CouchDB | (Just Updated) Admin Password Survives Every Redeploy on Railway](https://railway.com/template/obsidian-livesync-couchdb-v3521-or-admin)**

- **Creator:** SuperSlowSloth
- **Category:** Storage

## Template content

### couchdb

- **Image:** ghcr.io/bon5co/obsidian-livesync-railway:latest
- **Health check:** /_up
- **Public domain:** Yes

## Documentation

# Deploy and Host Obsidian LiveSync CouchDB on Railway

A CouchDB 3.5.2.1 sync server for the [Obsidian Self-hosted LiveSync](https://github.com/vrtmrz/obsidian-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`](https://github.com/vrtmrz/obsidian-livesync/blob/main/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

1. Copy `COUCHDB_PASSWORD` from the service's **Variables** tab (username is `admin`).
2. In Obsidian, install the **Self-hosted LiveSync** community plugin.
3. Point it at your Railway HTTPS domain, database `obsidiannotes`, with those credentials.
4. 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](https://github.com/vrtmrz/obsidian-livesync)
- [Upstream server setup documentation](https://github.com/vrtmrz/obsidian-livesync/blob/main/docs/setup_own_server.md)
- [Apache CouchDB documentation](https://docs.couchdb.org/)
- [Wrapper image source](https://github.com/bon5co/obsidian-livesync-railway)
- [Railway volumes documentation](https://docs.railway.com/volumes)

### 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.


## Similar templates

- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.
- [Redis](https://railway.com/deploy/redis-1) — Self Host Latest Redis with Railway
- [EasyImg](https://railway.com/deploy/easyimg) — Simple self-hostable Nuxt.js personal image hosting system.

Open this page in a browser: https://railway.com/deploy/obsidian-livesync-couchdb-v3521-or-admin
