# インストール

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

Source: https://nodaro.ai/ja/docs/self-hosting/install

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

## 1. クローンして設定する
```bash
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 スタック用のサンプルをコピーします。

```bash
cp .env.community.example .env
```

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

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

```bash
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` サービスに追加する必要があります。[設定](https://nodaro.ai/docs/self-hosting/configuration)には、すべての変数と、そのうち `.env` で設定できるものが載っています。

## 2. 内部シークレットを生成する
Nodaro は、独自のシークレットを 2 つ使います。

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

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

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

```bash
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` を設定し、マイグレーションを自分で適用します。[データベース](https://nodaro.ai/docs/self-hosting/database#apply-the-migrations-to-a-managed-project)を参照してください。

## 4. オブジェクトストレージを設定する
### 同梱の MinIO
設定は不要です。Compose ファイルには、次のデフォルト値で MinIO が含まれています。

| 変数 | デフォルト |
| --- | --- |
| `R2_ENDPOINT` | `http://minio:9000` |
| `R2_FORCE_PATH_STYLE` | `true` |
| `R2_BUCKET_NAME` | `nodaro-assets` |
| `R2_PUBLIC_URL` | `http://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 スタックでは、エンドポイントとアドレス指定の方式も設定します。

```bash
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. スタックを起動する
```bash
docker compose -f docker-compose.community.yml up
```

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

```text
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` のようにします。すべてのタグは、[アップデート](https://nodaro.ai/docs/self-hosting/updating)に載っています。

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

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

Community エディションのユーザーには、制限がありません。クレジットの台帳も管理パネルもありません。Business エディションでは、次に最初の管理者を昇格させます。[最初のユーザーと管理者](https://nodaro.ai/docs/self-hosting/first-admin)を参照してください。

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

### 新しい認証キーを発行する
```bash
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` を設定します。

```bash
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](https://nodaro.ai/docs/self-hosting/reverse-proxy) を参照してください。

### 誰がアカウントを登録できるかを決める
Community エディションは、1 人の運用者での利用を想定しています。登録ページにアクセスできる人は誰でもアカウントを作成でき、ログインしているユーザーは全員がプロバイダーキーを変更できます。Business エディションでは、プロバイダーキーを管理できるのは管理者だけです。[エディションとサーフェスプロファイル](https://nodaro.ai/docs/self-hosting/editions-and-profiles)を参照してください。

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

## Frequently asked questions

### Compose スタックでは、どの .env ファイルから始めればよいですか？

.env.community.example を .env にコピーします。このファイルには、Compose スタックが使う値だけが載っています。より大きな .env.example は、Compose スタック以外で動かす環境向けのリファレンスです。そのプレースホルダーの Supabase の値は、動作するデフォルト値を上書きしてしまいます。

### INTERNAL_ORCHESTRATOR_SECRET と NODARO_ENCRYPTION_KEY は、自分で生成する必要がありますか？

同梱の Compose スタックでは不要です。起動時に両方を生成し、暗号化キーは app-data ボリュームに保存します。独自のオーケストレーションで動かす場合は、両方に 32 バイトのランダムな値を 16 進数で設定します。たとえば openssl rand -hex 32 で生成できます。

### 同梱の MinIO の代わりに Cloudflare R2 を使うには、どうすればよいですか？

R2_ACCOUNT_ID、R2_ACCESS_KEY_ID、R2_SECRET_ACCESS_KEY、R2_BUCKET_NAME、R2_PUBLIC_URL を設定します。Compose スタックでは、さらに R2_ENDPOINT に自分のアカウントの r2.cloudflarestorage.com のエンドポイントを、R2_FORCE_PATH_STYLE に false を設定します。空の値は、MinIO のデフォルト値にフォールバックするためです。

### インストールが正しく起動したかどうかは、どうすればわかりますか？

ログに server listening on http://0.0.0.0:9000 という行が出るのを待ってから、http://localhost:3000/setup を開きます。プロバイダーキーを追加するまでは、プロバイダーキー以外のすべてのカードが緑になっているはずです。

### 環境をネットワークに公開する前に、何を変更する必要がありますか？

node tools/generate-selfhost-keys.mjs で新しい認証キーを発行し、新しい POSTGRES_PASSWORD とそれに合わせた DATABASE_URL、新しい MinIO の認証情報を設定します。さらに、PUBLIC_URL を https のアドレスにして、前段にリバースプロキシを置きます。
