課題
Obsidian で書き溜めたノートをスマホからも閲覧したい。しかし以下の制約がある。
- Obsidian モバイルアプリは Vault が肥大化する(画像・デイリーノートが大量にある等)と同期が失敗しがち
- Obsidian Publish は月額有料、かつ機密データを含む Vault は外部 SaaS のサーバーに置きづらい
- GitHub Mobile で Private リポを開くことはできるが、Wikilink がリンクとして機能せず実用性が低い
「スマホでは閲覧だけできれば十分」という前提のもと、機密性を保ちながら自分専用の認証付き Web サイトとして公開する仕組みを作る。月額コストは $0 を目指す。
解決策の全体像
GitHub にある Obsidian Vault のリポジトリとは別に「公開用リポジトリ」を作り、そこから定期的に Vault の内容を取得して Quartz で静的サイトを生成、Cloudflare Pages にデプロイする。さらに前段に Cloudflare Access を置いて認証保護することで、自分(または許可した人)以外はアクセスできないようにする。
[Vault Repo (private)]
│ Fine-grained PAT で読み取り
▼
[Publish Repo (private)] ── GitHub Actions ──▶ [Quartz Build] ──▶ [Cloudflare Pages]
│
[Cloudflare Access (認証)]
│
▼
スマホブラウザで閲覧
主な特徴
- Vault 本体のリポジトリは一切編集しない(settings 含めて触らない)
- 静的サイトは Quartz で生成(Wikilink・バックリンク・グラフビュー対応、見た目は Obsidian Publish 風)
- Cloudflare Access で認証ゲートを設置(メールPINで自分だけが入れる)
- 完全無料で運用可能(GitHub Actions 月2000分・Cloudflare Pages 無制限・Cloudflare Access 50ユーザーまで無料)
必要なもの
- GitHub アカウント(無料プランで OK)
- Cloudflare アカウント(無料プランで OK)
- 既に GitHub に push 済みの Obsidian Vault(obsidian-git プラグインなどで自動同期している Private リポ想定)
- ローカルに Node.js 22+、Git、
ghCLI(推奨)
手順
1. Quartz テンプレートを使った公開用リポジトリの準備
Quartz テンプレートをローカルにクローンして、不要な履歴と GitHub 設定をクリアする。
git clone --depth 1 https://github.com/jackyzha0/quartz.git your-vault-publish
cd your-vault-publish
rm -rf .git content/* .github
git init -b main
2. quartz.config.ts のカスタマイズ
最低限以下を変更する。
configuration: {
pageTitle: "Your Vault",
locale: "ja-JP",
baseUrl: "your-vault.pages.dev",
ignorePatterns: [
".obsidian",
".git",
"templates",
"private",
"**/.DS_Store",
],
defaultDateType: "modified",
...
}
公開したくないフォルダ・ファイルがあれば ignorePatterns に追加しておく。
ビルド速度を優先したい場合は Plugin.CustomOgImages() をコメントアウトしておくと OG 画像生成が省略されて速くなる。
3. GitHub Actions ワークフロー作成
.github/workflows/deploy.yml を以下の内容で作成。
name: Build and Deploy
on:
schedule:
- cron: "0 * * * *" # 毎時0分(無料枠 月2000分以内に収まる頻度)
workflow_dispatch:
push:
branches: [main]
concurrency:
group: deploy
cancel-in-progress: false
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout publish repo
uses: actions/checkout@v4
- name: Checkout vault content
uses: actions/checkout@v4
with:
repository: YOUR_USER/YOUR_VAULT
token: ${{ secrets.VAULT_TOKEN }}
path: vault-content
- name: Sync vault into content/
run: |
rm -rf content && mkdir -p content
rsync -a \
--exclude='.git' \
--exclude='.obsidian' \
--exclude='.DS_Store' \
vault-content/ content/
rm -rf vault-content
- name: Generate index.md if missing
run: |
if [ ! -f content/index.md ]; then
cat > content/index.md <<'EOF'
---
title: Your Vault
---
# Your Vault
Welcome to your vault.
EOF
fi
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- name: Install dependencies
run: npm ci
- name: Build site
run: npx quartz build
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy public --project-name=your-vault --branch=main
YOUR_USER/YOUR_VAULT は自分の Vault リポジトリのパスに置き換える。your-vault も自分のプロジェクト名に揃える。
4. Vault 読み取り用 Personal Access Token (PAT) の作成
GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens で新規作成。
- Token name:
your-vault-publish-readerなど - Resource owner: Vault リポを所有しているアカウント
- Repository access: Only select repositories → Vault リポのみを選ぶ(Publish リポではない)
- Permissions:
- Contents: Read-only
- Metadata: Read-only
注意点として、Resource owner と Repository access は Vault 本体側を指定すること。Publish リポを指定しても Vault は読めず、Actions 実行時に 404 エラーになる。
組織所有のリポの場合は組織管理者の承認が必要になることがある。承認が面倒なら Classic PAT(repo スコープ)でも代用できる。
5. Cloudflare Pages プロジェクトを空で作成
Cloudflare ダッシュボード → Workers & Pages → Create → Pages → Direct Upload を選択。
- Project name:
your-vault(このままyour-vault.pages.devがサブドメインになる) - 適当なプレースホルダー HTML(
<!DOCTYPE html><body>Initializing...</body>など)を1ファイルだけドラッグしてプロジェクトを作成
GitHub 連携ではなく Direct Upload を使う理由は、後述の通り GitHub Actions 側でビルドして wrangler でデプロイする設計のため。GitHub 連携にすると Cloudflare 側でも独自にビルドしようとして競合する。
その後、別途 Cloudflare の API Token と Account ID を取得しておく。
- API Token: My Profile → API Tokens → Create Token → 「Edit Cloudflare Workers」テンプレが手っ取り早い(Cloudflare Pages: Edit が含まれる)
- Account ID: ダッシュボードの URL またはアカウントホーム画面に表示されている32桁の値
6. GitHub Secrets 登録
Publish リポの Settings → Secrets and variables → Actions に以下3つを登録する。
| Secret 名 | 値 |
|---|---|
VAULT_TOKEN |
手順4で作った PAT |
CLOUDFLARE_API_TOKEN |
手順5で取得した Cloudflare API Token |
CLOUDFLARE_ACCOUNT_ID |
手順5で取得した Cloudflare Account ID |
gh CLI 経由なら以下のように対話的に登録できて、トークンを画面に表示せず安全。
gh secret set VAULT_TOKEN -R YOUR_USER/your-vault-publish
gh secret set CLOUDFLARE_API_TOKEN -R YOUR_USER/your-vault-publish
gh secret set CLOUDFLARE_ACCOUNT_ID -R YOUR_USER/your-vault-publish
7. Cloudflare Access で認証保護(最重要・最優先)
実コンテンツをデプロイする前に、必ず認証保護を設定する。デプロイ後に設定するとその間サイトが全公開状態になるため。
- Cloudflare ダッシュボード → Zero Trust へ移動
- 初回はチーム名(subdomain)を聞かれるので任意で設定。プランは Free を選択
- Access → Applications → Add an application → Self-hosted
- 設定:
- Application name:
your-vault - Session Duration:
1 month(毎回ログインを避けるため長め) - Application domain: Subdomain は空、Domain は
your-vault.pages.devをプルダウンから選択
- Application name:
-
Access policies → Create new policy:
- Policy name: 任意
- Action: Allow
- Include rule: Emails → 自分のメールアドレス
-
Authentication:
- 「Accept all available identity providers」を ON にしておけば、デフォルトで One-time PIN(メールにPIN送信)が使える
- Save / Add application
シークレットウィンドウで https://your-vault.pages.dev を開いて、Cloudflare Access のメールアドレス入力画面が出ることを確認する。これを確認するまで次の手順に進まない。
8. 初回デプロイ
Publish リポをコミットして GitHub に push、または Actions タブから手動で workflow を実行する。
git add .
git commit -m "Initial Quartz setup"
git push -u origin main
ビルドが完了すると、本物の Vault コンテンツが反映される。シークレットウィンドウで再度アクセスして、認証通過後に Vault のノートが見えれば成功。
ハマりポイント
Quartz は index.md が無いとトップページを生成しない
Vault のルートに index.md がなければ、ビルド出力に public/index.html が含まれない。結果、ルート URL(/)にアクセスすると古いプレースホルダー HTML が残ったまま見えてしまう。手順 3 のワークフローに Generate index.md if missing ステップを入れて、Vault に存在しない場合だけ自動生成する仕組みにしておくと安全。
PAT の権限指定で間違えやすいポイント
Resource owner と Repository access の両方が「Vault 本体側」を指していなければならない。Publish リポを指定しても権限的には何も得られず、Not Found エラーで Actions が失敗する。
Direct Upload を選ぶ理由
Cloudflare Pages の GitHub 連携を使うと、Cloudflare 側でも独自にビルドが走ってしまう。今回の設計は「GitHub Actions 側でビルドして wrangler で deploy」という形なので、Cloudflare 側のビルドは不要。Direct Upload を選べばこの競合を避けられる。
CDN キャッシュよりブラウザキャッシュの方が手強い
デプロイ直後にスマホで古いコンテンツが見える時、まずシークレットウィンドウで開き直すか URL に ?nocache=1 を付ける。それでもダメな時は Cloudflare の Pages 管理画面でデプロイの状態を確認する。
コストの目安
GitHub Actions の無料枠は月 2000 分。hourly cron で 1 ビルド 2 分の場合は月 1440 分で収まる。実運用での消費量は GitHub Settings → Billing で確認できる。月の中盤に使用量をチェックして、超えそうなら cron を 0 */2 * * *(2時間ごと)に下げて節約する。
Cloudflare Pages(無制限デプロイ・帯域・リクエスト)と Cloudflare Access(50ユーザーまで)は通常用途では無料枠で完全に賄える。
運用のコツ
- 「書く側はPC、見る側はスマホ」と割り切る。スマホからの編集はサポートしない設計
- 更新内容がスマホに反映されるまで最大1時間のラグがある。即時反映が必要なら Actions タブから手動実行(約2分)
- スマホで Web サイトを開いたあと「ホーム画面に追加」しておくと、アプリのように使える
- ノート単位で公開したくないものはフロントマターに
draft: trueを付ければ Quartz のRemoveDraftsプラグインで除外される