Obsidian を Web で使いたくて、Ignis を個人 k3s に載せた
Obsidian はローカルのファイルを直接扱えるところが好きだ。 ただ、使い続けていると「この vault をブラウザから開きたい」と思う場面が増えてくる。
出先の端末、タブレット、制約のある端末、ちょっとした確認だけしたいとき。 そういうときに、Obsidian の Web 版のように使える場所があるとかなり便利だと思っている。
自分の個人 k3s では、その入口として Nystik-gh/ignis を置いている。 まず、このプロジェクトを作って公開してくれている作者に感謝したい。 Obsidian をブラウザで使いたいという願いに対して、かなり真剣に向き合ってくれているプロジェクトだと思う。
この記事では YAML の細かい解説はしない。 Ignis が何をしてくれるのか、それを個人 k3s に載せるときに自分はどんな大まかな構成にしているのかを書く。
Ignis とは何か
Ignis は、Obsidian を通常のブラウザから使えるようにする self-hosted なサーバー実装だ。
単なるリモートデスクトップではない。 サーバー側に vault を置き、ブラウザから Obsidian の UI を開く。 そのため、VNC のような「画面を遠隔操作している」感覚ではなく、Web アプリとして Obsidian に触る体験に近い。
README を読むと、Ignis の中心は Obsidian が使っている Electron API をブラウザ向けに補う compatibility shim だと説明されている。 ここが面白い。 Obsidian を別物に作り直すのではなく、Obsidian がブラウザでも動けるように足場を作っている。
また、Ignis は Obsidian 本体を同梱して配布しているわけではない。 Docker container の初回起動時に、Obsidian を公式配布元から取得する。 この点も、独立した相互運用ツールとしての立ち位置がはっきりしていて好感がある。
Ignis の何がありがたいか
自分が特にありがたいと思っているのは、Obsidian の「ローカルファイルを扱う気持ちよさ」を、できるだけ Web 側へ持ってこようとしているところだ。
Ignis では、vault はサーバー上に置かれる。 ブラウザからその vault を開き、編集し、必要に応じて複数の vault を扱える。 ファイルの upload / download、ブラウザタブ間での workspace、タブ間の live sync など、単に画面を表示するだけではなく、日常的に使うための機能が積まれている。
Obsidian の core editor、markdown、canvas、command palette、テーマ、CSS snippet、Obsidian plugin API を使う多くの community plugin も動くと説明されている。 もちろん、すべての plugin が動くわけではない。 Node の native module や child_process に依存する plugin は難しい。 それでも「ブラウザから触れる Obsidian」としてここまで寄せているのは、かなり大きい。
モバイル幅では UI が切り替わること、HTTPS が必要な機能があること、server-side sync や headless sync の方向性があることも含めて、単発の実験ではなく、実用を意識したプロジェクトになっている。
作者自身が日常的な Obsidian instance として使っている、という README の説明もいい。 自分が使うものをちゃんと育てているプロジェクトは、触っていて信頼しやすい。
ただし、そのまま外に出してはいけない
Ignis の README でも強く注意されているが、Ignis には現時点で built-in auth がない。 つまり、外部公開するなら reverse proxy などで必ず保護する必要がある。
これはかなり重要だ。
Obsidian の vault は、単なる閲覧データではない。 日記、設計メモ、非公開メモや下書き、未公開のアイデアが入っていることもある。 しかも Ignis は編集できる入口になる。
だから、自分の k3s では Ignis を直接公開せず、Traefik の手前で OIDC 認証を要求している。 アプリの中でログインさせるのではなく、Edge 側で止める。 ここはこの構成の一番大事なところだと思う。
自分の k3s での大まかな構成
構成をざっくり書くと、こうなる。
Browser
-> Traefik
-> OIDC middleware
-> Ignis Service
-> Ignis Pod
-> local PV
認証情報は別の流れで管理している。
OpenBao
-> External Secrets Operator
-> Kubernetes Secret
-> Traefik OIDC middleware
GitOps の流れはこう。
Git repository
-> Argo CD Application
-> Ignis overlay
-> Kubernetes resources
細かい YAML は記事では省くが、構成としては次のように役割を分けている。
- 共通の base: Ignis の Namespace、Deployment、Service
- 本番用 overlay: 公開設定、TLS、永続化、認証 middleware との接続
- Secret 管理: OIDC 用 Secret を External Secrets 経由で同期
- GitOps 管理: Argo CD Application と Image Updater の設定
この分け方にしておくと、「Ignis を動かす最低限」と「自分の本番クラスタで必要な保護、公開設定、永続化」を分けられる。
Ignis そのものの構成と、自分のクラスタ固有の事情を混ぜすぎない。 YAML の一行一行より、この責務分離のほうが大事だと思っている。
Traefik で認証をかける
Ignis 自体に built-in auth がないので、自分の構成では Traefik の OIDC middleware を使っている。 OIDC provider には別途用意している認証基盤を使い、特定の group claim を持つユーザーだけが Ignis に入れるようにしている。
ここでのポイントは、Ignis Pod に OIDC client secret を直接持たせないことだ。 Secret を読むのは Traefik middleware 側で、Ignis はその内側の HTTP アプリとして動く。
アプリに足りない認証機能を、Kubernetes の Edge で補う。 この考え方は、code-server や RStudio のようなブラウザ作業環境をクラスタに置くときにも近い。
便利なものほど、入口を雑に公開しない。 Obsidian vault を触れるアプリなら、なおさらそうだ。
vault は local PV に置く
Ignis で一番消したくないのは vault だ。
自分の構成では、Ignis 用の永続ボリュームを用意し、その中を役割ごとに分けて使っている。
| path | 役割 |
|---|---|
/vaults | Obsidian vault |
/app/data | Ignis の設定や sync 関連データ |
/app/obsidian-app | 初回起動時に取得した Obsidian assets の cache |
この構成にしておくと、Pod を作り直しても vault と設定を残せる。 また、Obsidian assets の cache も残るので、毎回初回取得のような動きになりにくい。
ただし、local PV は node に縛られる。 単純で扱いやすい一方、ノード交換やディスク移行では手作業の知識が必要になる。 そのため、Ignis の vault は backup 対象として明示的に扱うべきだと思っている。
ここは今後もう少し整えたい。 「バックアップしている」だけでなく、「復元時に PV、PVC、nodeAffinity をどう戻すか」まで README に残したい。
初回起動と HTTPS
Ignis は初回起動時に Obsidian を公式配布元から取得する。 そのため、最初の Pod 起動は少し待つ前提で考えている。
自分の構成では、初回起動に少し時間がかかる前提で待てるようにしている。 このあたりは Kubernetes 側で吸収している現実の運用差分だ。
また、Ignis の README では secure context、つまり HTTPS または localhost が重要だと説明されている。 ブラウザの crypto API や clipboard API に依存する機能があるため、普通の HTTP 公開では壊れる機能が出る。
自分の構成では Traefik + TLS で公開している。 Obsidian を Web で使うなら、HTTPS は「できれば」ではなく、ほぼ前提として考えたほうがいい。
GitOps に載せる意味
Ignis は個人用のアプリだが、GitOps に載せている。
GitOps では、Ignis 用の overlay を Argo CD Application の同期対象にしている。 また、Image Updater では Ignis の container image を追跡しているが、latest や nightly のような tag は使わず、バージョン番号の付いた tag に絞っている。
理由は単純で、Ignis は vault を編集できるアプリだからだ。
自動更新は便利だが、Obsidian や Ignis 側の挙動が変わると、保存、同期、plugin の動作に影響する可能性がある。 そのため、更新は GitOps に載せつつも、どの version を使っているかを明示し、更新後には最低限の動作確認をする前提にしている。
GitOps に載せる目的は、完全自動で放置することではない。 どの version を、どの overlay で、どの認証と storage に接続しているかを Git に残すことだ。
詰まりやすいところ
この構成で詰まりやすいのは、だいたい次のあたり。
- OIDC provider 側の redirect URI が合っていない。
- group claim が想定通りに token に入っていない。
- Traefik middleware が Secret を読めていない。
- TLS が正しく発行されていない。
- local PV の node と Pod の scheduling が合っていない。
- 初回起動時の Obsidian 取得に時間がかかる。
- HTTPS ではないため、ブラウザ API の一部が使えない。
- plugin が Node native module や
child_processに依存していて動かない。
Ignis の問題なのか、Ingress の問題なのか、OIDC の問題なのか、PVC の問題なのかを分けて見ることが大事になる。
切り分けるときは、まずアプリ本体と永続化が正常かを見て、その後に Ingress、認証 middleware、OIDC provider 側を確認する。 アプリが動いているのに入れない場合は、認証や入口側の設定を疑うことが多い。
まとめ
Obsidian の Web 版的な体験は、かなり求められていると思う。 少なくとも自分は、vault をブラウザから開けるだけで、メモや下書きの使い勝手が大きく変わる。
Nystik-gh/ignis は、その欲しかった体験にかなり近いものを提供してくれる。 Obsidian をブラウザで動かすための compatibility shim、server-side vault、multi-vault、upload / download、tab 間 sync、HTTPS 前提の実用設計。 まだ制約はあるが、それも README でかなり正直に書かれている。
だからこそ、自分の k3s では Ignis をそのまま外に出さず、Traefik OIDC、ExternalSecret、local PV、Argo CD の中に置いている。
細かい YAML より大事なのは、どこで守り、どこにデータを置き、どう更新し、壊れたときにどこを見るかだ。 Ignis は便利さが強い分、入口と永続化をちゃんと設計しておきたい。
Obsidian をブラウザで使いたい人にとって、Ignis はかなり面白い選択肢だと思う。 そして、自分のクラスタで実際に動かしてみると、こういうプロジェクトを公開してくれていることへのありがたさを改めて感じる。
