セルフホスト
Nesh は MIT ライセンスで、Node.js が動く環境と Postgres が用意できれば自前でホストできます。リファレンス構成は Vercel + Supabase ですが、どちらも必須ではありません。
前提条件
- Node.js 20 以降 (Vercel のビルドイメージそのままで動きます)。
- Postgres 15 以降 — Supabase、Neon、RDS、自前運用、いずれも可。
- Next.js のビルド成果物が動くホストならどこでも (Vercel、Cloudflare、Fly.io、VM、Docker など)。
- 本番オリジンは HTTPS 必須 — ブラウザは平文 HTTP では Service Worker を登録しません。
1. クローンとインストール
リポジトリをクローンして依存関係をインストール:
git clone https://github.com/piro0919/nesh.git
cd nesh
pnpm install2. Postgres を用意してマイグレーションを適用
スキーマはすべて supabase/migrations/ にあります。Supabase を使う場合は、リポジトリ同梱の CLI でローカルスタックを起動:
pnpm db:startリモートプロジェクトにも同じマイグレーションを適用してください。Supabase 以外の Postgres を使う場合は supabase/migrations/ 配下の SQL ファイルを名前順に流し込みます。
全テーブルで Row-Level Security 有効。ダッシュボードからの DB アクセスは Supabase 認証されたユーザーとして、cron や REST 送信などの内部ルートだけが service role キーで RLS をバイパスします。
3. 環境変数
を にコピーして以下を埋めます: .env.example → .env.local.
NEXT_PUBLIC_SUPABASE_URL | Supabase が公開する Postgres URL (または任意の PostgREST エンドポイント)。 |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Anonymous (公開) キー — ブラウザに渡しても安全。 |
SUPABASE_SERVICE_ROLE_KEY | Service-role キー — サーバー専用、RLS をバイパスします。DB パスワードと同等に扱ってください。 |
NEXT_PUBLIC_SITE_URL | Nesh デプロイの公開オリジン。SDK ユーザーに見せる apiBase と公開イベント追跡 URL の生成に使われます。 |
CRON_SECRET | cron が自身を認証するための共有秘密。十分にランダムな文字列で OK。 |
VAPID_KEY_ENCRYPTION_KEY | プロジェクト毎の VAPID 秘密鍵を保存時に暗号化する 32 バイトの AES-256-GCM 鍵。下記コマンドで生成。この鍵を失うと既存プロジェクトの VAPID アイデンティティへアクセスできなくなります。 |
ADMIN_USER_IDS | 任意。/admin ダッシュボードへアクセスできる Supabase ユーザー UUID をカンマ区切りで指定。 |
# Generate VAPID_KEY_ENCRYPTION_KEY
node -e "console.log(require('node:crypto').randomBytes(32).toString('base64'))"
# Generate CRON_SECRET
node -e "console.log(require('node:crypto').randomBytes(24).toString('base64url'))"4. デプロイ
Vercel: リポジトリを連携し、ステップ 3 の環境変数を設定して deploy。同梱の vercel.ts が cron スケジュールを自動で配線します。
自前ホスト: 以下でビルド・起動:
pnpm build
pnpm start # default :3000Vercel 以外では /api/cron/dispatch を自分でスケジュールする必要があります — ステップ 5 を参照。
5. cron ワーカーをスケジュール
cron ワーカーは予約通知の dispatch、Webhook 配信の再試行、レート制限テーブルの掃除を行います。約 1 分ごとに動かしてください。認証は CRON_SECRET を Bearer トークンとして渡します。
Vercel の場合: 同梱の vercel.ts がこのスケジュールを宣言しているので、そのままで動作。
Vercel 以外: GitHub Actions、fly.io machines、crontab + curl、Kubernetes CronJob など、お好みのスケジューラで。crontab の例:
* * * * * curl -fsS -H "Authorization: Bearer $CRON_SECRET" \
https://your-nesh.example.com/api/cron/dispatch6. 最初のユーザーと管理者
UI からサインアップしてアカウントを作成。Supabase Studio (もしくは SQL) でユーザー UUID を取得し、ADMIN_USER_IDS に追加すると /admin ダッシュボードが解放されます。
運用上の注意
- プロジェクト作成後は
VAPID_KEY_ENCRYPTION_KEYを変更しないでください。DB と一緒にバックアップを取りましょう。ローテーションには projects.vapid_private_key の再暗号化が必要です。 - 通知のファンアウトは送信ルートのプロセス内で順次実行される実装です (デフォルト上限の 5,000 購読者/プロジェクト程度を想定)。それ以上に伸ばす場合はキューに切り出すことを検討してください。
- イベント追跡 (shown / clicked) は仕様上、認証なしの公開エンドポイントです (ビーコンは資格情報を送りません)。IP 単位でレート制限済み。
- サーバーエラーは
error_logsに永続化され /admin に出ます。デプロイのデバッグに便利。