1. はじめに:現実的なアプローチ
Umamiを完全にCloudflare上に構築しようとする試みは魅力的ですが、現実的には複雑度が高い経路です。
UmamiはPostgreSQLまたはMySQLのみを公式サポートしており、Cloudflare D1(SQLiteベース)は公式サポートしていません。Cloudflare WorkersはV8 Isolate環境のため、Node.jsベースのUmamiをそのまま構築できず、データベースレイヤーを直接パッチする必要があります。そのパッチは更新ごとに壊れるリスクが大きいです。
そこで本ドキュメントでは、「UmamiをCloudflareに極力近づけつつ、実用的に運用する」2つの現実的なアプローチを検討します。対象サイトは、現在Cloudflare Pages無料ティアで運用中のvibequant.ccとそのサブドメインです。
関連背景:Cloudflareウェブ分析ソリューションガイドで推奨された「Web Analyticsで開始 → 必要時にUmami拡張」の実行計画にあたります。
| アプローチ | 説明 | 推奨状況 |
|---|---|---|
| A. Vercel + Cloudflare Workerプロキシ | Umamiアプリは Vercel、DBはNeon/Supabase、トラッキングはCloudflare Workerでプロキシ | 最も簡単で速い。検証・導入の第一候補 |
| B. Fly.io + Cloudflare Workerプロキシ | Umamiアプリは Fly.ioコンテナ、DBはNeon/Supabase、トラッキングはCloudflare Workerでプロキシ | コールドスタート・サーバーレス制約が気になる場合。若干の運用コスト・設定が必要 |
訪問者のブラウザ
|
| script + /api/send (analytics.vibequant.cc)
v
Cloudflare Worker(ファーストパーティ・プロキシ)
|
v
Umamiアプリ (A: Vercel / B: Fly.io) <--> PostgreSQL (Neon または Supabase)
2. シナリオ比較まとめ
| 項目 | A. Vercel + Worker | B. Fly.io + Worker |
|---|---|---|
| 設定の難易度 | 低(約40〜60分) | 中(CLI、メモリスケール、デプロイ再試行) |
| 月額コスト(小規模) | 実質0円が可能 | 0円に近くならない場合もある(下記コスト節参照) |
| コールドスタート | Vercel Function + Neon/Supabase一時停止時に発生 | マシンがalways-onなら低い。スケール・トゥ・ゼロなら発生 |
| 運用の複雑さ | Fork同期、Vercelビルド上限 | Dockerイメージ、fly scale、IPv4 |
| データ所有 | DBはNeon/Supabase、アプリはVercel | DBはNeon/Supabase(またはFly Postgres)、アプリはFly |
| vibequant.ccへの適合度 | 第一推奨 | トラフィック・安定性問題後の移行用 |
| 広告ブロッカー回避 | Workerカスタムドメインで同様に可能 | 同様 |
結論(推奨):まずAで導入・検証し、Vercelのコールドスタート・Hobby上限・Prisma接続の問題が体感されたらBに移行します。Workerプロキシとanalytics.vibequant.ccドメイン設計は両方で再利用します。
3. アプローチA:Vercel + Cloudflare Workerプロキシ(推奨)
Umamiコミュニティで最も広く使われる組み合わせです。公式ガイド:Running on Vercel。
3.1 アーキテクチャ
訪問者のブラウザ
|
| GET /u.js , POST /api/send
v
Cloudflare Worker @ analytics.vibequant.cc
|
v
Vercel (Umami Next.js) <--> Neon または Supabase (PostgreSQL)
3.2 準備物
| 項目 | 備考 |
|---|---|
| GitHubアカウント | Umami fork用 |
| Cloudflareアカウント(無料) | すでにvibequant.ccのDNS/Pagesを運用中 |
| Vercelアカウント(Hobby) | GitHubログイン |
| NeonまたはSupabase | 無料PostgreSQL |
opensslまたはパスワード生成器 |
APP_SECRET用 |
| vibequantビルドパイプラインの修正権限 | VibeQuant/content/build.mjsにスクリプトを挿入 |
3.3 段階別インストール
Step 1: Umamiリポジトリのフォークumami-software/umamiを自分のGitHubアカウントにフォークします。Step 2: PostgreSQL作成
NeonまたはSupabaseでプロジェクトを作成し、接続文字列(postgresql://...)をコピーします。
- Neon:サーバーレスPostgres、アイドル時に一時停止(コールドスタート)する可能性がある
- Supabase:無料ティアのDB容量・接続上限を確認する必要がある
Step 3: VercelへUmamiをデプロイ1. VercelでAdd New → Projectからフォークしたumamiをインポート
2. 環境変数を設定:
| 変数名 | 値 | 備考 |
|---|---|---|
DATABASE_URL |
PostgreSQL接続文字列 | 必須。Neonの場合はpooled URLを推奨 |
APP_SECRET |
openssl rand -hex 32の結果 |
v2以降基準。旧版文書のHASH_SALTは置き換えられた(Environment variables) |
TRACKER_SCRIPT_NAME |
例:uまたはvq-beacon |
デフォルトのscript.jsの代わりに使用してブロック確率を減らす |
COLLECT_API_ENDPOINT |
例:/api/e(任意) |
デフォルトの/api/sendの代わりに使用可能 |
DISABLE_TELEMETRY |
1(任意) |
Umami自身のテレメトリを無効化 |
- デプロイ後、
.vercel.appのURLを確認
Step 4: Umami初期設定
- デプロイURLにアクセス
- デフォルトアカウント:
admin/umami(Login) - すぐにパスワードを変更4. Settings → Websitesでサイトを追加しWebsite IDをコピー
vibequantはホストが複数あるため、Websiteをどう分割するかをこのステップの前に決めます(下記8. vibequant.ccの追加要件参照)。
Step 5: Cloudflare WorkerプロキシWorkerはトラッカースクリプトと収集APIの両方をプロキシする必要があります。元の案のように/api/sendだけを通すと、スクリプトの読み込みが壊れます。
例(パスは実際のTRACKER_SCRIPT_NAME / COLLECT_API_ENDPOINTに合わせて調整):
const UMAMI_ORIGIN = "https://your-umami.vercel.app"; // Vercel Umami URL
const SCRIPT_PATH = "/u.js"; // TRACKER_SCRIPT_NAMEの結果に合わせる
const COLLECT_PATH = "/api/send"; // またはCOLLECT_API_ENDPOINT
export default {
async fetch(request) {
const url = new URL(request.url);
const path = url.pathname;
const isScript = path === SCRIPT_PATH || path === SCRIPT_PATH.replace(/\.js$/, "");
const isCollect = path === COLLECT_PATH;
if (!isScript && !isCollect) {
return new Response("Not found", { status: 404 });
}
const upstream = new URL(path + url.search, UMAMI_ORIGIN);
const headers = new Headers(request.headers);
headers.set("Host", new URL(UMAMI_ORIGIN).host);
// Cloudflare訪問位置ヘッダーがあればそのまま転送(Managed Transforms有効時)
// CF-IPCountry, CF-IPCity など
const init = {
method: request.method,
headers,
body: request.method === "GET" || request.method === "HEAD" ? undefined : request.body,
redirect: "follow",
};
const response = await fetch(upstream, init);
const out = new Response(response.body, response);
out.headers.set("Access-Control-Allow-Origin", "*"); // 必要ならホストのホワイトリストに絞る
return out;
},
};
注意:
- 統計照会用のAPIトークンをWorkerのソースにハードコードしないこと。ダッシュボードはVercel URL(または別の保護されたパス)から直接アクセスします。
- プロダクションでは
UMAMI_ORIGINをWorkerのSecrets / Varsとして保持します。
Step 6: カスタムドメインWorkerにanalytics.vibequant.ccを接続します。トラッキングがファーストパーティ(または同じ登録ドメインのサブドメイン)として見えれば、広告ブロッカー回避の確率が上がります。コミュニティの議論:umami#1026。Step 7: vibequant.ccにトラッキングコードを挿入正しいスクリプトの形は以下の通りです(srcはスクリプトファイル、/api/sendではない):
<script
defer
src="https://analytics.vibequant.cc/u.js"
data-website-id="YOUR_WEBSITE_ID"
></script>
静的HTMLはcontent/build.mjsのlayout()で生成されるため、すべてのpages/<strong>/index.htmlを手動で修正するのではなく、ビルドテンプレートの<head>**(例:extraHeadまたは共通スニペット)に入れる方が安全です。その後、各Pagesプロジェクト(vibequant-web、vibequant-tech、vibequant-ctiなど)を再デプロイします。
3.4 長所短所
| 長所 | 短所 |
|---|---|
| 設定が最も速い。公式Vercelガイドと一致 | Hobbyプランのファンクション実行時間・同時実行数の上限 |
| Docker/CLI不要 | Neon/Supabaseのアイドル一時停止とVercelコールドスタートが重なる可能性 |
| コストを0円に近く維持しやすい | Forkをupstreamと定期的に同期する必要がある |
| WorkerプロキシはBに移行しても再利用可能 | Prisma + サーバーレスDB接続プールの問題が発生しうる(pooled URLがほぼ必須) |
| Next.jsネイティブホスティング | ダッシュボードもVercelにあるため、障害時にアプリ・収集が同時に影響を受ける |
3.5 リスク(A)
| リスク | 影響 | 緩和策 |
|---|---|---|
| Neon/Supabaseの一時停止 | 最初のPVの遅延・ドロップ | 定期ping、または最小有料プラン、またはBへ移行 |
| Vercel Hobby上限超過 | デプロイ失敗・帯域制限 | トラフィック監視、必要時にProまたはBへ |
| 接続文字列をnon-pooledで使用 | 間欠的なDBエラー | Neon pooled / Supabase poolerのURL |
デフォルトのadmin/umamiを放置 |
ダッシュボード乗っ取り | 即座にパスワード変更、URL共有を最小化 |
| Workerがオープンプロキシ化 | 悪用・コスト増 | パスのホワイトリスト、必要ならOrigin制限 |
| Forkの放置 | セキュリティパッチの欠落 | upstreamリモートの定期同期 |
4. アプローチB:Fly.io + Cloudflare Workerプロキシ
Vercelのサーバーレス制約が負担になる場合や、常駐プロセスに近い形にしたい場合に選択します。公式ガイド:Running on Fly.io。
4.1 アーキテクチャ
訪問者のブラウザ
|
v
Cloudflare Worker (analytics.vibequant.cc)
|
v
Fly.io (Umami Docker) <--> Neon/Supabase または Fly Postgres
4.2 インストール概要
- Neon/SupabaseでPostgreSQL作成(Aと同様) — または
fly launch時にPostgresを作成 - flyctlをインストール・ログイン
fly.tomlを作成後デプロイ。イメージ例:
# 公式ドキュメント例に基づく。region・app名は環境に合わせて変更
kill_signal = "SIGINT"
kill_timeout = "5s"
[experimental]
auto_rollback = true
[build]
# ドキュメント: docker.umami.is/... または ghcr.io/umami-software/umami:postgresql-latest
image = "docker.umami.is/umami-software/umami:postgresql-latest"
[[services]]
protocol = "tcp"
internal_port = 3000
processes = ["app"]
[[services.ports]]
port = 80
handlers = ["http"]
force_https = true
[[services.ports]]
port = 443
handlers = ["tls", "http"]
[services.concurrency]
type = "connections"
hard_limit = 25
soft_limit = 20
[[services.tcp_checks]]
interval = "15s"
timeout = "2s"
grace_period = "1s"
- 主な運用ポイント(公式ドキュメント基準):
fly secrets set APP_SECRET="$(openssl rand -hex 32)"
fly deploy
fly scale memory 512 # Umamiは256MBで失敗する事例が多い
fly deploy
- ログイン:
admin/umami→ パスワード変更 - AのStep 5〜7と同様にWorkerプロキシ・ドメイン・サイトスクリプトを接続(
UMAMI_ORIGINだけFly URLに変更)
4.3 長所短所
| 長所 | 短所 |
|---|---|
| コンテナで明確なコントロール | CLI・スケール・ヘルスチェックなどの学習コスト |
| 512MB always-onならコールドスタート緩和 | 無料ティアの256MBマシンだけでは不足する可能性が高い |
リージョンをnrt/icnなどから選択可能 |
公開IPv4など少額の固定課金が発生する可能性(Fly pricing) |
| AのWorker/DBを再利用しやすい | イメージタグlatestの追跡・ロールバック責任 |
| Vercel Hobby上限から独立 | 放置時にマシンコスト・幽霊ボリュームが蓄積 |
4.4 リスク(B)
| リスク | 影響 | 緩和策 |
|---|---|---|
| メモリ512MB未満 | OOM、デプロイ/マイグレーション失敗 | fly scale memory 512以上 |
| 「無料」という前提 | 月数ドルの課金 | Billing alert、IPv4・マシン数の点検 |
| Fly Postgresを併用 | ストレージ・マシンの二重コスト | DBはNeon/Supabaseの維持を推奨 |
| スケール・トゥ・ゼロ | 最初のリクエストの遅延 | 最低1マシンをalways-on、またはAと同様のping |
| リージョンの不一致(アプリ東京、DB米国) | 収集APIの遅延 | アプリ・DBのリージョンを近づける |
5. 共通:Cloudflare最適化とD1非推奨
5.1 Cloudflare位置ヘッダー
CloudflareダッシュボードでManaged Transformsのvisitor location headersを有効にすると、Umamiが国・地域をより正確に認識します。関連環境変数:CLIENT_IP_HEADER、SKIP_LOCATION_HEADERS(Environment variables)。
5.2 D1にUmamiを構築する経路
D1で動かすにはDBレイヤーのパッチが必要です。
- Umami更新ごとにパッチを再適用
- 公式未サポート → 障害時はコミュニティ依存
- D1の無料割り当て・SQLite制約
非推奨。 Neon/Supabaseの無料PostgreSQLが保守コスト対効果に優れています。
5.3 ファーストパーティ・トラッキング
analytics.vibequant.cc + カスタムTRACKER_SCRIPT_NAME / COLLECT_API_ENDPOINTの組み合わせが、広告ブロッカー回避に最も現実的です。「回避」は完全ではなく、一部の厳格なブロックリストには依然として引っかかる可能性があります。
6. コスト整理(無料ティア基準、2026年の文脈)
| サービス | 無料/許容量(概算) | Umamiに十分か? | 注意 |
|---|---|---|---|
| Cloudflare Workers | 日次リクエスト上限(アカウントプラン基準) | トラッキングプロキシとしては通常十分 | オープンプロキシ・ボット悪用時に消耗 |
| Vercel Hobby | 帯域・ファンクション上限 | 小規模コンテンツサイトには通常十分 | 商用利用上限・コールドスタート |
| Neon Free | ストレージ・compute時間 | 初期・低トラフィックには十分 | アイドル一時停止 |
| Supabase Free | DB容量・帯域 | 初期には十分 | プロジェクトのpauseポリシー確認 |
| Fly.io | 共有CPU・時間の許容量あり | Umamiの512MB要求と衝突する可能性 | IPv4・メモリ超過時に有料化 |
- B: 「完全無料」と断定しづらい。メモリ・IPv4だけでも月に少額課金が発生しうる。Billing alertを必ず設定する。
「月額コスト0円」はA + Neon/Supabase + Workerの組み合わせでのみ安全に目標とすべきです。
7. 共通リスクと運用上の課題
| 領域 | 内容 |
|---|---|
| セキュリティ | デフォルトパスワードの変更、ダッシュボードURL露出の最小化、WorkerにAPI Bearerトークンを入れない、APP_SECRETの漏洩禁止 |
| プライバシー | Umamiはクッキーレスに近いが、公開サイトの個人情報保護方針・クッキーバナー方針と合致するか確認。EU訪問者がいれば保管期間・目的を明示 |
| データ損失 | Neon/Supabase無料ティアの削除・pauseポリシー。定期的なDBダンプまたは論理バックアップ |
| 正確性 | 広告ブロッカー・ITP・ボットフィルターによりPVは常に過小/過大の可能性。Cloudflare Web Analyticsと並行して交差検証を推奨 |
| 依存関係 | アプリホスト(Vercel/Fly)+DB(Neon/Supabase)+CF Workerの3軸。一つの軸が障害を起こすと収集に空白が生じる |
| 更新 | Fork sync(A)またはイメージタグ固定(B)。Prismaマイグレーション失敗時のロールバック計画 |
| 悪用 | /api/sendスパムによるDB肥大化。Website IDの公開は避けられないため、rate limit・異常値の監視 |
8. vibequant.ccの追加要件
元のガイドにない、このレポ・ドメイン構造のために追加で必要な作業です。
8.1 マルチホスト戦略
現在の概略マッピング(CUSTOM_DOMAIN_SETUP.md):
| ホスト | Pagesプロジェクト | コンテンツ |
|---|---|---|
vibequant.cc |
vibequant-web | ハブ・エッセイなど |
docs.vibequant.cc |
vibequant-docs | Columns |
tech.vibequant.cc |
vibequant-tech | TechDoc |
cti.vibequant.cc |
vibequant-cti | CTI |
play.vibequant.cc |
vibequant-play | Playground |
lab / research |
各々 | 実験・リサーチ |
選択肢:
- ホストごとにWebsite ID — ダッシュボードがクリーンになり、スクリプトのIDをホストごとに分岐
- 1つのWebsiteに複数ドメイン — 設定が単純、レポートでホスト/パスによりフィルタ
コンテンツアーカイブ用途であれば、ホストごとのWebsite(docs / tech / cti / hub)が分析に有利です。
8.2 ビルドパイプライン挿入
トラッキングコードはVibeQuant/content/build.mjsのlayout()の<head>に入れるのが正しいです。生成されたHTMLを直接修正すると次のビルドで上書きされます。
追加で必要なもの:
UMAMI_WEBSITE_ID_*またはビルド時のenvでIDを注入- ローカルプレビューでトラッキングを無効化するフラグ(
UMAMI_ENABLED=0) - ビルド後、関連するPagesすべてを再デプロイ
8.3 DNS / Worker
analytics.vibequant.cc→ Workerカスタムドメイン- 既存のPagesカスタムドメインと衝突しないか確認
- CORS:複数サブドメインからスクリプト・POSTが来るため、Worker/Umami CORS設定を確認
8.4 Cloudflare Web Analyticsとの関係
すでにWeb Analyticsを使用中、または使用予定であれば:
- 短期:並行運用して数値を交差検証
- 中期:Umamiが安定したらWeb AnalyticsはPVバックアップ用のみ維持、または整理
両方を有効にしてもページコストは小さいですが、指標解釈時に二重集計を混同しないよう注意します。
8.5 カスタムイベント(後続)
スクロール深度・アウトバウンドクリックなどはUmamiCustom Eventsで追加します。基本のpageviewが安定した後に実装します。
8.6 ドキュメント・運用チェック
APP_SECRET、DB URLをレポにコミットしない(.env/ Vercel・Fly secrets)- 障害時の連絡経路:Vercel/Flyのステータス、Neon/Supabaseのステータス
- 週1回:fork syncまたはイメージダイジェストの確認(任意)
9. チェックリスト:vibequant.cc導入スケジュール
| 段階 | 作業 | 予想時間 |
|---|---|---|
| 1 | ホスト別Website戦略の決定(単一 vs 複数ID) | 10分 |
| 2 | Umami GitHubフォーク | 2分 |
| 3 | Neon/Supabase PostgreSQL作成 | 5分 |
| 4 | Vercelデプロイ + DATABASE_URL / APP_SECRET / tracker名 |
15分 |
| 5 | ログイン・パスワード変更・Website追加 | 5分 |
| 6 | Cloudflare Worker(script + collectプロキシ)+ Secrets | 15分 |
| 7 | analytics.vibequant.cc接続 |
5分 |
| 8 | Managed Transforms(visitor location)確認 | 3分 |
| 9 | build.mjsにスクリプト挿入 + ローカルビルド確認 |
15分 |
| 10 | 該当Pagesプロジェクトを再デプロイ | 10〜20分 |
| 11 | テスト訪問 → Realtime/ダッシュボード確認 | 5分 |
| 12 | (任意)Billing alert、DBバックアップ、Web Analytics併用メモ | 10分 |
総予想:約1〜1.5時間(マルチホスト・ビルド修正を含む場合)。原案の40〜50分は「単一サイト・手動HTML挿入」基準に近いです。
アプローチBを最初から選ぶと、Flyメモリスケール・課金確認で+30〜60分と少額のコストの可能性が加わります。
10. 推奨決定
- 第一段階:アプローチA(Vercel + Neon + Worker)
- コスト・速度・文書成熟度の面でvibequant.ccに最も適合
- プロキシは最初から
analytics.vibequant.cc- 後でBに移行してもWorker originだけ差し替え
- D1/Workersネイティブのumamiは行わない4.build.mjs経由で挿入 + ホストごとのWebsite ID5.コールドスタート・Hobby上限が体感されたらBに移行
- それまではFlyの「無料」を前提としないこと
この組み合わせは無料ティアに近く維持しながら、ファーストパーティ・トラッキング、データ所有、Umami更新経路を確保します。Cloudflare Web Analyticsで軽く始めた後、この計画でUmamiを接続する順序が、運用負担対効果として最も優れています。
11. リファレンス
公式ドキュメント
- Umami — Running on Vercel
- Umami — Running on Fly.io
- Umami — Environment variables(
APP_SECRET、TRACKER_SCRIPT_NAME、COLLECT_API_ENDPOINT) - Umami — Login (default admin / umami)
- Umami — Tracker functions / custom events
- Umami GitHub
- Fly.io — Resource pricing
- Fly.io — flyctl
- Vercel — Rewrites(代替:メインアプリがVercelの場合の同一ドメインプロキシ)
- Neon / Supabase
コミュニティ・ガイド
- Preventing ad blockers with Cloudflare Worker (umami#1026)
- Self-hosted Umami on Vercel + Supabase(例)
- Umami on Vercel + Neon(要約ガイド)
このリポジトリ
- Cloudflareウェブ分析ソリューションガイド
- VibeQuantカスタムドメイン設定
- トラッキング挿入ポイント:
VibeQuant/content/build.mjs(layout()<head>)