サーバー
Paprika を動かすサーバー側(Hub・Worker)のセットアップ・運用ガイド。 操作する側(SDK)の使い方は はじめに へ。
3 つの構成パターン
サーバーをどう配置するか。用途に合わせて選びます(後で組み替えも可能、例: A → B にスケールアップ)。
A. 1 台で全部
お試し・小〜中規模向けです。Docker 一発で redis + hub + worker(+agent) を1ホストにまとめて起動します。最も簡単です。
B. ハブ + リモート worker
並列を増やしたい・分散したいときに使います。ハブを1台、worker を別マシン N 台で WebSocket 接続します。フリート運用に向いています。
C. Hub のみ(開発)
SDK 開発や軽い検証用に Docker なしで Python から直接起動。Worker は別途・任意。
図にすると:
A. [host] redis ── hub ── worker (Chrome × N lanes)
http://localhost:8000
B. [hub-host] redis ── hub ── WebSocket ── [worker-host #1] worker
http://paprika.lan:8000 worker
── WebSocket ── [worker-host #2] worker
…
── WebSocket ── [worker-host #N] worker
C. [dev-host] python -m server --mode hub (Worker は CLI / 別 Docker / なし)
http://localhost:8000
| A. 1 台 | B. 分散 | C. Hub のみ | |
|---|---|---|---|
| 主用途 | お試し・小〜中規模 | 本番・並列を増やす | 開発・検証 |
| 必要なもの | Docker | Docker(各ホスト) | Python 3.10+ |
| 起動コマンド | docker compose up -d --build | 同上 + 各 worker で -f docker-compose-worker.yml up -d | python -m server --mode hub |
| Redis | 同梱(自動) | 同梱(自動) | 任意(無ければインメモリ) |
インストール・起動
A. 1 台で全部(Docker Compose)
git clone https://github.com/paps-jp/paprika.git
cd paprika
cp .env.example .env
docker compose up -d --build
起動後:
- 管理画面 →
http://localhost:8000(管理画面ガイド) - noVNC(Lane 0)→
http://localhost:6080/vnc_lite.html?autoconnect=1 - Swagger(HTTP API)→
http://localhost:8000/docs
前提: Docker + Docker Compose v2、Linux ホスト推奨。1 レーンあたり ~500MB–1GB RAM(既定 2 レーン)。
LLM 機能(codegen / vision-agent / page.agent)を使うときだけ OpenAI 互換の LLM エンドポイントが必要、Fetch だけなら不要。
B. ハブ + リモート worker(分散)
① ハブホスト:A と同じ手順で立ち上げる。ただし他マシンからアクセスするので .env で公開アドレスを設定:
# .env (ハブホスト)
NOVNC_PUBLIC_HOST=paprika.lan # 管理画面の noVNC リンクが指すホスト名/IP
PUBLIC_BASE_URL=http://paprika.lan:8000 # worker がアセットを POST する先
LANE_POOL=2 # ローカル worker のレーン数(不要なら 0)
② worker ホスト(追加したい台数だけ):
git clone https://github.com/paps-jp/paprika.git /opt/paprika
cd /opt/paprika && cp .env.example .env
# .env を編集:
# HUB_URL=ws://paprika.lan:8000
# NOVNC_PUBLIC_HOST=<このホストの LAN IP/DNS>
docker compose -f docker-compose-worker.yml up -d
③ 接続確認:ハブの GET /workers(管理画面の「ワーカー」タブでも可)に alive=true で現れれば OK。
C. Hub のみ(CLI/開発)
Docker を使わず Python から直接起動できます。SDK の開発や軽い検証向けです。
git clone https://github.com/paps-jp/paprika.git
cd paprika
python -m venv .venv && source .venv/bin/activate # 任意
pip install -r requirements.txt
# ハブのみ起動(最小・インメモリ)
python -m server --mode hub --host 0.0.0.0 --port 8000
# Redis 永続化付き
python -m server --mode hub --port 8000 \
--redis-url redis://localhost:6379 \
--data-dir ./data/jobs
Worker も CLI で立てる場合:
# 別ターミナルで(要: Chrome + Xvfb + noVNC = Linux)
python -m server --mode worker \
--hub-url ws://localhost:8000 \
--lane-pool 1 \
--novnc-public-host localhost --novnc-base-port 6080
--lane-pool 使用時は Chrome + Xvfb + noVNC を自前で用意する必要があります。本格運用では Docker 版が圧倒的に楽です(依存込みで一発)。主な CLI オプション:
| オプション | 対象 | 説明 |
|---|---|---|
--mode hub / worker / all | — | 動作モード(all = hub 既定) |
--host / --port | hub | バインドアドレス / ポート(既定 0.0.0.0 / 8000) |
--redis-url | hub | Redis DSN。無指定はインメモリ |
--data-dir | hub | ジョブ作業ディレクトリ(既定 ./data/jobs) |
--public-base-url | hub | worker に教える公開 URL |
--reload | hub | コード変更で自動リロード(開発用) |
--hub-url | worker | 接続先ハブの WS URL |
--lane-pool N | worker | レーン(専用 Chrome+noVNC)を N 本起動 |
--novnc-public-host / --novnc-base-port | worker | noVNC の公開ホスト / 先頭ポート |
--labels K=V,… | worker | ルーティング用ラベル |
--worker-secret | both | worker↔hub 認証の共有シークレット(両側一致) |
環境変数
Docker は .env ファイルから読み、CLI は引数で渡せます。よく使うものだけ抜粋(全項目は Hub 起動時のログでも確認できます)。
Hub 側
| 変数 | デフォルト | 説明 |
|---|---|---|
PUBLIC_BASE_URL | http://hub:8000 | worker に教える hub URL |
WORKER_SECRET | (無) | worker WS handshake 認証 |
CODEGEN_LLM_URL / CODEGEN_MODEL_NAME | — | codegen 用 LLM endpoint / model |
PAPRIKA_RUNNER_IMAGE / ..._MAX_CONCURRENT | ...:latest / 3 | runner イメージ / 同時数 |
Worker 側
| 変数 | デフォルト | 説明 |
|---|---|---|
HUB_URL | ws://paprika.lan:8000 | hub の WS URL |
WORKER_SECRET | (無) | hub と一致が必要 |
LANE_POOL | (file) | Lane (ブラウザ) 数 |
MAX_CONCURRENT | 2 | 同時ジョブ数 |
NOVNC_PUBLIC_HOST / NOVNC_BASE_PORT | localhost / 6080 | noVNC(hub 自動補正あり) |
AGENT_URL / AGENT_LLM_URL / COGAGENT_URL | — | LLM / vision エンドポイント |
PAPRIKA_WORKER_AUTO_FETCH_SOURCE | 1 | tarball 自己更新 |
paprika-client / Runner
| 変数 | デフォルト | 説明 |
|---|---|---|
PAPRIKA_HUB | http://localhost:8000 | SDK の接続先 |
PAPRIKA_JOB_ID | (無) | runner が session に紐づける parent job(自動セット) |
PAPRIKA_CLIENT_ACTION_LOG | 1 | [paprika] page.X(...) ログ |
更新・フリート運用
Hub を更新する
ssh root@paprika.lan
cd /opt/paprika && git pull && docker compose restart hub
server/worker/*.py を変えた場合も、hub 再起動で新ソース tarball が配信され、worker は次の handshake で自己更新します。pip 依存を増やしたときだけ docker compose up -d --build hub。
worker を追加する(B構成のスケールアップ)
新しい Linux ホストで B 構成の手順 ② を繰り返すだけ。Hub に自動接続されレーンが増えます。
自己更新・クローン検知・noVNC 補正
- 自己更新: worker は handshake 時に Hub と自分の version(
server+coreの全.pyの SHA-256)を比較し、不一致なら最新ソースを取得・展開して再起動。手動 VERSION bump 不要。詳細: Worker 自動配信の仕組み - クローン検知: worker ホストを複製して worker_id が重複しても、Hub が接続元 IP の差で検知し新 ID を発行。運用上は何もしなくて OK
- noVNC 補正: stale な
NOVNC_PUBLIC_HOSTを Hub が接続元 IP で書き換え、さらに hub プロキシ経由 URL に変換。外部から worker の LAN IP に直接届く必要はありません。iframe 埋め込み: VNC 埋め込み API
保存場所
収集物は Hub の Docker volume(paprika_paprika-data)/CLI なら --data-dir 配下に集約されます。
| パス | 内容 |
|---|---|
{data}/jobs/{id}/assets/ | 画像 / 動画 / etc. |
{data}/jobs/{id}/log.txt | ジョブログ |
{data}/jobs/{id}/attempts/{n}/ | codegen の各 attempt 出力 |
{data}/jobs/{id}/state/{key}.json | page.set_state() の永続データ |
{data}/jobs/hosts/ · presets/ · skills/ | ホスト別 cookie / preset / skill snippets |
アーキテクチャ(詳細)
中央集権型です。Operator / SDK → Hub → Worker(Lane = Chrome)。収集物は Hub に集約され、worker は通り道です。
| コンポーネント | 役割 | 規模 |
|---|---|---|
| Hub | API サーバ、ジョブ管理、ワーカー登録、管理 UI | 1 プロセス |
| Worker | Xvfb + Chrome の Lane を保持、CDP 経由でページ操作 | 多数の LAN ホスト |
| Lane | 独立 Chrome + noVNC viewer | 1 worker あたり 1–2 |
| Runner | codegen / rerun の使い捨て sandbox | job ごとに spawn → 削除 |
| Agent service | LLM / VLM プロキシ(任意。LLM 機能を使う場合) | 1 プロセス |
| Redis | job state の永続化(任意。無ければインメモリ) | Hub 同居 |
データの流れ: POST /jobs → Hub がキュー → WS で worker に割当 → worker が実行し POST /jobs/{id}/assets で Hub にアップロード → GET /jobs/{id}/result で取得。進捗は WS /jobs/{id}/events でライブ配信。
HTTP API
全エンドポイントはフラット(/api/ prefix なし)、認証なし(LAN 内信頼前提)。インタラクティブな一覧は Swagger UI /docs。SDK 経由が基本ですが、未ラップのレジストリ系は await cli._json("GET", "/hosts") でも叩けます。
| グループ | 主なエンドポイント |
|---|---|
| Jobs | POST /jobs · GET /jobs[/{id}] · /result · /assets.json · /cancel · DELETE · WS /jobs/{id}/events |
| Sessions | POST /sessions · action 群(/navigate /click /evaluate /set_input_files …)· /cookies · /network |
| Workers | GET /workers · WS /workers/{id}/link · POST /workers/{id}/status |
| Registries | /hosts · /profiles · /presets · /engines · /skills · /conventions · /settings |
トラブルシュート
worker が hub に繋がらない
docker logs paprika-worker-1でログ確認HUB_URLが正しいか /curl http://paprika.lan:8000/healthで到達性WORKER_SECRET不一致だとbad worker secretで切断
セッションが 404 になる
無操作が続くと reaper が回収します(既定 idle: SDK セッション 300 秒 / fetch keep_session 60 秒)。長時間動かすなら投入時に延長:
cli.session("...", idle_ttl_s=3600)
# あるいは: await page.keepalive(idle_ttl_s=600)
ジョブが queued のまま
GET /workers で alive=true な worker と空きレーンがあるか確認。全レーン埋まりで POST /jobs すると 503("fleet at capacity")が返るので、クライアントは指数バックオフを。
codegen-loop が同じスクリプトで失敗し続ける
Live パネル → コードタブで各 attempt の script.py を確認。共通の失敗パターンは conventions / skills に登録すると次回以降の prompt に注入されます。