Crowi

セルフホスティング (自前の runner プロジェクト)

自前の runner プロジェクトで api イメージを作り、web フロントエンドまで結線して本番デプロイする手順

このページは、公式の full / slim イメージでは要件を満たせない場合に、自前の runner プロジェクトを作って本番デプロイする運用者向けの手順です。具体的には 次のようなケースを想定しています。

  • 公式イメージに同梱されない独自プラグイン(社内 npm レジストリのものなど)を 読み込みたい
  • ストレージ / 検索 / メール / レンダラのドライバを任意の組み合わせで固定したい
  • イメージの依存を必要最小限に絞り、ビルドパイプラインを自社で管理したい

公開されている full / slim イメージで足りる場合は、公式イメージで動かす だけで十分です。ここではその一歩先、runner プロジェクトを一から作る場合を 扱います。

Crowi の本番構成は「api(Hono)+ web(Next.js)+ MongoDB(+ 任意で Redis / Elasticsearch / S3)」です。@crowi/api はプラグインを同梱しないため、 どのドライバを使うかは runner プロジェクトが所有します。この前提は 設定 の「プラグインの解決方法」で詳しく説明しています。

全体像

web と api は別コンテナで、いずれもコンテナ内ポート 3000 で待ち受けます。ブラウザにはその前段に置いた リバースプロキシの 1 オリジンだけを見せ、/api・/files とリアルタイムの WebSocket を api へ振り分けます。 プロキシの設定例 (Caddy / nginx)、WebSocket の Upgrade 透過、アップロードの body size 上限は デプロイ構成 にまとめてあります。本番投入前に必ず読んでください。

runner プロジェクトを作る

プロジェクトディレクトリと package.json

任意の場所にディレクトリを作り、@crowi/api と使いたいプラグインを依存に 宣言します。下記は S3 ストレージ + Elasticsearch 検索 + PlantUML/KaTeX レンダラを使う例です。

package.json
{
  "name": "my-crowi-runner",
  "private": true,
  "type": "module",
  "scripts": {
    "start": "crowi-api"
  },
  "dependencies": {
    "@crowi/api": "2.0.0-alpha.17",
    "@crowi/plugin-storage-aws-s3": "2.0.0-alpha.17",
    "@crowi/plugin-search-elasticsearch": "2.0.0-alpha.17",
    "@crowi/plugin-renderer-plantuml": "2.0.0-alpha.17",
    "@crowi/plugin-renderer-katex": "2.0.0-alpha.17"
  }
}

バージョンは実際に使う Crowi のリリースに揃えてください。@crowi/api と @crowi/plugin-* は同一バージョンで足並みを揃えるのが安全です(リリースは linked group として同時にバージョンが上がります)。

暗黙のデフォルトプラグイン(@crowi/plugin-storage-local / @crowi/plugin-search-mongo / @crowi/plugin-mail-smtp)は宣言しなくても 読み込まれます。ローカルストレージ + MongoDB 検索 + SMTP のままでよければ、 @crowi/api だけを依存にすれば動きます。slim 相当を自前で組む形です。

crowi.config.json

読み込むプラグインと有効ドライバを宣言します。プラグインごとの設定値(バケット名 や認証情報など)はここには書かず、起動後に管理画面(/admin/plugins)から 設定します。

crowi.config.json
{
  "plugins": [
    "@crowi/plugin-storage-aws-s3",
    "@crowi/plugin-search-elasticsearch",
    "@crowi/plugin-renderer-plantuml",
    "@crowi/plugin-renderer-katex"
  ],
  "storage": { "driver": "s3" },
  "search": { "driver": "elasticsearch" }
}

フィールドの意味とドライバ名の対応は crowi.config.json を参照してください。

.env

api が起動時に読む環境変数を用意します。MONGO_URI と SECRET_TOKEN は 必須です(SECRET_TOKEN が未設定・空・空白のみ・既知の placeholder の 場合、api は起動しません)。本番では CROWI_ENCRYPTION_KEY も必ず設定 してください。

.env
MONGO_URI=mongodb://mongodb:27017/crowi
REDIS_URL=redis://redis:6379          # 複数レプリカ運用では必須
CROWI_ENCRYPTION_KEY=...               # openssl rand -base64 32
SECRET_TOKEN=...                       # openssl rand -base64 32、全レプリカで同じ値

各変数の意味は 環境変数 を参照してください。

ローカルで起動確認

依存をインストールし、runner プロジェクトのディレクトリを作業ディレクトリにして 起動します。

pnpm install   # または npm install
pnpm start     # = crowi-api。api がコンテナ内ポート 3000 で待ち受ける

api は起動時にこのプロジェクトの node_modules/ からプラグインを解決します。 プラグインを追加・削除しても api の再ビルドは不要です。

api の Docker イメージを作る

runner プロジェクトをそのままイメージ化します。公式イメージと同じく、 WORKDIR を runner プロジェクトのルートにし、 node_modules/@crowi/api/dist/app.js を実行します。

Dockerfile
FROM node:24-bookworm-slim
WORKDIR /app

# runner プロジェクトのマニフェストを先に入れて依存だけ先に解決(キャッシュ効率)
COPY package.json pnpm-lock.yaml* package-lock.json* ./
RUN corepack enable && pnpm install --prod || npm install --omit=dev

# 設定とソースを配置
COPY crowi.config.json ./
# .env はイメージに焼き込まず、コンテナ env / env_file で渡すことを推奨

ENV NODE_ENV=production
ENV PORT=3000
EXPOSE 3000
CMD ["node", "node_modules/@crowi/api/dist/app.js"]

社内レジストリのプラグインを使う場合は、pnpm install の前に .npmrc を COPY してレジストリ / 認証を設定してください。crowi.config.json を コンテナ外からマウントすれば、再ビルドなしでドライバ選択を差し替えられます (公式 compose もこの方式です)。

機密値(CROWI_ENCRYPTION_KEY / SECRET_TOKEN など)はイメージに 焼き込まず、デプロイ時のコンテナ環境変数か env_file で渡します。

web フロントエンドを結線する

web は公開されている crowi/crowi-web イメージをそのまま使います。これは描画専任の Next サーバで、絶対 API URL を一切焼き込みません。ブラウザは自分のオリジンの相対パス /api・/files を叩き、 WebSocket URL は window.location から導出します。そのため 1 つのイメージがどの api を宛先にしても動きますが、それらのパスを api へ振り分ける前段のリバースプロキシが必要です。

web サーバを直接公開して /api の proxy を任せないでください。web に内蔵の proxy は宛先をビルド時に焼き込む (CROWI_API_URL を実行時に読まない) ため、 直接公開した web サーバはビルド時の既定の宛先に proxy してしまい、api に届きません。 前段にリバースプロキシを置いてください。

推奨構成は web と api の前段に同一オリジン + リバースプロキシを置く形です。 プロキシの振り分け(/api・/files、およびリアルタイムの /collab・/presence・ /notifications の WebSocket アップグレード)の Caddy / nginx 最小例と、 クロスオリジン・Vercel / PaaS の各バリエーションは デプロイ構成 にまとめてあります。本番投入前に必ず読んでください。

起動順とヘルスチェック

ミドルウェアを先に起動

MongoDB(必要に応じて Redis / Elasticsearch)を起動し、到達可能にします。

マイグレーションを適用

v1 からのアップグレードや preflight マイグレーションがある場合は、api 起動前に 適用します。詳細は v1 からの移行 を参照してください。

api → web の順で起動

api を起動して /api/app/info が 200 を返すことを確認してから、web を起動します。

複数レプリカで運用する場合は、REDIS_URL と CROWI_MULTI_INSTANCE の 扱いが変わります。SECRET_TOKEN は単一・複数レプリカのどちらでも必須 ですが、複数レプリカでは 全レプリカを完全に同じ値 にする必要が あります。値を変更する(ローテーションする)場合は、旧レプリカを drain・停止してから新しい値の新版レプリカを起動する drain-first の手順を踏んでください。新旧レプリカが異なる値で同時に 稼働する期間を作ってはいけません。環境変数 と リアルタイム共同編集の運用 を参照してください。

次のステップ

On this page