Obsidian-livesync Setup
Want to use Obsidian Live Sync without installing Deno? Learn how to set up CouchDB with Docker Compose and containerize the Deno configuration script for a clean, hassle-free sync server setup.
I have been a longtime Joplin user, since it provides it own official sync server, however I wanted to try out Obsidian, but setting up and figuring out a sync server was a journey of its own.
I finally settled on the https://github.com/vrtmrz/obsidian-livesync since it was relatively easy to setup, but one thing I did not want to install was yet another javascript compiler, deno hence I want to show you how I went about dockerizing the setup scriptt
Setup
First we have setup and configure couchdb, for this I used docker compose and followed the official docs.
Couchdb
services:
couchdb:
image: couchdb:3.5.2
user: 5984:5984
environment:
- COUCHDB_USER=user #Please change as you like.
- COUCHDB_PASSWORD=user #Please change as you like.
volumes:
- ./couchdb-data:/opt/couchdb/data
- ./couchdb-etc:/opt/couchdb/etc/local.d
ports:
- 5984:5984
restart: always5984:5984 for the two directories:sudo chown -R 5984:5984 /opt/docker/obsidian/Couchdbcouchdb configuration script
Once this is up and running we can run the configuration script. Since I did not want to export the variable we can prepend the bash script with the necessary variable
curl -s https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/main/utils/couchdb/couchdb-init.sh | hostname=localhost:5984 username=user password=user bashDockerizing the deno script
Since I did not want to install another javascript compiler, I figured to dockerize the client setup so it easy to run anywhere.
Dockerfile
ARG DENO_VERSION=2.9.3
FROM denoland/deno:alpine-${DENO_VERSION}
ARG LIVESYNC_REF=main
ENV SETUP_SCRIPT_URL="https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/${LIVESYNC_REF}/utils/flyio/generate_setupuri.ts"
USER root
WORKDIR /app
# Download and cache the upstream TypeScript script and its pinned npm dependency
# during the image build. The container can then run with --cached-only.
RUN deno cache "${SETUP_SCRIPT_URL}" \
&& chmod -R a+rX /deno-dir
COPY --chown=deno:deno generate-setup-uri.sh /app/generate-setup-uri.sh
RUN chmod 0755 /app/generate-setup-uri.sh
USER deno
ENTRYPOINT ["/app/generate-setup-uri.sh"]generate-setup-uri.sh
#!/bin/sh
set -eu
error() {
printf 'ERROR: %s\n' "$*" >&2
exit 1
}
for variable in \
LIVESYNC_HOSTNAME \
LIVESYNC_DATABASE \
LIVESYNC_E2EE_PASSPHRASE \
COUCHDB_USER \
COUCHDB_PASSWORD
do
eval "value=\${${variable}:-}"
[ -n "$value" ] || error "$variable is missing or empty"
done
case "$LIVESYNC_HOSTNAME" in
http://*|https://*) ;;
*) error "LIVESYNC_HOSTNAME must begin with http:// or https://" ;;
esac
# CouchDB database names must start with a lowercase letter. Keeping this
# validation here also prevents the LiveSync 'No capitals allowed in URL' error.
printf '%s' "$LIVESYNC_DATABASE" | grep -Eq '^[a-z][a-z0-9_$()+/-]*$' \
|| error "LIVESYNC_DATABASE must start with a lowercase letter and contain only lowercase letters, digits, _, $, (, ), +, -, or /"
# Map the Docker-friendly variable names to the lowercase names expected by
# the original LiveSync Deno script.
export hostname="${LIVESYNC_HOSTNAME%/}"
export database="$LIVESYNC_DATABASE"
export passphrase="$LIVESYNC_E2EE_PASSPHRASE"
export username="$COUCHDB_USER"
export password="$COUCHDB_PASSWORD"
# Important: an empty uri_passphrase must be UNSET. Passing an empty variable
# would make the upstream script use an empty Setup-URI passphrase rather than
# generate a friendly random one.
if [ -n "${LIVESYNC_URI_PASSPHRASE:-}" ]; then
export uri_passphrase="$LIVESYNC_URI_PASSPHRASE"
else
unset uri_passphrase 2>/dev/null || true
fi
exec deno run \
--cached-only \
--allow-env=hostname,username,password,database,passphrase,uri_passphrase \
"$SETUP_SCRIPT_URL".env
# Public CouchDB endpoint, normally your HTTPS reverse-proxy URL.
LIVESYNC_HOSTNAME=https://couchdb.internal.example.com
# Must be lowercase. Example: obsidiannotes
LIVESYNC_DATABASE=obsidiannotes
# Vault end-to-end encryption passphrase.
# Single quotes keep $, #, spaces, and other special characters literal.
LIVESYNC_E2EE_PASSPHRASE='replace-with-a-long-unique-e2ee-passphrase'
# CouchDB credentials.
COUCHDB_USER='user'
COUCHDB_PASSWORD='user'
# Optional and DIFFERENT from LIVESYNC_E2EE_PASSPHRASE.
# Leave commented or empty to let the upstream script generate one.
# LIVESYNC_URI_PASSPHRASE='replace-with-a-separate-setup-uri-passphrase'You can then build this image docker build -t client-setup . and then run it docker run --rm -it --env-file .env client-setup