コンテンツにスキップ
コンソール →
公式サイト →
AI に聞くなら、この URL を貼る 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はいアプリの識別子。アプリ作成時に使われる
workspacestringnullプロジェクト単位の CLI 操作で使う既定ワークスペース。ワークスペースの slug を推奨。所属が 1 つだけなら CLI が自動選択するため書かなくてよい。明示した --workspace はこの値より優先し、apps list の一覧は絞り込まない
descriptionstringnullアプリの説明(300 文字以内)
typestringnullアプリ種別。"web" のみ
runtimestringはい実行環境。対応ランタイムを参照
commandstring | list条件付き起動コマンド。cron のみ・静的のみの構成では省略可
envmap{}秘密でない環境変数
dbobjectはいデータベースとローカル SQLite の方針
cronslist条件付き[]定期実行ジョブ。command も静的 assets も無い場合は必須
assetsobjectnull静的アセット配信
healthobjectnullデプロイ時ヘルスチェックのパス
secretsobject{}シークレットの宣言と必須条件
authobjectnull対話ログインを通さない外部向けエンドポイント
emailobject{}受信メール
verifystring | list[]デプロイ後に追加で検証するパス
regionstringnull新規アプリの配置リージョン
storageobject{}廃止された disk_id だけを受理する互換ブロック

廃止されたトップレベルキー databasesworkers は、値が null や空リストでも拒否されます。永続的な関係データは db.mode: libsql、時刻起点の処理は crons で表現してください。

旧名のトップレベル tenantworkspace の互換用別名として受け付けます。撤去時期は 未定です。両方を書く場合、生の文字列値が完全に一致している必要があります。

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

keelson.yaml は CLI(YAML 1.2)と API(YAML 1.1)の 2 つの実装が解析します。引用符のないスカラーの型解決が食い違うため、次の文字列は引用符で囲む必要があります。囲まないと string_value_not_portable で拒否されます。

  • 数字で始まる値(slug: "123-app")
  • 日本語など ASCII 英字以外で始まる値(description: "営業向けアプリ")
  • - で始まる値。コマンドをリストで書くときのフラグ(command: [python, app.py, "--port", "8080"])
  • YAML が真偽値や null と解釈する語(yes / no / on / off / true / false / null とその大文字違い)
  • : を含む値(":memory:")

英字で始まる通常の値(python app.pymy-appdist)は引用符なしで書けます。env だけは規則が強く、値をすべて引用符かブロックスカラー(| / >)で書きます(env を参照)。


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

slug: my-app

ルール:

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

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


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

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

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


アプリ種別です。省略可能です。

type: web

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

制約:

  • type: webcrons は併用できません
  • Web アプリと cron を両方持つアプリでは 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 が自動でインストールします。静的サイト(command なし)ではこの処理は走らず、アップロードされるのも assets.dirkeelson.yaml だけです。command には起動コマンドだけを書いてください。commandpip 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 downloadgo build -o /workspace/app .command: "./app" で起動)

ビルドの制約:

  • requirements.txtpyproject.toml が両方あるときは requirements.txt だけを使います。pyproject.toml 側だけに書いた依存や自作パッケージのインストールは行われないので、必要なものは requirements.txt に含めてください
  • インストール可能な Python の pyproject.toml には、対応するロックファイル(requirements.txt / poetry.lock / uv.lock / Pipfile.lock)のいずれかが必要です
  • Node のビルドは npm のみを使い、package-lock.json が必要です。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

ルール:

  • commandcrons、静的 assets のいずれかが必要です
  • cron だけのアプリに command は不要です
  • type: webassets がある静的サイトに 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_ENVDB_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 の変更は反映されません。


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

db:
mode: libsql
フィールド必須既定値説明
modestringはいlibsql または none。旧名 tursolibsql に正規化
migratestringnullデプロイ時に実行するマイグレーションコマンド。libsql のときのみ有効
auto_adoptbooleanfalse旧設定との互換のため受理されるが、現在は何もしない。DB を引き継ぐ機能ではない
local_sqliteobjectnull再生成可能な一時 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 が注入することはありません。

/data のファイル SQLite を永続化するモードはありません。ファイル SQLite を使うコード(sqlite3better-sqlite3 など)はデプロイ時に検出され、local_sqlite の宣言がなければ拒否されます。

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

db:
mode: libsql
migrate: "python migrate.py"
  • mode: libsql のときのみ有効。文字列で指定します
  • コンテナ型・ハイブリッド型でのみ実行されます。静的サイトにはコンテナがないため、宣言しても実行されません
  • 候補リビジョンがヘルスチェックを通った後、トラフィック切り替えの前に、デプロイ対象のイメージ上で実行されます。アプリの起動コードは移行前のスキーマで動く必要があります
  • 終了コードが 0 以外ならデプロイは deploy.runtime.migration_failed で失敗し、旧リビジョンが維持されます
  • 毎回のデプロイで実行されるため、冪等に書きます(CREATE TABLE IF NOT EXISTSON 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
schedule: "0 3 * * *"
command: "python cleanup.py"
timeout: 60
enabled: true
フィールド必須既定値説明
namestringはいジョブ名。小文字英数字とハイフン、1〜63 文字、重複不可
schedulestringはい5 フィールドの cron 式
commandstring | listはい実行コマンド
timeoutinteger300タイムアウト秒。1〜600
enabledbooleantruefalse にするとスケジュールされない

ルール:

  • 1 アプリ最大 10 本。プランによりさらに少ない上限があります
  • type: web と併用できません
  • 別インスタンスで実行されるため、ローカルファイル(/data を含む)は 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

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


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

同じ処理は crons で表現します。ドレイン型の処理は、短い間隔のスケジュールを 1 本立て、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(hybrid)の配信設定です。

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

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

ルール:

  • dir.. は使えません
  • api/ で始まり、/ そのものではなく、/__keelson 配下でないこと
  • api はトップレベルの command がある場合のみ有効
  • assetscommand の両方がある hybrid では fallback が必須

CLI はデプロイ用アーカイブを作るとき、パスに .git.venv__pycache__.pytest_cachenode_modulesdistbuild.idea.vscode.DS_Store を含むものを除外します。宣言した assets.dir とその祖先は免除されるので、dist などのビルド出力は含まれます。ただし assets.dir 配下でも dist/node_modules/** のように除外名に再び一致するものは除外されます。.git、シンボリックリンク、通常ファイル以外、--secrets-from-env-file で指定したファイルは名前によらず常に除外されます。CLI はそのプロジェクト相対パスだけを、秘匿値を含めず、自動除外される .keelson-config/previous-secrets-files.json に保存します。

env 系のファイル(最後の要素が .env で始まるか終わるもの。.env.env.production.envrc.secrets.env など)は assets.dir の中でも除外されます。

プロジェクト固有の除外は、プロジェクト直下の .keelsonignore に書きます。gitignore に似た記法(1 行 1 パターン、# コメント、/、末尾 /*?**[abc][a-z]、先頭 ! の否定)が使え、最後に一致した行が優先されます。!.env.production で env ファイルを意図的に再同梱できますが、.git、組み込み除外、.keelsonignore 自身、--secrets-from-env-file のファイルは再同梱できません。.gitignore は読みません。

assets があり、文字列形式・配列形式のどちらの command もない静的アプリでは、既定で assets.dir 配下のファイルと keelson.yaml だけをアーカイブします。assets.dir へ到達するため、その祖先ディレクトリは走査できます。外側のファイルを意図的に戻すには .keelsonignore の先頭 ! を使います。ディレクトリと中身を戻すには !keep/!keep/** の両方が必要です。コンテナ型・ハイブリッド型ではビルドに必要なソースを従来どおり同梱します。

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

keelson deploy --check はアーカイブ内容と主要な設定を手元で検証しますが、API 側の検証より緩い項目があります(assets / crons / auth / email / secrets の未知キー、cron 式の妥当性、verify のパス形式など)。--check が通っても、デプロイ時に deploy.config.invalid で止まることがあります。

アップロード前に keelson deploy --check --json を実行し、archive.excludedarchive.excluded_env_filesarchive.secret_like_filesarchive.embedded_credentialsarchive.unscanned_filesarchive.unscanned_binary_count を確認してください。embedded_credentials は値を出さずパスと種別だけを報告します。プレビュー資格情報やアプリ用トークンが検出された場合はアップロードを停止し、Webhook 署名鍵のみの一致であれば警告を表示して続行します。16 MiB を超えるファイルとバイナリ判定されたファイルは本文検査をせず、除外ファイルも検査対象外です。secret_like_filescredentials.json*.pem のような秘匿値を含みそうな名前に加え、過去に --secrets-from-env-file で指定したものの今回は除外指定しなかった実在ファイルも警告します。prod-secrets.txt のような env 系でない名前も対象で、警告されたファイルは除外されず同梱されます。

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

静的サイト(edge-static / edge-spa)の再デプロイは、新しいファイルがエッジに反映されるまで 25〜30 秒かかります。


デプロイ時のヘルスチェックに使うパスです。/ が重い、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_of | list | 条件付き | null | いずれか 1 つが設定されていればよい名前の空でないリスト | | required[].all_of | list | 条件付き | null | すべて設定されている必要がある名前の空でないリスト | | required[].message | string | — | "" | 未設定時に表示する案内 |

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 キーによる検証を行ってください。


受信メールの設定です。

email:
inbound:
enabled: true

email.inbound.enabled は boolean で、既定は false です。受信メールを処理するにはコンテナが必要です。静的サイト(type: web + assetscommand なし)で有効にすると、設定は受理されますがデプロイが deploy.config.invalid で失敗します。


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

verify:
- /dashboard
- /settings
  • 単一のパスは文字列でも 1 要素のリストでも指定できます
  • 最大 20 パス(前後の空白を除き、重複を除いた数)。各パスは / で始まり、// で始まらず、パス要素としての .. と制御文字を含まないこと
  • コンテナ / hybrid では公開ホスト経由で候補リビジョンから取得し、静的 / 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: us-oregon

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

論理キー表示名
jp-tokyo日本
us-oregon米国西海岸

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

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


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

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

デプロイモードは commandassetsfallback の有無から導出されます。直接は選べません。keelson status --json などの出力は deploy_mode の生ラベルを返します。

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

ルール内容
実行面が必要commandcrons、静的 assets のいずれかを指定する
type: web は cron 不可type: webcrons を併用しない
静的サイトにはコンテナがないcommand のない静的サイト・SPA では、cronsdb.migrateemail.inbound は動かない。宣言が受理されても実行されない(email はデプロイ失敗)ので、これらが要るならコンテナ型かハイブリッドにする
workers は廃止crons で書き直す
db.migratelibsql のみdb.mode: libsql が必要
ローカル SQLite は一時領域のみdb.local_sqlite.paths/tmp/ 配下か :memory:
assets.api にはバックエンドが必要トップレベルの command を設定する
hybrid には fallback が必要assetscommand が両方あるとき assets.fallback を設定する

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 アプリが pending 行を Managed SQLite に書き、cron が別インスタンスで処理します。共有する状態はローカルファイルではなく 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.modelibsqlnone で宣言する
廃止された databases がある削除する。永続データは Managed SQLite、一時 SQLite は db.local_sqlite で宣言
workers がある(workers_not_supported削除して crons で書き直す
commandpip install / npm install がある(command_installs_dependencies削除する。依存はビルド時に自動インストールされる
依存マニフェストがない(missing_dependency_manifestGo ではプロジェクトルートに go.mod を置く。Python または Node.js では、外部ライブラリを使う場合に適切なマニフェストを置く。標準ライブラリだけなら不要
runtimecommand の言語が合わない(runtime_command_mismatchランタイムを合わせるか、起動コマンドを直す
env の値が引用符なし(env_value_not_stringすべての値を引用符で囲む(数値・真偽値も)
環境変数名が KEELSON_ で始まる名前を変える。この名前空間はプラットフォーム予約
local_sqlite.paths/tmp/ の外/tmp/:memory:、または Managed SQLite を使う
commandcrons、静的 assets のどれもないいずれかを追加する
crons[].timeout が 600 を超える600 以下、かつプランの上限以下にする
assets.api/ で始まらない/api のような絶対パスにする
hybrid で assets.fallback がないindex.html などを設定する
ビルドが reserved_path_conflict で失敗ビルド出力直下の __keelson ディレクトリを改名する