Self-hosted livesync

JunMyung Lee·2024년 2월 14일
0

옵시디언

목록 보기
1/2

fly.io를 통해서 서버를 구성 및 배포를 하고, CouchDB(카우치 DB)로 문서를 관리 하여 실시간으로 동기화를 진행한다. 자세한 설명은 다음 문서를 참고한다.

Obsidian Self-hosted LiveSync Plugin 사용을 위한 가이드 입니다. (github.com)

deploy_couchdb_to_flyio.ipynb - Colaboratory (google.com)

리소스 비용

모든 플랜에 무료로 포함된 리소스:

  • 최대 3개의 shared-cpu-1x 256mb VM
  • 3GB 영구 볼륨 스토리지(총)
  • 160GB 아웃바운드 데이터 전송

기능

  • 문서의 동기화 충돌을 시각적으로 해결
  • 거의 실시간에 가까운 기기 간 양방향 동기화
  • 엔드 투 엔드 암호화가 지원
  • 플러그인 동기화

CouchDB 구성하기

예제에서는 구글 Colab을 사용하였지만 개발자 기준에서는 추후 관리나 편의성을 위해서는 로컬에서도 괜찮겠다 싶다.

fly 구성

fly.io 가입 및 카드 등록

https://fly.io/ 사이트를 통해 가입하고 해외 카드를 등록한다. ( 예제 사이트에 자세히 나와있다 )

flyctl 설치

curl -L https://fly.io/install.sh | sh

flyctl 설치 확인 및 alias 등록

https://mertyn-obsidian.fly.dev/

flyctl 등록

vi ~/.zshrc
alias flyctl="/Users/liam/.fly/bin/flyctl"

flyctl 계정 연결

flyctl auth signup

# Opening https://fly.io/app/auth/cli/00ae0884e7fd97f6a980f73d532eaff4

# Waiting for session... Done
# successfully logged in as ...

flyctl 서버 생성

flyctl launch --auto-confirm --detach --no-deploy --name mertyn-obsidian --image couchdb:latest --region nrt

# Using image couchdb:latest
# Creating app in /content/fly
# We're about to launch your app on Fly.io. Here's what you're getting: 
# Organization: 이준명 (fly launch defaults to the personal org) 
# Name: mertyn-obsidian (specified on the command line) 
# Region: Tokyo, Japan (specified on the command line) 
# App Machines: shared-cpu-1x, 1GB RAM (most apps need about 1GB of RAM) 
# Postgres: <none> (not requested) 
# Redis: <none> (not requested) 
# Created app 'mertyn-obsidian' in organization 'personal' 
# Admin URL: [https://fly.io/apps/mertyn-obsidian](https://fly.io/apps/mertyn-obsidian) 
# Hostname: mertyn-obsidian.fly.dev 
# Wrote config file fly.toml 
# Validating /content/fly/fly.toml 
# ✓ Configuration is valid 
# Your app is ready! Deploy with `flyctl deploy`

Colab 예제를 보면 서버 생성시 --generate-name 옵션을 사용한다. 자동으로 서버 이름을 생성하는데 진행시 Error: Validation failed: Name has already been taken가 발생한다. 이에 따라 직접 중복되지 않는 이름을 지정할 수 있도록 --name으로 사용하도록 변경하였다.

flyctl 볼륨 생성

flyctl volumes create --region nrt couchdata --size 2 --yes

# ID: vol_p4mo0qq333nqx6dv 
# Name: couchdata 
# App: mertyn-obsidian 
# Region: nrt 
# Zone: fe01 
# Size GB: 2 
# Encrypted: true 
# Created at: 14 Feb 24 00:20 UTC 
# Snapshot retention: 5

fly.toml 설정 변경

cat fly.toml

# app = 'mertyn-obsidian'
# primary_region = 'nrt'
# [build]
#   image = 'couchdb:latest'
# [http_service]
#   internal_port = 8080
#   force_https = true
#   auto_stop_machines = true
#   auto_start_machines = true
#   min_machines_running = 0
#   processes = ['app']
# [[vm]]
#   cpu_kind = 'shared'
#   cpus = 1
#   memory_mb = 1024
# Modify fly.toml 
cat ./fly.toml | grep -iv "\[env\]" | sed -e 's/8080/5984/g' | sed -e 's/_machines = true/_machines = false/g'> fly.tmp
cat fly.tmp > ./fly.toml
echo -e "\n[env]\n  COUCHDB_USER = \"${couchUser}\"\n[mounts]\n  source=\"couchdata\"\n  destination=\"/opt/couchdb/data\"" >> ./fly.toml

# app = 'mertyn-obsidian'
# primary_region = 'nrt'
# [build]
# image = 'couchdb:latest'
# [http_service]
# internal_port = 5984
# force_https = true
# auto_stop_machines = false
# auto_start_machines = false
# min_machines_running = 0
# processes = ['app']
# [[vm]]
# cpu_kind = 'shared'
# cpus = 1
# memory_mb = 1024
# [env]
# COUCHDB_USER = "..."
# [mounts]
# source="couchdata"
# destination="/opt/couchdb/data"

flyctl password 설정

flyctl secrets set COUCHDB_PASSWORD=${couchPwd}

# Secrets are staged for the first deployment

Deploy

flyctl deploy --detach --remote-only
flyctl status

# ==> Verifying app config
# Validating /content/fly/fly.toml
# ✓ Configuration is valid
# --> Verified app config
# ==> Building image
# Searching for image 'couchdb:latest' remotely...
# image found: img_589kp9e8el94oj2e
# Watch your deployment at https://fly.io/apps/mertyn-obsidian/monitoring
# Provisioning ips for mertyn-obsidian
# Dedicated ipv6: 2a09:8280:1::2a:a53d:0
# Shared ipv4: 66.241.125.8
# Add a dedicated ipv4 with: fly ips allocate-v4
# This deployment will:
# * create 1 "app" machine
# No machines in group app, launching a new machine
# Finished launching new machines
# -------
# Checking DNS configuration for mertyn-obsidian.fly.dev
# Visit your newly deployed app at https://mertyn-obsidian.fly.dev/
# App
# Name = mertyn-obsidian
# Owner = personal
# Hostname = mertyn-obsidian.fly.dev
# Image = library/couchdb:latest
# Machines
# PROCESS ID VERSION REGION STATE ROLE CHECKS LAST UPDATED
# app 6e82d339f521d8 1 nrt created 2024-02-14T00:23:53Z

CouchDB 설정 변경

curl -X POST "${couchHost}/_cluster_setup" -H "Content-Type: application/json" -d "{\"action\":\"enable_single_node\",\"username\":\"${couchUser}\",\"password\":\"${couchPwd}\",\"bind_address\":\"0.0.0.0\",\"port\":5984,\"singlenode\":true}" --user "${couchUser}:${couchPwd}"

# {"ok":true}

curl -X PUT "${couchHost}/_node/nonode@nohost/_config/chttpd/require_valid_user" -H "Content-Type: application/json" -d '"true"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/chttpd_auth/require_valid_user" -H "Content-Type: application/json" -d '"true"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/httpd/WWW-Authenticate" -H "Content-Type: application/json" -d '"Basic realm=\"couchdb\""' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/httpd/enable_cors" -H "Content-Type: application/json" -d '"true"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/chttpd/enable_cors" -H "Content-Type: application/json" -d '"true"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/chttpd/max_http_request_size" -H "Content-Type: application/json" -d '"4294967296"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/couchdb/max_document_size" -H "Content-Type: application/json" -d '"50000000"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/cors/credentials" -H "Content-Type: application/json" -d '"true"' --user "${couchUser}:${couchPwd}"
curl -X PUT "${couchHost}/_node/nonode@nohost/_config/cors/origins" -H "Content-Type: application/json" -d '"app://obsidian.md,capacitor://localhost,http://localhost"' --user "${couchUser}:${couchPwd}"

추가 커맨드

==Application list 확인==

flyctl app list

# NAME           	OWNER   	STATUS  	LATEST DEPLOY
# mertyn-obsidian	personal	deployed	5h34m ago

==Application 삭제==

flyctl apps destroy [name] -y

# Destroyed app [name]

접속 확인

생성된 URL을 통해 접속을 하면 UI가 보이지 않는다. 이때 다음의 주소로 접속하여 ID/PASS 를 입력한다.
https://mertyn-obsidian.fly.dev/_utils

==접속화면==

==업데이트된 데이터==


이후 스텝은 예제의 내용을 그대로 따라한다. 하단은 필요부분을 복사-붙여넣기 한 부분이다.

obsidian에서 self-hosted livesync 설치, 설정

self-hosted livesync 링크를 눌러 옵시디언에서 플러그인 설치화면으로 갑니다.

Install 버튼을 눌러 설치합니다.
image-20230318230303040

Enable 버튼을 눌러 플러그인을 활성화 합니다.
image-20230318230320100

Ctrl + P 를 눌러 설정에 들어간 후에, Self-hosted LiveSync 설정을 누릅니다. 상단에 🛰️ 탭을 누릅니다. 그리고 이전에 Colab을 통해 설치한 CouchDB의 접속 정보를 입력합니다.

  • URI: 구글 Colab에서 설치한 CouchDB의 접속 URL입니다. '/ 로 끝나지 않게 작성해주세요.
  • Username: CouchDB 사용자명
  • Password: CouchDB 비밀번호
    • 참고: 이 암호는 Obsidian의 vault에 일반 텍스트로 저장됩니다.
  • Database name: 동기화를 위한 DB명입니다. 다른 기기에서도 같은 DB명으로 입력해야 하기 때문에, 기억해주세요. 비어 있으면 안됩니다!
    image-20230318230329142

이제 플러그인에서 DB에 잘 접속되는지 확인을 해봐야 합니다. Check database configurationCheck을 눌러봅니다. 대부분은 Fix 버튼이 나오는 것을 확인할 수 있습니다. Fix 버튼을 모두 눌러줍니다.
image-20230318231141484

첫 동기화

!!! 주의 !!! 다음 동기화 이전에 vault를 꼭 백업해주세요.
이제 처음 동기화를 위해 Rebuild everythingRebuild 버튼을 누릅니다. 시간이 조금 걸릴 수 있습니다.
image-20230318231230935

동기화가 완료되었으면, 이제 라이브 싱크 설정을 합니다. 사실 라이브 싱크를 사용하지 않고 주기적으로 동기화를 하는 등의 옵션이 있습니다만, 이 플러그인을 사용하는 주 목적은 라이브 싱크입니다. 🔧 탭을 누르고 아래 설정을 해줍니다.
image-20230318231536828

한번 설정하면 Presets의 항목이 다시 비어버리는 경우가 있는데, 이건 버그인 것 같습니다.
확인을 위해서는 🔁 탭에 들어가신 후, LiveSync가 활성화 되어 있는지 확인합니다.
image-20230320113440877

다른 obsidian 기기에서의 self-hosted livesync 설정

이제 다른 기기에서 obsidian을 실행하고 self-hosted livesync를 설치해주세요. 그리고 위에서 설정했던 것 처럼, CouchDB 설정을 해줍니다. 여기서는 절대 Rebuild 같은 것을 하지 않을 겁니다. CouchDB 설정만 합니다. 마찬가지로 DB에 접속이 되는지 확인하기 위해 Check database configurationCheck을 눌러봅니다.
image-20230318231646814

📦 탭을 누르고 Fetch rebuilt DBFetch 버튼을 누릅니다. Fetch 하는데 시간이 조금 걸리지만, 바로 LiveSync 설정을 해봅니다.
image-20230318231758563

🔧 탭을 누르고 아래 설정을 해줍니다.
image-20230318232025383

이제 라이브 싱크가 제대로 되는지 확인해봅니다.
image-20230318232053492

플러그인의 상태 표시

위에서 Show status inside editor 를 활성화를 같이 했는데요. 이럴경우 에디터 우측 상단에 다음과 같은 상태를 확인할 수 있습니다.

  • 상태
    • ⏹️ 멈춤
    • 💤 라이브 동기화가 활성화되었습니다. 변경을 기다리는 중입니다.
    • ⚡️ 동기화 중입니다.
    • ⚠ 오류가 발생했습니다.
  • ↑ 업로드된 청크 및 메타데이터
  • ↓ 다운로드한 청크 및 메타데이터
  • ⏳ 보류 중인 프로세스 수
  • 🧩 청크를 기다리는 파일 수입니다. 파일을 삭제하거나 파일 이름을 변경한 경우에는 다음과 같이 기다리세요.⏳ 아이콘이 사라집니다.

처음에 밀린 동기화를 하게 되면 ⚡️ 상태입니다. 보통은 💤 상태에서 ⏳ 와 ↑, ↓ 이 발생합니다.

모바일 동기화가 안되는 경우

  • 모바일에서 종종 동기화가 안 되는 경우가 있습니다. 저는 이럴 경우 모바일 옵시디언을 종료하고 다시 실행합니다. 그러면 동기화가 제대로 되는 경우가 많습니다.
  • 그리고 플러그인의 업데이트를 주기적으로 체크해서 업데이트해 주는 게 좋습니다. 업데이트 주기가 일정하진 않지만, 빠를 경우 1주일에 한두 번 업데이트가 있었습니다.

참고링크

profile
11년차 검색개발자 입니다. 여러 지식과 함께 실제 서비스를 운영 하면서 발생한 이슈에 대해서 정리하고 공유하고자 합니다.

0개의 댓글