本番の設置

運用向け単一サーバー設置

永続 S3 を使うサーバーの ready 応答を確認します

作業内容

一台の Linux に公開イメージを digest で固定して設置し、/readyz と /docs の応答を確認します。永続 AWS S3 を使います。この Compose 経路は独自 endpoint を指定できません。他の S3 互換 endpoint が必要なら Kubernetes 設置に従います。高可用性が必要なら Kubernetesを選びます。

準備

項目要件
OSLinux。x86_64 と arm64 の両方に対応します
Docker Engine28 以上
Docker Compose2.24.6 以上
ディスクDocker データルートが XFS で、prjquota 付きで mount されていること。preflight はこれを確認しません。満たさなければ deploy で scheduler の quota 検査が失敗し、設置が止まります。ext4 サーバーでは先に XFS ディスクの準備を完了します。Docker Desktop では使えません
時刻NTP 同期。再起動後に Docker が自動起動すること
ツールgit、jq、curl、openssl、Bun 1.3.14、Docker Buildx プラグイン。Docker daemon にアクセスできるアカウント
object store永続 AWS S3 bucket。Compose test-ops は AWS S3 のみに対応し、独自 endpoint は指定できません。bucket の準備で保護契約と権限を確認します
外部ghcr.io と Docker Hub からイメージを取得できること。パッケージはログイン不要です。セッションは api.anthropic.com と github.com にアクセスします

設置にはリポジトリ checkout が必要です。compose ファイルと scripts/test-ops.sh を checkout から読むためです。イメージは checkout でビルドしません。

手順

1. バージョンとソースの固定

現在の設定文書・モデル接続・秘密 key 契約に対応する公開タグを、変更履歴と照合して選びます。次の二つの placeholder を、パッケージ契約で得た実際のタグと、同じソース commit に置き換えます。イメージの main タグは Git タグではないため、checkout 値と同じとは考えないでください。

TAG='<published-image-tag>'
SOURCE_REF='<matching-source-commit-or-release-tag>'
for app in control-host worker egress-proxy; do
  echo "$app $(docker buildx imagetools inspect "ghcr.io/jeongjaesoon/werft-$app:$TAG" --format '{{.Manifest.Digest}}')"
done

三つのイメージ取得がすべて成功し、digest が返ってから進みます。

git clone https://github.com/JeongJaeSoon/werft.git
cd werft
git checkout "$SOURCE_REF"
bun install --frozen-lockfile

checkout は選んだ release の commit で、依存関係のインストールが成功している必要があります。release ファイルは checkout 外に保存し、clean checkout 条件を維持します。

2. 秘密情報と設定文書

秘密の値はリポジトリ外の env ファイルだけに置きます。運用者だけが読める必要があります。group や other に権限があるとスクリプトが拒否します。

sudo mkdir -p /etc/werft
sudo install -m 600 -o "$USER" infra/test-ops.env.example /etc/werft/test-ops.env
sudo install -d -m 700 -o "$USER" /var/lib/werft/test-ops

エディターで /etc/werft/test-ops.env を開き、次を設定します。sed -i のように一時ファイルを作るツールは /etc/werft で Permission denied となるため、その場で書き込むエディターを使います。

変数値
POSTGRES_PASSWORDランダムな値。英字、数字、. _ ~ - だけを使います
EGRESS_AUTHORIZER_TOKEN32 文字以上のランダムな値
PLATFORM_SECRET_KEYopenssl rand -hex 32 の 64 文字 hex。失うと保存した資格情報を読めなくなります
BOOTSTRAP_TOKENコメントのままにします。最初の owner を作るトークンは API が生成し、手順 4 の deploy の後に scripts/test-ops.sh bootstrap-token が一度だけ表示します。固定値が必要なら、コメントを外して 32–256 文字のランダムな値を設定します。その場合、このコマンドはトークンを出力しません
CONSOLE_ORIGINコンソールから GitHub App を作るときに必要な、ブラウザのコンソール origin(scheme://host[:port])。なければ「GitHub で作成」ボタンは無効です。Slack アカウント連携のリダイレクトと Slack のイベントアドレスもこの値から計算します(なければ Slack 連携は無効です)。env の例にはこの行がないため、自分で追加します。SSH tunnel で開くなら http://127.0.0.1:<tunnel port> を指定します。設置後の追加・変更は start ではなく TEST_OPS_OBJECT_STORE=s3 scripts/test-ops.sh upgrade /var/lib/werft/test-ops/current.json で現在の release を再適用して反映します

例の LocalStack 値を運用 S3 の値に変更します。秘密をコマンドラインやログへ出力しないでください。

変数運用環境の値
EXECUTION_INSTALLATION_ID他の環境と重複しない id。デプロイ後に変更しません
PLATFORM_SETTINGS_DOCUMENT/etc/werft/settings.json
EXECUTION_WORKSPACE_QUOTAon
AWS_REGION、S3_BUCKET準備した AWS bucket の region と名前。独自 endpoint は未対応です
AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEYbucket の最小権限の API 資格情報
EGRESS_CREDENTIAL_ALLOWLISTprovider・Git host と <bucket>.s3.<region>.amazonaws.com:443。ドットを含む bucket 名では s3.<region>.amazonaws.com:443
EGRESS_CREDENTIAL_PRIVATE_ALLOWLIST空の値。localstack:4566 を削除します

モデル key は設置後にコンソールのモデル接続で入力するため、v0.1.2 タグでは ANTHROPIC_API_KEY を空のままにします。ただし v0.1.0 タグの checkout では compose がこれを必須とし、空のままだと preflight が exit 1 で終わります。そのバージョンでは env ファイルにモデル key (または後でコンソールで差し替える仮の値) を入れます。空を許す変更は JeongJaeSoon/werft#1262 で入り、v0.1.2 がそれを含む最初の公開リリースです。PLATFORM_SECRET_KEY を失うと保存した資格情報を読めなくなるため、別途安全にバックアップします。

設定文書は /etc/werft/settings.json に置き、セッションが使う GitHub リポジトリを書きます。秘密情報は含みません。リポジトリ URL だけを実際の値に変更します。例は公開リポジトリ用です。リポジトリ項目には "auth": { "kind": "github_app" } が必要です。なければ import 時にそのリポジトリが除外され、preflight が設置を止めます。非公開リポジトリの認証は API サーバー文書に従います。

migrate コンテナが読む必要があるため、ファイルは 0644 にします。先に空のファイルを作り、エディターで次の内容を入れます。

sudo install -m 644 -o "$USER" /dev/null /etc/werft/settings.json
{
  "version": 1,
  "connections": {},
  "repositories": {
    "sample-app": {
      "url": "https://github.com/<owner>/<repo>.git",
      "branch": "main",
      "auth": { "kind": "github_app" }
    }
  },
  "mcp_servers": {}
}

リポジトリ URL は実際に使う公開リポジトリに変更します。非公開リポジトリの GitHub App は手順 2 の入力一覧の CONSOLE_ORIGINを準備してから、設置したコンソールで構成します。ファイルは秘密を含まず、migrate が読める必要があります。

3. release 入力の生成

選んだ TAG を保持したシェルで実行します。DEPLOYMENT_DIR は checkout 外の環境別ディレクトリです。

DEPLOYMENT_DIR=/var/lib/werft/test-ops
SETTINGS_DIGEST="$(bun run scripts/lib/test-ops.ts settings-digest /etc/werft/settings.json)"
digest() { docker buildx imagetools inspect "ghcr.io/jeongjaesoon/werft-$1:$TAG" --format '{{.Manifest.Digest}}'; }
jq -n \
  --arg commit "$(git rev-parse HEAD)" \
  --arg control "ghcr.io/jeongjaesoon/werft-control-host@$(digest control-host)" \
  --arg worker "ghcr.io/jeongjaesoon/werft-worker@$(digest worker)" \
  --arg egress "ghcr.io/jeongjaesoon/werft-egress-proxy@$(digest egress-proxy)" \
  --arg settings "$SETTINGS_DIGEST" \
  '{source_commit: $commit,
    images: {control_host: $control, worker: $worker, egress_proxy: $egress},
    settings_digest: $settings}' > "$DEPLOYMENT_DIR/release.json"

三つのイメージ digest がすべて空でないことを確認します。

4. S3 を明示して検査・設置

TEST_OPS_OBJECT_STORE=s3 scripts/test-ops.sh preflight "$DEPLOYMENT_DIR/release.json"
TEST_OPS_OBJECT_STORE=s3 scripts/test-ops.sh deploy "$DEPLOYMENT_DIR/release.json"

preflight は bucket の保護設定と scratch version の書き込み・hold・読み取り・hold 解除・削除を検査します。quota は deploy 時に scheduler が検査します。両方成功し、サービスが healthy になる必要があります。object store 方式は最初の deploy 後に変更できません。

env ファイルに BOOTSTRAP_TOKEN を設定していない場合は、deploy の後で最初の owner のトークンを受け取ります。トークンはコンテナログではなく、API コンテナ内の owner 専用ファイルに置かれ、このコマンドが表示と同時に削除します。

scripts/test-ops.sh bootstrap-token

表示された値を /bootstrap に貼り付けます(最初の owner と key)。同じコマンドを再実行してもトークンは出力されず、終了コード 1 で終わります。値を控え損ね、まだ owner がいない場合は、scripts/test-ops.sh stop と start で API を再起動すると新しいトークンが作られます(古いトークンは無効になります)。すでに BOOTSTRAP_TOKEN を設定している環境は変わりません。

確認

scripts/test-ops.sh status
curl --max-time 10 -fsS -w '\n%{http_code}\n' http://127.0.0.1:3000/readyz
curl --max-time 10 -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3000/docs

ready の本文と 200、docs 200、各サービスの healthy を確認します。PostgreSQL は loopback だけで待ち受け、Docker TCP socket は外部から到達できない必要があります。運用 AWS S3 設置全体とデータがある状態での復元は、このチュートリアルでは実行確認していません。LocalStack の空 checkpoint の照合と ready 200 で代替しません。

よくある問題

最初の deploy が失敗すると、起動したコンテナが残り、current.json がないため stop は使えません。失敗ログで quota・network・Secret などの原因を確認し、今回の project 名を確認してから次のように停止・削除します。-v は付けません。

PROJECT='<this-installation-project>'
printf '%s\n' '{"services":{"x":{"image":"alpine:3"}},"networks":{"default":{}}}' \
  | docker compose --project-name "$PROJECT" -f - down --remove-orphans

原因を直し、同じ release ファイルと同じ環境で deploy を再実行します。成功済みの環境を再起動するときは start を使います。

quota エラーは XFS の準備、bucket の保護・権限エラーは bucket の準備を確認します。env 権限エラーは手順 2 のファイル mode、settings digest エラーは手順 3 の digest・release 入力生成を確認します。最初の deploy が失敗しても、正常デプロイの状態ファイルがあるとは考えないでください。

元に戻す

正常な環境は停止・再起動でデータを保持します。最初の deploy の失敗では、原因とこの project が作ったリソースを先に調べます。reset や volume 削除を既定の後片付けにしないでください。必要なデータがないことを確認した環境だけ、別の削除手順に従います。

次に読む

アクセス経路 → 最初の owner と key → モデル接続。運用開始前にバックアップと復元を設定します。

以前の URL

以前の節から現在の文書を探す

運用向け単一サーバー設置

XFS ディスクの準備

配布パッケージ契約

自分の registry 用イメージのビルド

最初の owner と利用者 key の発行

モデル接続とプロファイルの設定

Compose の停止・再起動・削除

利用者アクセス経路の設定

checkpoint bucket の準備

バックアップと復元訓練

このページ