Nodaro ドキュメント
ドキュメントノードリファレンスモデルAI エージェント(MCP)開発者向けセルフホスティングリサーチ

インストール

Nodaro のセルフホスティング環境を順を追ってインストールします。リポジトリのクローン、.env、シークレット、マイグレーション、オブジェクトストレージの設定から、スタックの起動、ログイン、セキュリティの強化までを説明します。

このガイドでは、Community エディションを 1 ステップずつ、それぞれの理由とともにインストールします。流れはクイックスタートと同じで、マネージドサービス、シークレット、ストレージ、セキュリティの強化についての説明が加わります。同梱の Compose スタックでは、ほとんどのステップで操作は必要ありません。何が行われるのか、あとで何を変更すればよいのかを知るために読んでください。

1. クローンして設定する

git clone https://github.com/nodaroai/app.nodaro.ai.git nodaro
cd nodaro

Community エディションの Compose スタックでは、.env は任意です。Compose ファイルには、動作するデフォルト値とともに、Supabase、MinIO、Redis が同梱されています。.env を作成するのは、プロバイダーキーを追加する、公開 URL を変更する、自分のマネージドサービスを Nodaro の接続先にする、といった場合だけです。

.env を作成するには、Compose スタック用のサンプルをコピーします。

cp .env.community.example .env

Compose スタックでは .env.example をコピーしないでください

.env.example は、Compose スタック以外で動かす環境向けのリファレンスです。SUPABASE_URL=https://YOUR-PROJECT.supabase.co などのプレースホルダーの値が Compose のデフォルト値を上書きし、同梱のデータベースが動かなくなります。

よく設定する値は次のとおりです。

PUBLIC_URL=http://localhost:3000        # your install's public address

# Only with a managed Supabase project instead of the bundled one:
SUPABASE_URL=https://YOUR-PROJECT.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
SUPABASE_ANON_KEY=eyJ...

# At least one model provider:
KIE_API_KEY=
REPLICATE_API_TOKEN=
ANTHROPIC_API_KEY=
ELEVENLABS_API_KEY=

Compose ファイルがアプリに渡す変数は、決まったリストに限られます。リストにない変数は、docker-compose.community.yml の nodaro サービスに追加する必要があります。設定には、すべての変数と、そのうち .env で設定できるものが載っています。

2. 内部シークレットを生成する

Nodaro は、独自のシークレットを 2 つ使います。

変数役割
INTERNAL_ORCHESTRATOR_SECRETNodaro コンテナ内で、オーケストレーターを API に対して認証します。32 文字以上です。
NODARO_ENCRYPTION_KEY保存された認証情報を暗号化する、64 文字の 16 進数のキーです。対象は、/setup で貼り付けたプロバイダーキー、SNS のログイン用トークン、ユーザーが Webhook 出力(Webhook Output)用に保存した HTTP の認証情報です。以前の名前の SOCIAL_ENCRYPTION_KEY も、引き続き使えます。

同梱の Compose スタックでは、このステップは不要です。コンテナが、起動時に両方を生成します。暗号化キーは app-data ボリュームの /data/nodaro/encryption-key に保存され、以降の起動のたびに再利用されます。このボリュームは、データベースと一緒にバックアップしてください。

ホスティングプラットフォームや個別のコンテナなど、独自のオーケストレーションで動かす場合は、両方を自分で設定します。

echo "INTERNAL_ORCHESTRATOR_SECRET=$(openssl rand -hex 32)" >> .env
echo "NODARO_ENCRYPTION_KEY=$(openssl rand -hex 32)" >> .env

NODARO_ENCRYPTION_KEY は安全に保管し、決して変更しないでください。別のキーでは、このキーで暗号化したものがすべて読み取れなくなります。

3. データベースのマイグレーションを適用する

同梱のスタックでは、これは自動で行われます。アプリは起動時に、API が起動する前に supabase/migrations/ 内のファイルを適用します。適用したファイルは記録され、次回の起動時にはスキップされます。マイグレーションが途中までしか適用されていないデータベースに対しては起動を拒否し、失敗したファイルの名前をログに出力します。

マネージドの Supabase プロジェクトを使う場合は、RUN_MIGRATIONS_ON_BOOT=false を設定し、マイグレーションを自分で適用します。データベースを参照してください。

4. オブジェクトストレージを設定する

同梱の MinIO

設定は不要です。Compose ファイルには、次のデフォルト値で MinIO が含まれています。

変数デフォルト
R2_ENDPOINThttp://minio:9000
R2_FORCE_PATH_STYLEtrue
R2_BUCKET_NAMEnodaro-assets
R2_PUBLIC_URLhttp://localhost:3000/storage/nodaro-assets

アプリの Web サーバーがメディアを /storage/ の下で配信するため、ブラウザーとバックエンドは同じ URL を読み込みます。バケットは初回の起動時に、公開読み取りのアクセス権付きで作成されます。メディアは、minio-data ボリュームに保存されます。

環境を実際のドメインで提供する場合は、R2_PUBLIC_URL=https://<your-domain>/storage/nodaro-assets を設定します。スタックを公開する前に、MinIO の認証情報である R2_ACCESS_KEY_ID と R2_SECRET_ACCESS_KEY を変更してください。

Cloudflare R2

エグレス料金がかからないため、本番のデプロイには Cloudflare R2 をおすすめします。

  1. nodaro-assets などのバケットを作成し、R2_BUCKET_NAME にその名前を設定します。
  2. バケットの Settings で、公開用の r2.dev アドレスを有効にするか、カスタムドメインを割り当てます。その URL を、R2_PUBLIC_URL にコピーします。
  3. Manage R2 API tokens で、このバケットに対する Object Read & Write の権限を持つトークンを作成します。その値を、R2_ACCESS_KEY_ID、R2_SECRET_ACCESS_KEY、R2_ACCOUNT_ID にコピーします。
  4. Compose スタックでは、エンドポイントとアドレス指定の方式も設定します。
R2_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
R2_FORCE_PATH_STYLE=false

この 2 つは、空の値にしてもクリアされません。Compose ファイルは、空の変数に MinIO のデフォルト値を使うためです。Compose スタック以外では、どちらも設定しないでください。エンドポイントは、R2_ACCOUNT_ID から導き出されます。

起動時に、ログに [storage] failed to create bucket という行が 1 つ出力されますが、問題はありません。R2 のトークンはバケットを作成できず、バケットはすでに存在しているためです。

そのほかの S3 互換ストレージ

AWS S3、Backblaze B2、DigitalOcean Spaces、Supabase Storage、または自分で運用する MinIO の場合は、次のように設定します。

  • R2_ENDPOINT に、ストレージの S3 API の URL を設定します。
  • セルフホスティングのサーバーの多くでは、R2_FORCE_PATH_STYLE=true を設定します。
  • R2_PUBLIC_URL に、バケットの公開 URL を設定します。
  • Cloudflare R2 と MinIO 以外では、R2_REGION にストレージのリージョンを設定します。

R2_REGION のデフォルトは auto です。これは Cloudflare R2 独自の値で、MinIO では無視されます。AWS、DigitalOcean Spaces(nyc3、fra1 など)、ローカルの Supabase(local)は、auto を受け付けません。その場合、すべてのリクエストが、リージョンには触れない認可エラーまたはエンドポイントのエラーで失敗します。

メディアを公開で読み取れるようにする

方法は 2 つあり、ほとんどの環境では 1 つ目だけで十分です。

  1. バケットポリシー:これがデフォルトです。R2_ENDPOINT を独自に設定している場合、アプリは起動時にバケットを作成し、匿名での読み取りを許可するポリシーを付与します。Cloudflare R2 では不要です。公開バケットの設定で対応できます。
  2. STORAGE_OBJECT_ACL によるオブジェクトごとの ACL:バケットポリシーを受け付けないストレージ向けです。よくある例は DigitalOcean Spaces で、1 つのバケットに限定したキーからのバケットポリシーを受け付けません。STORAGE_OBJECT_ACL=public-read を設定すると、アプリが書き込むすべてのオブジェクトに、その ACL が付きます。

2 つ目の方法が必要な場合を除き、STORAGE_OBJECT_ACL は空のままにします。空の場合、ACL ヘッダーは送信されません。キーに ACL を設定する権限がないストレージでこの変数を設定すると、すべてのアップロードが失敗します。Nodaro が受け付けるのは、標準の既定 ACL(canned ACL)である private、public-read、public-read-write、authenticated-read、aws-exec-read、bucket-owner-read、bucket-owner-full-control です。それ以外の値は、起動時に拒否します。

5. スタックを起動する

docker compose -f docker-compose.community.yml up

アプリのイメージ ghcr.io/nodaroai/nodaro-community は、ビルド済みのものがプルされます。初回の起動では、5〜10 分かけてコンパイルする代わりに、約 2.4 GB をダウンロードします。2 回目以降の起動は、数秒で終わります。Redis と nodaro サービスのログが並んで表示されます。次の行が表示されたら、API は稼働しています。

nodaro-1  | server listening on http://0.0.0.0:9000

同じコンテナ内の Web サーバーが、これをポート 3000 で提供します。http://localhost:3000 を開きます。

latest は main ブランチに追従します。再現可能な環境にするためにリリースを固定するには、.env で NODARO_IMAGE を設定します。たとえば NODARO_IMAGE=ghcr.io/nodaroai/nodaro-community:v1.23.0 のようにします。すべてのタグは、アップデートに載っています。

代わりにソースからイメージをビルドするには、docker compose -f docker-compose.community.yml build を実行します。これが必要なのは、コードを変更したときだけです。公開 URL、ポート、ドメイン、Supabase のキーはコンテナの起動時に読み込まれるため、公開されているイメージのままでも、再起動すれば変更が反映されます。

6. 初めてログインする

アプリで、メールアドレスとパスワードを使ってアカウントを登録します。ユーザーは認証サービスが作成し、ユーザーのプロフィールは Nodaro が自動で作成します。同梱のスタックでは、確認メールは送信されません。

Community エディションのユーザーには、制限がありません。クレジットの台帳も管理パネルもありません。Business エディションでは、次に最初の管理者を昇格させます。最初のユーザーと管理者を参照してください。

公開する前に環境のセキュリティを強化する

Compose のデフォルト値はローカルでの利用を想定したもので、本質的に誰でも知ることができる値です。ほかの人が環境にアクセスできるようにする前に、次の作業を行います。

新しい認証キーを発行する

node tools/generate-selfhost-keys.mjs >> .env

このスクリプトは、SUPABASE_JWT_SECRET、SUPABASE_ANON_KEY、SUPABASE_SERVICE_ROLE_KEY を出力します。2 つのキーはシークレットで署名されるため、3 つとも同じ実行で生成したものを使う必要があります。anon キーを変更しても、再ビルドは不要です。コンテナが、実行時に /config.js でブラウザーに渡すためです。

新しいパスワードを設定する

POSTGRES_PASSWORD と、それに合わせた DATABASE_URL を設定します。

POSTGRES_PASSWORD=<new-password>
DATABASE_URL=postgres://postgres:<new-password>@db:5432/postgres

MinIO の新しい認証情報も、R2_ACCESS_KEY_ID と R2_SECRET_ACCESS_KEY に設定します。

データベースが内部ロールのパスワードを POSTGRES_PASSWORD に合わせるのは、初回の起動時だけです。db-data ボリュームがすでにある場合は、ボリュームを削除する(データも削除されます)か、supabase_admin としてロールのパスワードを手動で変更します。

HTTPS で提供する

PUBLIC_URL に実際の https:// のアドレスを設定し、スタックの前段にリバースプロキシを置きます。リバースプロキシと HTTPS を参照してください。

誰がアカウントを登録できるかを決める

Community エディションは、1 人の運用者での利用を想定しています。登録ページにアクセスできる人は誰でもアカウントを作成でき、ログインしているユーザーは全員がプロバイダーキーを変更できます。Business エディションでは、プロバイダーキーを管理できるのは管理者だけです。エディションとサーフェスプロファイルを参照してください。

すべての変更を docker compose -f docker-compose.community.yml up -d で反映し、/setup を確認します。

よくある質問

最終更新

目次