コンテンツにスキップ
コンソール →
公式サイト →
URL を貼り付けて AI に質問 https://keelson.dev/ja/llms.txt

keelson.yaml

keelson.yaml はプロジェクトルートに置くデプロイ設定ファイルです。ランタイム、起動コマンド、環境変数、データベース、定期実行ジョブ、静的アセットなどを定義します。

デプロイ時に Keelson はこのファイルを読み、ビルドと実行環境を決めます。入門は keelson.yaml の設定を参照してください。

slug: my-app
runtime: python-slim
command: "python app.py"
db:
mode: none

フィールド型必須既定値説明
slugstringはい—アプリの識別子。アプリ作成時に使われる
workspacestring—nullプロジェクト単位の CLI 操作で使う既定ワークスペース。ワークスペースの slug を推奨。所属が 1 つだけなら CLI が自動選択するため書かなくてよい。明示した --workspace はこの値より優先し、apps list の一覧は絞り込まない
descriptionstring—nullアプリの説明(300 文字以内)
iconstring—nullコンソールでアプリのアイコンとして表示する画像。keelson.yaml のあるフォルダからの相対パス。icon を参照
typestring条件付きnullアプリ種別。web のみ。起動コマンドのない静的サイト・SPA では必須
runtimestringはい—実行環境。対応ランタイムを参照
commandstring | list条件付き—起動コマンド。定期実行ジョブのみ、または type: web と assets を指定した静的サイトでは省略可
envmap—{}秘密でない環境変数
dbobjectはい—データベースとローカル SQLite の方針
cronslist条件付き[]定期実行ジョブ。command がなく、静的サイト(type: web と assets)でもない場合は必須
taskslist—[]アプリが SDK で投入するバックグラウンドタスク。tasks を参照
mcpobject—nullAI クライアントから MCP で使うツールの宣言。mcp を参照
assetsobject—null静的アセット配信
healthobject—nullデプロイ時ヘルスチェックのパス
secretsobject—{}シークレットの宣言と必須条件
authobject—null対話ログインを通さない外部向けエンドポイント
verifystring | list—[]デプロイ後に追加で検証するパス
regionstring—null新規アプリの配置リージョン
storageobject—{}廃止された disk_id だけを受理する互換ブロック

廃止されたトップレベルキー databases と workers は、値が null や空リストでも拒否されます。継続して保存する業務データは db.mode: libsql、リクエストの後に実行する処理は tasks、決まった時刻に実行する処理は crons で表現してください。

旧名のトップレベル tenant も workspace の互換用別名として受け付けます。撤去時期は 未定です。両方を書く場合、前後の空白や大文字小文字も含めて、値が完全に一致している必要があります。

上の表にないトップレベルキー(build、port、scaling など)や、各オブジェクトの中の未知のキーは拒否されます。独自のキーを足せる拡張可能な形式ではありません。crons / secrets / storage に null を書くと省略と同じにはならず拒否されます。省略したいときはキーごと書かないでください。

迷ったら、文字列の値は引用符で囲んでください。 CLI と API で同じ文字列として読み取れるようにするためです。

次のような文字列は、引用符で囲むか、ブロックスカラー(| / >)で書く必要があります。引用符なしで書くと、string_value_not_portable で拒否されます。

  • 数字で始まる値(slug: "123-app")
  • 日本語などの非 ASCII 文字で始まる値(description: "営業向けアプリ")
  • - で始まる値。コマンドの引数も対象です(command: [python, app.py, "--port", "8080"])
  • YAML が真偽値や null と解釈する語(yes / no / on / off / true / false / null と、env のキーの制約に列挙した大文字小文字の表記)
  • : で始まる値(":memory:")など、下記の例外に当てはまらない記号で始まる値

引用符を省略できるのは、次の場合です。ただし、上に挙げた真偽値・null と解釈される語は除きます。

値の種類引用符を省略できる書き方例
slug、runtime、シークレット名などの識別子半角英字か _ で始まるmy-app、python-slim、OPENAI_API_KEY
コマンド、説明文、パスなどの文字列半角英字か _、または /、./、../ で始まるpython app.py、/health、./app

: を含むだけで引用符が必須になるわけではありません。たとえば description: https://example.com は引用符なしで書けます。ただし、: (コロンと空白)を含む文字列など、YAML 自体の構文上、引用符が必要な場合もあります。引用符を付けても、各フィールドのパス形式や文字数などの制約は変わりません。

env の値は例外で、先頭の文字にかかわらず、すべて引用符かブロックスカラーで書く必要があります(env を参照)。


アプリの識別子です。アプリ作成時の公開 URL(https://<ワークスペース slug>--<slug>.keelson.run)の一部になります。

slug: my-app

ルール:

  • 小文字英数字とハイフン(a-z、0-9、-)のみ
  • 1〜63 文字
  • 先頭と末尾は英数字
  • ハイフンの連続(--)は不可
  • 予約語: admin api assets auth console health static www

public_slug は廃止された互換フィールドで、無視されます。


アプリが誰向けで何をするかを示す 1〜2 文です。

description: "営業チーム向けの日報・週報作成アプリ。週次サマリーを自動集計します"

前後の空白を除いて 300 文字(Unicode コードポイント)以内。超えるとデプロイが失敗します。コンソールのアプリ説明欄に表示され、説明がまだ空のときだけ適用されます。コンソールで編集した説明がデプロイで上書きされることはありません。


コンソールのアプリ一覧・アプリ詳細でアプリのアイコンとして表示する画像です。省略できます。指定しないアプリは名前の頭文字で表示され、テンプレートから作ったアプリはテンプレートのアイコンで表示されます。

icon: ./assets/app-icon.png
  • パスは keelson.yaml のあるフォルダからの相対パスです。コマンドを実行したフォルダは関係ありません。プロジェクトの外を指すパス(絶対パス、.. で外に出るパス)、\ を含むパス、シンボリックリンクは使えません。
  • 画像はソースと一緒にアップロードされるため、アーカイブから除外される場所には置けません(アーカイブに含まれるものを参照)。command のない静的サイトでは assets.dir の中に置いてください。
  • 使える画像は PNG・JPEG・WebP で、256KB 以下、縦横とも 32〜2048 ピクセルです。形式は拡張子ではなくファイルの中身で判定します。SVG は使えません。
  • keelson deploy(--check を含む)は、アプリを作成・アップロードする前に画像を確かめ、問題があればパスと原因を表示して止まります。原因は icon.path(見つからない・読めない・シンボリックリンク・アップロードされない)、icon.format、icon.size、icon.dimensions、icon.corrupt(画像のヘッダーが読めない)のいずれかです。

アイコンはデプロイが成功した時点で反映され、CLI は完了時に Icon: の行を 1 行表示します(--ndjson では icon_outcome)。

icon_outcome意味
appliedkeelson.yaml の画像をアプリのアイコンにした
unchangedすでに同じ画像がアイコンになっている
kept_console_iconコンソールでアップロードしたアイコンを残した(keelson.yaml では置き換えない)
kept_clearedコンソールでアイコンが削除されているため、デプロイでは戻さない

コンソールで設定・削除したアイコンは、常に keelson.yaml より優先されます。その後で keelson.yaml の画像を使いたい場合は、コンソールのアプリの「設定」でその画像をアップロードしてください。keelson.yaml から icon を消しても、アプリのアイコンは消えません。

アプリアイコンは順次提供中です。デプロイが icon is not available yet で拒否された場合は、keelson.yaml から icon を消して再度デプロイしてください。


アプリ種別です。起動コマンドのない静的サイト・SPA では type: web が必須です。それ以外では省略できます。

type: web

指定できる値は web だけです。type: web を指定すると、assets だけで command なしのデプロイができます。

制約:

  • type: web と crons は併用できません
  • Web アプリと定期実行ジョブを両方持つアプリでは type を省略します

実行環境です。静的サイトだけのデプロイでも必須ですが、静的サイトではビルドに使われません。静的サイトは手元や CI でビルド済みの assets.dir をそのまま配信します。

ランタイム言語用途
python-slimPython軽量。API、テキスト処理など
python-mediaPython画像・動画処理(Pillow、opencv、ffmpeg 関連など)
node-slimNode.js軽量
node-mediaNode.js画像処理(sharp など)
go-slimGo軽量
go-mediaGoメディア処理

迷ったら -slim から始め、メディア処理系ライブラリが必要になったら -media に切り替えます。

コンテナ型とハイブリッド型では、依存パッケージはビルド時に Keelson が自動でインストールします。静的サイト(type: web と assets を指定し、command なし)ではこの処理は行われません。既定でアップロードされるのは assets.dir 配下のファイルと keelson.yaml だけです(アーカイブに含まれるもの)。command には起動コマンドだけを書いてください。command に pip install / npm install / go build を含めると、CLI の事前チェックが command_installs_dependencies でデプロイを止めます。

ランタイム検出するファイルビルド時に実行される処理
python-*requirements.txtpython -m pip install --user -r requirements.txt
python-*pyproject.toml([project] または [build-system] あり)。requirements.txt がない場合のみpython -m pip install --user .
node-*package-lock.json / package.jsonnpm ci(ロックファイルあり)または npm install、続けて npm run build --if-present
go-*go.mod / go.sumgo mod download、go build -o /workspace/app .(command: "./app" で起動)

ビルドの制約:

  • requirements.txt と pyproject.toml が両方あるときは requirements.txt だけを使います。pyproject.toml 側だけに書いた依存や自作パッケージのインストールは行われないので、必要なものは requirements.txt に含めてください
  • インストール可能な Python の pyproject.toml には、対応するロックファイル(requirements.txt / poetry.lock / uv.lock / Pipfile.lock)のいずれかが必要です
  • Node.js のビルドは npm のみを使います。外部パッケージへの依存を宣言するアプリには package-lock.json が必要です。開発用・任意・peer 依存も対象です。外部依存の宣言がなければ、ロックファイルは省略できます。ロックファイルがなく、package.json がある場合は npm install が実行されます。pnpm-lock.yaml / yarn.lock だけの場合は事前チェックが lockfile_unsupported でデプロイを止めます。package-lock.json と併存している場合はそのまま残してかまいません
  • サードパーティ依存を宣言する Go モジュールには go.sum が必要です。標準ライブラリだけを使うモジュールには必要ありません
  • 公開レジストリからのみ取得できます。private registry、git+ssh 依存、認証が必要なインストールは失敗します
  • Go は CGO_ENABLED=0 でビルドされます
  • ビルド対象は linux/amd64 のみ
  • ビルド時にシークレットは渡りません
  • ビルドの上限時間は 600 秒

アプリ起動時に実行するコマンドです。文字列(シェル経由)またはリスト(直接実行)で指定します。

# 文字列形式(/bin/sh -c で実行)
command: "python app.py"
# リスト形式(exec で直接実行)
command:
- python
- app.py

ルール:

  • 起動コマンド(command)、定期実行ジョブ(crons)、静的サイト(type: web と assets)のいずれかが必要です
  • 定期実行ジョブだけのアプリに command は不要です
  • type: web で assets がある静的サイトに command は不要です
  • 空文字列・空リストは「起動コマンドなし」として扱われます。通常の Web アプリでは指定が必要です。crons[].command は空にできません
  • 依存関係のインストールは含めません(依存関係のインストールを参照)

秘密でない環境変数をキーと値で定義します。値はすべて文字列です。

PORT は Keelson が実行時に設定します。env に書いても無視されます。

値は必ず引用符で囲むか、ブロックスカラー(| / >)で書いてください。 引用符のない値は env_value_not_string で拒否され、デプロイは開始されません。数値・真偽値も同様です。

env:
NODE_ENV: "production"
DEBUG: "false"
LOG_LEVEL: "info"

引用符が必須なのは、keelson.yaml を CLI(YAML 1.2)と API(YAML 1.1)の 2 つの実装が解析しており、引用符のないスカラーの型解決が食い違うためです。たとえば K: 0o123 は経路によって "83" にも "0o123" にもなります。引用符で囲めば両方で同じ文字列になります。

引用符を付けないキーは、英字か _ で始まり、英数字と _ だけで構成される必要があります。NODE_ENV や DB_POOL のような通常の環境変数名はそのまま書けます。

次の語は YAML 1.1 で真偽値・null と解釈されるため、引用符なしでは使えません:

yes Yes YES no No NO true True TRUE false False FALSE on On ON off Off OFF null Null NULL

ハイフンを含む名前や予約語は、キーを引用符で囲みます。

env:
NODE_ENV: "production"
"MY-VAR": "x"
"yes": "x"

KEELSON_ で始まるキー(大文字小文字を区別しない)はプラットフォーム予約で、env には設定できません。env の重複宣言、env 内のキー重複、YAML の merge key(<<)も拒否されます。

秘密の値は env ではなく secrets で宣言し、値はコンソールまたは CLI で設定します。env と同じ名前のシークレットが設定されている場合はシークレットの値が優先され、env の変更は反映されません。


データベースの扱いを選びます。db と db.mode は必須です。

db:
mode: libsql
フィールド型必須既定値説明
modestringはい—libsql または none。旧名 turso は libsql に正規化
migratestring—nullデプロイ時に実行するマイグレーションコマンド。libsql のときのみ有効
auto_adoptboolean—false旧設定との互換のため受理されるが、現在は何もしない。DB を引き継ぐ機能ではない
local_sqliteobject—null再生成可能な一時 SQLite ファイルの明示宣言
mode意味
libsqlKeelson がアプリ専用の Managed SQLite を用意し、KEELSON_DB_URL / KEELSON_DB_AUTH_TOKEN(別名 TURSO_DATABASE_URL / TURSO_AUTH_TOKEN)を注入する
noneKeelson は DB を管理しない。DB 不要のアプリ、または外部 DB を使うアプリ

mode: libsql は契約も接続設定も不要で、scale-to-zero に対応します。継続して保存する業務データにはこれを推奨します。

PostgreSQL、MySQL、自前の libSQL を使う場合は mode: none にし、接続情報をシークレットで渡します。外部 DB の接続情報を Keelson が注入することはありません。

ファイル SQLite を永続化するモードはありません(/data は存在せず、アプリからも作成できません)。ファイル SQLite を使うコード(sqlite3、better-sqlite3 など)はデプロイ時に検出され、local_sqlite の宣言がなければ拒否されます。

db.migrate は、新しいイメージでトラフィックを切り替える前に 1 回だけ実行されるコマンドです。

db:
mode: libsql
migrate: "python migrate.py"
  • mode: libsql のときのみ有効。文字列で指定します
  • コンテナ型・ハイブリッド型でのみ実行されます。静的サイトにはコンテナがないため、宣言しても実行されません
  • 候補リビジョンがヘルスチェックを通った後、トラフィック切り替えの前に、デプロイ対象のイメージ上で実行されます。アプリの起動コードは移行前のスキーマで動く必要があります
  • 終了コードが 0 以外ならデプロイは deploy.runtime.migration_failed で失敗し、旧リビジョンが維持されます
  • 毎回のデプロイで実行されるため、冪等に書きます(CREATE TABLE IF NOT EXISTS、ON CONFLICT DO NOTHING)

再生成できるキャッシュ用途のファイルだけを db.local_sqlite で宣言します。宣言してもファイルは永続化されません。

db:
mode: none
local_sqlite:
policy: ephemeral
paths:
- /tmp/cache.db
reason: "外部 API から再構築できる派生キャッシュ"
フィールド型必須制約
policystringはいephemeral のみ
pathslistはい空でないこと。各パスは /tmp/ 配下か :memory:
reasonstringはい消えても問題ない理由

廃止された databases ブロックは常に拒否されます。


定期実行ジョブを定義します。各ジョブは Web サービスとは別のインスタンスで実行されます。

crons:
- name: cleanup
description: "期限切れのセッションを削除する"
schedule: "0 3 * * *"
command: "python cleanup.py"
timeout: 60
enabled: true
フィールド型必須既定値説明
namestringはい—ジョブ名。小文字英数字とハイフン、1〜63 文字、重複不可
schedulestringはい—5 フィールドの cron 式
commandstring | listはい—実行コマンド
timeoutinteger—300タイムアウト秒。1〜600
enabledboolean—truefalse にするとスケジュールされない
descriptionstring——ジョブの 1 行説明。コンソールの定期実行タブに表示する。下の crons[].description を参照

ルール:

  • 1 アプリ最大 10 本。プランによりさらに少ない上限があります
  • crons[].description は表示専用です。前後の空白を除き、空なら未指定と同じです。除いた後で 100 文字を超えると cron_description_too_long で拒否されます(切り詰めはしません)。書き換えても実行内容は変わりません
  • type: web と併用できません
  • 別インスタンスで実行されるため、ローカルファイル(/tmp を含む)は Web と共有されません。共有する状態は db.mode: libsql に置きます
  • 前回の実行が継続中なら、その回はスキップされます
  • スケジュールはワークスペースのタイムゾーンで評価されます
  • timeout の絶対上限は 600 秒。省略時は 300 秒ですが、プランの上限がそれより低ければプラン上限に切り詰められます

本数・最小間隔・timeout 上限のプラン別の値はプランと制限を参照してください。

式意味
0 * * * *毎時 0 分
*/15 * * * *15 分ごと
0 3 * * *毎日 3:00
0 9 * * 1-5平日 9:00
0 0 1 * *毎月 1 日 0:00

* * * * *(毎分)は全プランの最小間隔より短いため拒否されます。実行の挙動と設計は定期実行ジョブを参照してください。


バックグラウンドタスクを宣言します。アプリのコードが SDK で名前を指定して投入すると、Keelson は宣言したコマンドを Web サービスとは別のインスタンスで 1 回起動し、失敗した試行は自動で再試行します。crons と違い、時刻では起動しません。投入の仕方・コマンドの書き方・2 回走っても壊れない書き方はバックグラウンドタスクを参照してください。

command: "python app.py"
tasks:
- name: generate-pdf
description: "注文の請求書 PDF を作る"
command: "python generate_pdf.py"
timeout: 180
max_attempts: 5
フィールド型必須既定値説明
namestringはい—タスク名。小文字英数字とハイフン、1〜63 文字(crons[].name と同じ規則)。前後の空白を除いて小文字化して扱うため、Foo は foo として受け付ける
commandstring | listはい—実行コマンド。文字列は /bin/sh -c、リストは直接実行
timeoutinteger—3001 回の試行の制限時間(秒)。1〜600
max_attemptsinteger—3初回を含む試行の最大回数。1〜5
descriptionstring——タスクの 1 行説明。コンソールのバックグラウンドタスクタブに表示する。下の tasks[].description を参照

ルール:

  • 1 アプリ最大 10 本(全プラン共通)
  • タスク名は重複できず、crons のジョブと同じ名前も使えません(task_name_conflicts_with_cron)。名前は前後の空白を除いて小文字化した後で比べます
  • tasks があるのに command も crons も無い設定は、タスクを投入するコードが無いため tasks_require_command_or_crons で拒否されます。type: web と assets だけで command の無い静的サイトもこれに当たります
  • type: web と併用できます
  • tasks[].description は表示専用です。前後の空白を除き、空なら未指定と同じです。除いた後で 100 文字を超えると task_description_too_long で拒否されます(切り詰めはしません)。書き換えても実行内容は変わりません
  • 未知のキーは拒否されます。同時実行数は宣言できません(プランの値を Keelson がかけます)
  • timeout の絶対上限は 600 秒。明示した値がプランの上限を超えると plan_task_timeout で拒否されます。省略時の 300 秒がプランの上限より大きければ、プランの上限に切り下げます
  • 各試行の標準入力に、attempt_no・payload・schema_version・task_id・task_name を持つ JSON が 1 行で渡されます。終了コード 0 が成功です。別インスタンスで実行されるため、ローカルファイルは Web と共有されません

timeout 上限のプラン別の値はプランと制限を参照してください。


アプリのツールを宣言し、Claude や ChatGPT などの AI クライアントから MCP で使えるようにします。ツールが呼ばれると、Keelson がアプリの POST /api/mcp/<name> を呼びます。ログイン・同意画面・AI クライアントとのやり取りは Keelson が受け持ちます。ハンドラの書き方・接続・上限は AI クライアントから使う(MCP)を参照してください。

command: "python app.py"
mcp:
enabled: true
instructions: "Look up stock levels and record incoming deliveries."
tools:
- name: search_items
description: "Search stock by item name."
access: read
input:
type: object
properties:
query:
type: string
required: [query]
- name: create_arrival
description: "Record one incoming delivery."
access: write
permission: manage
input:
type: object
properties:
item_id:
type: string
quantity:
type: integer
minimum: 1
required: [item_id, quantity]
フィールド型必須既定値説明
enabledbooleanはい—true でツールを公開する。false は宣言を残したまま呼び出しを止める(既存の接続は失効しない)
instructionsstring—nullAI クライアントに渡す、ツール全体の説明。4096 文字以内
toolslist条件付き—ツールの一覧。enabled: true なら必須。書いた場合は enabled にかかわらず 1〜40 本
filestring——instructions と tools を置く別ファイル。mcp.file を参照。新しい Keelson CLI が必要
tools[].namestringはい—ツール名。^[a-z][a-z0-9_]{0,63}$(英小文字で始まり、英小文字・数字・_ だけ。小文字化などの正規化はしない)。重複不可。ハンドラのパスは POST /api/mcp/<name>
tools[].descriptionstringはい—AI クライアントに見せるツールの説明。1〜1024 文字。空白だけは不可
tools[].accessstringはい—read か write。write は同意画面で別に表示され、利用者は読み取りだけを承認できる
tools[].permissionstring—viewview か manage。manage のツールはアプリの管理権限を持つ人だけが使える
tools[].inputobjectはい—引数の JSON Schema(2020-12)。最上位は type: object

ルール:

  • 宣言できるのは、サーバー側のプログラムが動くアプリ(command があり assets がない)だけです。静的サイト・SPA・ハイブリッドでは mcp is only supported for container apps で拒否されます
  • mcp と tools[] の未知のキーは拒否されます。ハンドラのパスは固定なので、tools[].endpoint は書けません
  • input は JSON として表せる値だけで書きます。入れ子は 32 段まで、JSON にして 64 KB まで。日付や、引用符なしでは文字列以外に読まれるキー(yes・on・数値など)は引用符で囲みます
  • input の中で $ref・$dynamicRef・$recursiveRef・x-mcp-header は使わないでください。$ref と x-mcp-header はデプロイで拒否され、$dynamicRef と $recursiveRef はデプロイを通っても呼び出しがすべて失敗します
  • mcp の中では YAML のアンカー・エイリアス・マージキー(<<)は使えません
  • mcp: を書いていなくても、サーバー側のプログラムが動くアプリでは /api/mcp と /api/mcp/ で始まるパスは MCP 専用です(予約 URL パス)

ツールが多いときは、instructions と tools を別の YAML ファイルに置けます。keelson.yaml には enabled と file だけを書きます。

command: "python app.py"
mcp:
enabled: true
file: mcp.yaml
# mcp.yaml(keelson.yaml と同じフォルダ)
instructions: "Look up stock levels and record incoming deliveries."
tools:
- name: search_items
description: "Search stock by item name."
access: read
input:
type: object
properties:
query:
type: string
required: [query]
  • デプロイ時に Keelson CLI が別ファイルの中身を keelson.yaml の mcp に差し込んでから検査・送信します。手元の keelson.yaml は書き換えません
  • 別ファイルのトップレベルに書けるのは instructions と tools だけです(どちらも省略可)。mcp.file と mcp.instructions / mcp.tools は同時に書けません
  • パスは keelson.yaml のあるフォルダからの相対パスで、そのフォルダの外(.. やシンボリックリンクで外に出る場合を含む)は指せません。拡張子は .yaml か .yml、大きさは 4 MiB まで
  • 別ファイルの中の誤りは、mcp.yaml: tools[3].input ... のように別ファイル名と位置で示されます
  • mcp.file を読めるのは新しい Keelson CLI だけです。古い CLI は mcp contains unsupported field(s): file でデプロイを拒否します。keelson upgrade で CLI を最新版にしてください。CLI を通さない経路では使えません

workers(バックグラウンドワーカー)は廃止されました。トップレベルに workers があると、値が空リストや null でも workers_not_supported で拒否されます。

リクエストを受けて走らせる処理は tasks に宣言し、SDK で投入します(バックグラウンドタスク)。未処理データを定期的に処理する場合は、crons に定期実行ジョブを定義します。プランで許可される間隔で実行し、1 回ごとに未処理分を処理して終了する形にします。

# NG — デプロイが拒否される
workers:
- name: drain
command: "python worker.py"
every: 10m
# OK — crons で書く
crons:
- name: drain
schedule: "*/5 * * * *"
command: "python drain.py"
timeout: 120

静的サイト、SPA、静的ファイル + バックエンド API(ハイブリッド)の配信設定です。

assets:
dir: dist
fallback: index.html
api: /api
フィールド型必須既定値説明
dirstringはい—アセットディレクトリ(プロジェクトルートからの相対パス)
static_dirstring—nulldir の廃止された別名。両方ある場合は一致が必要
fallbackstring条件付きnullSPA 用フォールバック(例: index.html)。dir 配下の相対パス。type: web を指定したハイブリッドでは必須
apistring—null(ハイブリッドでは実効値 /api)バックエンドへ転送するパスプレフィックス。command と assets の両方があるハイブリッドで省略すると /api が使われる

ハイブリッドでは api のパス配下がバックエンドへ転送され、それ以外は静的アセットとして配信されます。省略時のプレフィックスは /api です。別のパスにしたいときだけ指定します。

ルール:

  • dir に .. は使えません
  • api は / で始まり、/ そのものではなく、/__keelson 配下でないこと
  • api はトップレベルの command がある場合のみ有効
  • type: web を指定し、assets と command の両方があるハイブリッドでは fallback が必須です。type を省略した場合、設定検証では fallback の省略が認められます。SPA の画面を配信する場合は index.html などを指定してください

静的サイト(type: web と assets を指定し、command なし)では、既定で assets.dir 配下のファイルと keelson.yaml だけをアップロードします。コンテナ型・ハイブリッド型では、ビルドに必要なソースも含めます。どちらも、以下の除外ルールが適用されます。

assets.dir: . や同じ意味の ./ は避けてください。プロジェクト直下が公開対象となり、アーカイブに含まれる全ファイルが配信される可能性があります。CLI はデプロイ前に警告しますが、この設定は禁止しません。

  • パスの構成要素が .git、.venv、__pycache__、.pytest_cache、node_modules、dist、build、.idea、.vscode、.DS_Store に一致するファイルやディレクトリ
  • ファイル名が .env で始まるか終わるファイル(.env、.env.production、.envrc、.secrets.env など)。assets.dir の中でも除外されます
  • シンボリックリンク、通常ファイル以外、--secrets-from-env-file で指定したファイル

宣言した assets.dir と、そこに至るまでのディレクトリは、名前による除外の対象外です。そのため、assets.dir: dist なら dist のビルド出力を含められます。ただし、その中の dist/node_modules/** などは除外されます。.git はこの例外の対象になりません。

プロジェクト固有の除外は、プロジェクト直下の .keelsonignore に書きます。.gitignore は読みません。

書き方意味
1 行 1 パターン一致するファイルやディレクトリを除外する。最後に一致した行が優先される
# で始まる行コメント
/、末尾 /、*、?、**、[abc]、[a-z]gitignore に似たパス・パターン指定
先頭 !一致するファイルやディレクトリを再び含める

!.env.production で env ファイルを意図的に含めることもできます。ただし、.git などの組み込み除外、.keelsonignore 自身、--secrets-from-env-file で指定したファイルは戻せません。

静的サイトで assets.dir の外側にあるファイルを含めたい場合も、先頭 ! を使います。ディレクトリとその中身を含めるには、!keep/ と !keep/** の両方が必要です。

keelson deploy --check --json を実行し、除外されたファイルと、秘密情報を含む可能性があるファイルを確認してください。

  • プレビュー用の認証情報やアプリ用トークンがファイル内で検出された場合は、アップロードを停止します
  • Webhook 署名鍵だけが検出された場合は、警告を表示して続行します
  • ファイル名などから秘密情報を含む可能性があると判断した場合も、警告を表示します。警告だけでは除外されないため、必要に応じて .keelsonignore に追加します

--check は主要な設定も手元で検証します。ただし、assets / crons / auth / secrets 内の未知のキー、cron 式の妥当性、verify のパス形式などは API 側で検証します。--check が通っても、デプロイ時に deploy.config.invalid で止まる場合があります。

JSON の項目確認できる内容
archive.excluded除外されたファイル
archive.excluded_env_files除外された env ファイル
archive.secret_like_files名前などから秘密情報を含む可能性があると判断されたファイル
archive.embedded_credentialsファイル内で検出された認証情報のパスと種別。値は表示しない
archive.unscanned_filesサイズ上限などにより本文を検査しなかったファイル
archive.unscanned_binary_countバイナリと判定され、本文を検査しなかったファイルの数

16 MiB を超えるファイルと、バイナリと判定されたファイルは本文を検査しません。アーカイブから除外されたファイルも検査対象外です。

secret_like_files には、credentials.json や *.pem のような名前のほか、過去に --secrets-from-env-file で指定したものの、今回は除外されていない実在ファイルも含まれます。prod-secrets.txt のように env ファイルの命名規則に当てはまらない名前も対象です。

過去に指定したファイルを判定するため、CLI はそのプロジェクト相対パスを .keelson-config/previous-secrets-files.json に保存します。この記録には秘密の値は含まれず、記録ファイル自体もアップロードから自動で除外されます。

ファイル名にコンテンツハッシュが入った JavaScript / CSS(例: index-B7hK2mQ1.js)は 1 年間キャッシュされます。Keelson は、ASCII 英数字と _ からなり英字と数字の両方を含む 8〜64 文字の末尾セグメントをハッシュと認識します。HTML、style.css や app.js のようなハッシュなしのファイル、画像などは、アクセスのたびに ETag で更新を確認します。

静的サイト(edge-static / edge-spa)の再デプロイは、新しいファイルがエッジに反映されるまで最大 60 秒ほどかかります(実測 1〜57 秒、中央値は 30 秒前後)。60 秒待ってからファイルの有無を判断してください。


デプロイ時のヘルスチェックに使うパスです。/ が重い、DB に依存する、などの場合に軽量なエンドポイントを指定します。

health:
path: /health
  • 省略時は / を確認します
  • / で始まり、.. を含まず、/__keelson で始まらない 2048 文字以内のパス
  • HTTP 2xx / 3xx / 404 で合格、それ以外の 4xx と 5xx で不合格。404 が通るため、合格は「起動した」ことの確認であり、そのパスが実装されていることの証明ではありません
  • 候補リビジョンの内部 URL へ直接送られ、公開ホストや認証は経由しません。公開パスの検証は verify で行います

アプリが必要とするシークレットと、必須の組み合わせを宣言します。値はここには書かず、コンソール、CLI、またはデプロイ時の env ファイルで設定します。

secrets:
items:
- name: OPENAI_API_KEY
description: "OpenAI API key"
- name: ANTHROPIC_API_KEY
description: "Anthropic API key"
required:
- any_of: [OPENAI_API_KEY, ANTHROPIC_API_KEY]
message: "AI プロバイダのキーを少なくとも 1 つ設定してください"
フィールド型必須既定値説明
itemslist—[]シークレットの定義
items[].namestringはい—名前。環境変数の形式(大文字英字か _ で始まり、A-Z0-9_ のみ、255 文字以内)で書く。KEELSON_ で始まる名前は予約
items[].descriptionstring—""用途の説明。コンソールに表示される
requiredlist—[]設定済みシークレットに対して検証するルール
required[].any_oflist条件付きnullいずれか 1 つが設定されていればよい名前の空でないリスト
required[].all_oflist条件付きnullすべて設定されている必要がある名前の空でないリスト
required[].messagestring—""未設定時に表示する案内

required の各エントリは any_of または all_of のどちらか一方だけを持ちます。参照できるのは items で宣言した名前だけです。

名前は値を設定するときに大文字に正規化され、required の照合は大文字小文字を区別します。name: api_key と書くと値は API_KEY として保存され、required の条件が満たされません。最初から大文字で書いてください。MY-KEY のようにハイフンを含む名前は宣言できても値を設定できません。

新しいアプリでは keelson deploy --new --secrets-from-env-file <path> で、アプリ作成・シークレット設定・初回デプロイを 1 回で行えます。既存アプリのシークレット変更は次のデプロイで反映されます。


Webhook の受信など、対話ログインを通さずに外部システムから呼ばれるエンドポイントを宣言します。

auth:
endpoints:
- /api/webhooks/stripe
- path: /api/external/status
methods: [GET]
  • auth がある場合、endpoints は空でないリストが必須です
  • 各エントリはパス文字列、または path と省略可能な methods を持つオブジェクト
  • パスは /api/external/ または /api/webhooks/ で始まり、重複しないこと。/__keelson 配下は不可
  • パスは前方一致です。/api/external/status は /api/external/status-extra にも一致します
  • methods を指定する場合は空でないリスト。省略時は全メソッドを許可。大文字小文字は区別しません
  • methods が効くのは /api/external/ だけです。/api/webhooks/ には適用されず、メソッドを絞りたければアプリ側で判定します

「対話ログインを通さない」は「Keelson の認証が不要」という意味ではありません。宣言しただけでは外部から届かず、呼び出し側は Keelson が発行する資格情報を付ける必要があります。

パス必要な資格情報
/api/external/...api スコープのアプリトークンを Authorization: Bearer で送る
/api/webhooks/...webhook スコープのアプリトークンを X-Webhook-Secret ヘッダーで送るか、/api/webhooks/<secret>/... の形の URL を外部サービスに登録する

トークンの発行は keelson apps tokens create、URL の組み立ては外部連携を参照してください。Stripe の署名だけを送る通常の Webhook や、アプリ独自の API キーだけを送るクライアントは、アプリに届く前に拒否されます。

これらのパスへのリクエストでは X-Keelson-User-Id は空文字になります(ヘッダー自体は常に付き、対話ユーザーがいなければ空)。空を「ユーザーなし」として扱ってください。Keelson の資格情報に加えて、アプリ側でも Webhook 署名や API キーによる検証を行ってください。


デプロイ後の検証で追加で確認するパスです。既定では / だけを確認します。

verify:
- /dashboard
- /settings
  • 単一のパスは文字列でも 1 要素のリストでも指定できます
  • 最大 20 パス(前後の空白を除き、重複を除いた数)。各パスは / で始まり、// で始まらず、パス要素としての .. と制御文字を含まないこと
  • コンテナ型・ハイブリッド型では公開ホスト経由で候補リビジョンから取得し、静的サイト・SPA では公開前にリリースマニフェスト上で解決します
  • どちらの種類でも、宣言したパスが 2xx / 3xx 以外(404 / 401 / 403 / 405 など)なら verification_declared_path_unreachable でデプロイに失敗します
  • verify: にはアプリ自身のログインを必要としないパスを書いてください。検証リクエストにはアプリのユーザー情報が付かないため、アプリが返す 401 / 403 も不合格です
  • / は verify: にも書かれていても従来どおり寛容です。API だけのアプリが / で 404 を返しても合格します

クライアント側ルーティングでしか到達できない画面など、/ から辿れないエントリを確認したいときに使います。

これは health.path とは別の判定です。health.path は候補リビジョンを内部 URL で直接確認し、プロセスが起動した証拠として 404 でも合格します。verify は宣言した公開パスが実際に配信できるかを確認するため、404 では不合格です。


新規アプリを作るときの配置リージョンを任意で指定します。

region: jp-tokyo

クラウド事業者のリージョン名ではなく、Keelson の論理キーを指定します。

論理キー表示名新規作成
jp-tokyo日本可(既定)
us-oregon米国西海岸未提供(指定すると拒否)

新規アプリでは CLI の --region、keelson.yaml の region、ワークスペースの既定リージョンの順で優先されます。明示したリージョンが未定義または新規作成に未開放の場合は、別リージョンへ切り替えずに拒否されます。

アプリのリージョンは作成時に確定し、後から変更できません。既存アプリと異なる region を指定したデプロイは拒否されます。別リージョンへ移す場合は、新しいアプリとして作り直してください。


storage は廃止された disk_id だけを受理します。値は無視され、永続ストレージや /data の同期を有効にしません。残っていたら削除してください。

フィールド型必須既定値説明
disk_idstring—null無視される旧識別子。小文字英数字とハイフン、1〜32 文字

デプロイモードは command、assets、assets.fallback の有無から自動的に決まります。keelson status --json などの出力では、下表の値が deploy_mode に返されます。静的サイト・SPA の設定には type: web も必要です。

呼称deploy_modecommandassetsfallback説明
Web アプリcontainerありなし—通常のアプリ
静的サイトedge-staticなしありなし静的ファイルのみ
SPAedge-spaなしありありフォールバック付き静的ファイル
ハイブリッドhybridありありtype: web を指定した場合は必須静的ファイル + バックエンド API

ルール内容
起動コマンド・定期実行ジョブ・静的サイトのいずれかが必要command、crons、または type: web と assets の組み合わせを指定する
タスクには投入するコードが必要tasks がある場合は command か crons を指定する(tasks_require_command_or_crons)
タスクとジョブの名前は別にするtasks[].name は crons[].name と同じにできない(task_name_conflicts_with_cron)
静的サイトと定期実行ジョブは併用不可静的サイトに必要な type: web と crons を併記すると、設定検証で拒否される。定期実行ジョブを使う場合は type を省略する
静的サイトにはコンテナがない静的サイト・SPA では db.migrate を宣言しても実行されない。マイグレーションを使う場合はコンテナ型かハイブリッド型にする
workers は廃止リクエストの後に実行する処理は tasks、決まった時刻に実行する処理は crons で書き直す
db.migrate は libsql のみdb.mode: libsql が必要
ローカル SQLite は一時領域のみdb.local_sqlite.paths は /tmp/ 配下か :memory:
mcp はサーバー側のプログラムが動くアプリだけcommand があり assets がないアプリにだけ書ける(mcp is only supported for container apps)
assets.api にはバックエンドが必要トップレベルの command を設定する
type: web を指定したハイブリッドには fallback が必要type: web、assets、command を併記する場合は assets.fallback を設定する。type を省略した場合は、この必須チェックの対象外

slug: crud-app
description: "顧客と案件を管理する社内 CRM"
runtime: python-slim
command: "python app.py"
db:
mode: libsql
migrate: "python migrate.py"
env:
PYTHONUNBUFFERED: "1"

手元で npm run build などを実行して dist を作ってからデプロイします。Keelson 側ではビルドしません。

slug: marketing-site
type: web
runtime: node-slim
db:
mode: none
assets:
dir: dist
fallback: index.html
slug: daily-report
runtime: python-slim
db:
mode: libsql
env:
PYTHONUNBUFFERED: "1"
crons:
- name: generate
schedule: "0 9 * * *"
command: "python report.py"
timeout: 120

Web アプリ + バックグラウンドタスク

Section titled “Web アプリ + バックグラウンドタスク”

Web アプリがリクエストを受けて SDK で generate-pdf を投入し、Keelson が Web アプリとは別のインスタンスでタスクのコマンドを実行します。詳しくはバックグラウンドタスクを参照してください。

slug: pdf-reports
runtime: python-slim
command: "python app.py"
db:
mode: libsql
env:
PYTHONUNBUFFERED: "1"
tasks:
- name: generate-pdf
command: "python generate_pdf.py"
timeout: 180
max_attempts: 3

Web アプリ + 未処理データを定期的に処理するジョブ

Section titled “Web アプリ + 未処理データを定期的に処理するジョブ”

タスクを使わずにリクエストの後の処理を組む場合は、未処理のデータを DB に保存して定期実行ジョブで処理します。処理は次の実行まで待ちます。リクエストの後すぐに始めたい処理には、バックグラウンドタスクを使ってください。

Web アプリが未処理のデータを Managed SQLite に保存し、定期実行ジョブが別のインスタンスで処理します。両者で共有するデータは db.mode: libsql に保存します。

slug: task-drainer
runtime: python-slim
command: "python app.py"
db:
mode: libsql
env:
PYTHONUNBUFFERED: "1"
crons:
- name: drain
schedule: "*/5 * * * *"
command: "python drain.py"
timeout: 120

ハイブリッド(静的ファイル + バックエンド API)

Section titled “ハイブリッド(静的ファイル + バックエンド API)”
slug: photo-galleries
runtime: node-slim
command: "node server.js"
db:
mode: libsql
env:
NODE_ENV: "production"
assets:
dir: dist
fallback: index.html
api: /api
slug: payment-hooks
runtime: node-slim
command: "npm start"
db:
mode: libsql
env:
NODE_ENV: "production"
secrets:
items:
- name: STRIPE_WEBHOOK_SECRET
description: "Stripe の Webhook 署名シークレット"
required:
- all_of: [STRIPE_WEBHOOK_SECRET]
auth:
endpoints:
- path: /api/webhooks/stripe
methods: [POST]

Stripe に登録する URL には webhook スコープのアプリトークンを含めます(https://<host>/api/webhooks/<token>/stripe)。methods は Webhook には適用されないので、POST 以外を拒否したければアプリ側で判定します。

slug: my-go-app
runtime: go-slim
command: "./app"
db:
mode: none

Keelson がデプロイ時に Linux 向けにビルドし、バイナリを ./app に置きます。


原因対処
db または db.mode がないdb.mode を libsql か none で宣言する
廃止された databases がある削除する。永続データは Managed SQLite、一時 SQLite は db.local_sqlite で宣言
workers がある(workers_not_supported)削除する。リクエストを受けて走らせる処理は tasks、時刻で動く処理は crons で書く
command に pip install / npm install がある(command_installs_dependencies)削除する。依存はビルド時に自動インストールされる
依存マニフェストがない(missing_dependency_manifest)Go ではプロジェクトルートに go.mod を置く。Python または Node.js では、外部ライブラリを使う場合に適切なマニフェストを置く。標準ライブラリだけなら不要
runtime と command の言語が合わない(runtime_command_mismatch)ランタイムを合わせるか、起動コマンドを直す
env の値が引用符なし(env_value_not_string)すべての値を引用符で囲む(数値・真偽値も)
環境変数名が KEELSON_ で始まる名前を変える。この名前空間はプラットフォーム予約
local_sqlite.paths が /tmp/ の外/tmp/、:memory:、または Managed SQLite を使う
起動コマンド・定期実行ジョブ・静的サイトの設定がないcommand、crons、または type: web と assets の組み合わせを追加する
crons[].timeout が 600 を超える600 以下、かつプランの上限以下にする
tasks があるのに command も crons も無い(tasks_require_command_or_crons)タスクを投入する Web アプリの command、または crons のジョブを追加する
タスクと定期実行ジョブの名前が同じ(task_name_conflicts_with_cron)どちらかの名前を変える
tasks[].timeout が 600 を超える(TASK_TIMEOUT_EXCEEDS_STANDARD_LIMIT)600 以下、かつプランの上限以下(plan_task_timeout)にするか、処理を小さなタスクに分ける
mcp.enabled が true なのに mcp.tools がないツールを 1 本以上宣言するか、mcp.file で別ファイルに置く
静的サイト・SPA・ハイブリッドに mcp がある(mcp is only supported for container apps)mcp を削除するか、command だけのアプリにする
mcp.tools[].input に $ref や x-mcp-header があるスキーマを展開して書く。$dynamicRef と $recursiveRef も使わない
mcp contains unsupported field(s): fileKeelson CLI が古い。keelson upgrade で最新版にする
assets.api が / で始まらない/api のような絶対パスにする
type: web を指定したハイブリッドで assets.fallback がないindex.html などを設定する
ビルドが reserved_path_conflict で失敗ビルド出力直下の __keelson ディレクトリを改名する