はじめに
ドキュメントガイド
このドキュメントは、Keelson を使ってアプリをデプロイ・運用するための情報をまとめたものです。
Keelson のサービス概要、料金、セキュリティについては 公式サイト を参照してください。
Keelson の対応ランタイムや制約は Keelson Deploy Spec に1ページでまとまっています。以下の URL を AI エージェントに渡すことで、自分が作ったアプリが Keelson にデプロイできるかを確認してもらうことができます。
https://keelson.dev/ja/docs/reference/deploy-spec.txt
クイックスタート
このガイドでは、サンプルのWebアプリケーションをKeelsonにデプロイし、ブラウザでアクセスできることと、ログイン保護がデフォルトで有効になること を確認します。
このガイドを始める前に、次のものを用意してください。
- Node.js と npm — ターミナルで
node -v と npm -v を実行し、バージョンが表示されればOKです。インストールが必要な場合は Node.js公式サイト から推奨版(LTS)をダウンロードしてください。
- Keelson のアカウント — まだの方は keelson.dev からサインアップしてください。
- Claude Code や Codex など、Agent Skill を利用できるAIエージェント
インストール後、以下のコマンドで確認してください。
あなたのマシンをKeelsonのアカウントと紐付けます。以下のコマンドを実行してください。
ブラウザが開き、ログイン画面が表示されます。ログインが完了すると、ターミナルに戻って操作を続けられます。
Keelsonでは、デプロイやデプロイ状態の確認(ログの確認)をAIエージェントに任せることができます。AIエージェントがKeelsonを操作するための Skill を、以下のコマンドでインストールしてください。
npx skills add https://github.com/keelsonhq/agent-skills --skill xxxxxx
デプロイのテスト用に、シンプルなPython (FastAPI) アプリを用意しました。このサンプルアプリには、認証やセキュリティに関するコードは一切含まれていません。
- sample-web (GitHub) からZIPファイルをダウンロードし、デスクトップなどに展開します。
- 展開したフォルダを、普段お使いのAIエージェント(Claude Codeなど)で開きます。
ここがKeelsonの醍醐味です。複雑なコマンドを打つ必要はありません。AIエージェントのチャット欄に、一言こう指示してください。
指示の例:
「Skillを使って、このアプリをKeelsonにデプロイして」
AIエージェントが keelson.yaml を読み取り、自動的にビルドとデプロイを開始します。デプロイには通常1〜2分かかります。その間、AIがサーバーの構築やセキュリティ設定をすべて代行しています。成功すると、AIが以下のような公開URLを教えてくれます。
https://your-app-name.keelson.run/
デプロイされたURLをブラウザで開いてみましょう。
- ログイン済みブラウザ: アプリが表示されます。
- シークレットウィンドウ: URLを開くと、Keelsonのログイン画面が表示されます。
これが Security by Default です。アプリのコードに認証処理を書かなくても、Keelson がデフォルトでログイン保護を適用します。

基本コンセプト
Keelson は、社内やチームで共有するアプリを安全に公開するための実行基盤です。
ユーザーはアプリそのものの開発に集中し、公開・認証・共有に必要な仕組みは Keelson が引き受けます。このページでは、その考え方を説明します。
Keelson にデプロイされたアプリには、ユーザーのブラウザから直接アクセスが届くわけではありません。すべてのリクエストは、まず Keelson Proxy を通ります。

ユーザーが Keelson にデプロイされたアプリの URL を開くと、リクエストは次の順序で処理されます。
- 公開URLから、どのアプリへのアクセスかを特定する
- Keelson Proxy がログイン状態を確認する
- アプリへのアクセス権限を確認する
- 許可された場合のみ、リクエストをアプリへ転送する
- アプリのレスポンスをユーザーに返す
重要なのは、認証とアクセス制御の判断がアプリ本体の外側で行われることです。そのため、アプリ開発者は認証画面やセッション管理を毎回自前で実装しなくても、共有前提のアプリを安全に公開できます。
Keelson では、認証とアクセス制御の責務をアプリ本体の外側に分離しています。アプリは業務ロジックに集中しつつ、共有時のセキュリティはプラットフォーム側で一貫して扱えます。
Keelson では、アプリをデプロイした瞬間からログイン保護が有効になります。これを Security by Default と呼んでいます。
- セキュリティは後付けではなく、最初から組み込まれている
- 「動いた後に認証を足す」のではなく、「公開した時点で安全」
- Quickstart で体験した、シークレットウィンドウでのログイン画面がこの仕組みの結果
Keelson が単なるホスティングではなく、社内アプリのための実行基盤である理由がここにあります。
Keelson はアプリの入口でログイン保護とアクセス制御を提供します。アプリ内部の業務ルールに基づく制御が必要な場合は、アプリ側で追加の実装を行います。
Keelson を使うとき、開発者が関わる範囲と Keelson が引き受ける範囲は明確に分かれています。
| アプリが担うこと | Keelson が担うこと |
|---|
| UI | デプロイ先の用意 |
| 業務ロジック | 公開URL |
| API | ログイン保護 |
| データ処理 | アプリへのアクセス制御 |
| 実行環境の管理 |
この分担があるため、アプリの開発者はインフラやセキュリティの構築に時間を割く必要がありません。
Keelson は、ローカルで一人だけが使うアプリのための基盤ではありません。チームや社内で安全に共有することを前提に設計されています。
そのため、以下の機能がプラットフォームに組み込まれています。
- 公開URL — デプロイするだけでチームに共有できるURLが発行される
- ログイン保護 — 許可されたメンバーだけがアクセスできる
- メンバー管理 — 誰がどのアプリにアクセスできるかを制御できる
これらの詳細は、以下のページで説明しています。
最初はアプリを載せて動かすことに集中すれば十分です。
Keelson の設定は段階的に進められます。クイックスタート で触れた体験は最小構成の入り口であり、必要に応じて以下のような設定をあとから追加できます。
アプリを作る
対応アプリ種類
Keelson は、社内やチームで共有する Web アプリ・API・定期実行ジョブを安全にデプロイ・公開するための実行基盤です。
AI(ChatGPT、Claude、Manus など)で生成した小〜中規模の業務アプリに特に向いています。
想定しているアプリの例:
- 社内ツール — 顧客管理、案件管理、在庫管理など
- 管理画面 — データの閲覧・編集用ダッシュボード
- 連携アプリ — Slack / Notion / Google Sheets との自動連携
- 軽量な自動化処理 — CSV取込、定期集計、通知バッチ
- バックオフィス向けアプリ — 承認申請、日報・レポート生成
フォーム+一覧表示+SQLite。CRUD 操作が中心の典型的な業務アプリで、Keelson のデータ永続化(/data)がそのまま使えます。
テキスト検索 UI+バックエンド API。社内ナレッジを検索・閲覧するためのアプリで、認証付きで安全に社内公開できます。
ファイルアップロード+加工処理+ダウンロード。定型業務の自動化に最適で、Keelson なら非エンジニアにも URL を共有するだけで使ってもらえます。
フォーム送信+ステータス管理+通知。ワークフロー系の小さなアプリで、チーム内のメンバー管理と組み合わせてアクセス制御できます。
入力フォーム+テンプレート出力。日次・週次の報告を定型化するアプリで、定期実行ジョブ(cron)と組み合わせて自動集計も可能です。
Webhook 受信+API 呼び出し。外部サービスとのデータ連携を行うアプリで、Web アプリ+定期ジョブの組み合わせで構成できます。
cron ジョブのみで動く構成。売上集計、ログ解析、通知送信など、UI なしで定期実行だけを行うケースにも対応しています。
チャット UI+LLM API 呼び出し。社内向けの AI アシスタントを、認証付きで安全にチームに提供できます。
Keelson は特定のフレームワーク専用の PaaS ではありません。HTTP サーバーとして起動する標準的な構成のアプリであれば、フレームワークを問わず動かせます。
| ランタイム | 用途 |
|---|
python-slim | 軽量な Python アプリ(API、テキスト処理など) |
python-media | メディア処理向け Python(画像・動画ライブラリ含む) |
node-slim | 軽量な Node.js アプリ |
node-media | メディア処理向け Node.js |
go-slim | 軽量な Go アプリ |
go-media | メディア処理向け Go |
- Web アプリ — HTTP サーバーとして起動し、ブラウザからアクセスするもの
- API サーバー — JSON API を提供するバックエンド
- 定期実行ジョブ(cron) — スケジュールに従って定期的にコマンドを実行するもの
- ワーカープロセス — Web アプリと並行して動くバックグラウンド処理
フレームワークの例: FastAPI、Flask、Express、Next.js、Hono、Gin など。keelson.yaml の command で起動できるものであれば動作します。
以下に当てはまるなら、Keelson が適しています。
- 社内利用が前提 — チームや社内のメンバーに限定して公開したい
- 認証をかけて安全に公開したい — ログイン保護をアプリに実装せずに済ませたい
- 小さなアプリを複数動かしたい — 1つのワークスペースで複数アプリを管理できる
- SQLite やファイル保存を使いたい —
/data への永続化がプラットフォーム標準で使える
- AI に作らせたアプリをまず動かしたい — Dockerfile 不要、
keelson.yaml だけでデプロイできる
- 開発者以外にも見せたい — URL を共有するだけで、非エンジニアもブラウザからアクセスできる
以下のようなケースには、Keelson は最適ではありません。
- 超高トラフィックな一般公開サービス — 大規模なコンシューマー向けサービスは想定外
- 厳しい低レイテンシが必要な edge 寄りの用途 — CDN エッジでの実行には非対応
- 複雑な分散システム — マイクロサービス間の高度なオーケストレーションには向かない
- GPU 前提の重い推論基盤 — GPU インスタンスは提供していない
- 特殊なミドルウェア前提の構成 — Redis、PostgreSQL(外部)、Kafka などを自前で構成する必要がある場合
- 厳密なネットワーク制御や専有インフラが必須 — VPC ピアリング、専用ノードなどが初期要件の場合
以下の質問に順番に答えてください。3分で判断できます。
1. 利用者は社内・チームメンバーが中心ですか?
→ いいえ → 不特定多数への公開サービスには向いていません
2. アプリは Web UI または API を提供しますか?
→ いいえ → 定期実行ジョブ(cron)だけの構成でも対応可能です。それ以外の形態は対象外です
3. Node.js / Python / Go のいずれかで動きますか?
→ いいえ → 現時点ではこの3つのランタイムに対応しています
4. GPU や特殊なミドルウェア(Redis、Kafka など)は必要ですか?
→ はい → 現時点では対応していません
5. 専有インフラや厳密なネットワーク制御は初期要件ですか?
→ はい → Enterprise プランでの対応を検討中です。お問い合わせください
すべてクリアした場合 → Keelson で動かせます。
もっとも単純な構成でデプロイする例を示します。
ディレクトリ構成:
keelson.yaml:
command: "pip install --user -r requirements.txt && python app.py"
app.py:
from fastapi import FastAPI
return {"message": "Hello from Keelson"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
ディレクトリ構成:
keelson.yaml:
command: "npm install && npm start"
index.js:
const express = require("express");
const port = process.env.PORT || 8080;
app.get("/", (req, res) => {
res.json({ message: "Hello from Keelson" });
app.listen(port, "0.0.0.0", () => {
console.log(`Listening on port ${port}`);
デプロイが完了すると、https://my-app.keelson.run/ のような URL が発行されます。この URL にアクセスすると、ログイン済みのメンバーだけがアプリを利用できます。
不要です。keelson.yaml でランタイムと起動コマンドを指定するだけでデプロイできます。Keelson がビルドと実行環境の構築を行います。
はい。keelson.yaml で assets を設定すれば、ビルド済みの静的ファイルをホストできます。
はい。UI を持たない JSON API サーバーも問題なくデプロイできます。
ビルドとランタイム
Keelson にアプリをデプロイすると、以下の流れで公開されます。
ソースコード → CLI / AI エージェントが送信 → Keelson がビルド → コンテナとして起動 → 公開 URL 発行
- ソースコードを送る — CLI(
keelson deploy)または AI エージェントの Skill がソースコードと keelson.yaml を Keelson に送信します
- Keelson がビルドする — 指定されたランタイムに基づいて、依存関係のインストールと実行環境の構築が自動で行われます
- コンテナとして起動する — ビルドされたアプリが
keelson.yaml の command に従って起動します
- 公開 URL が発行される —
https://<slug>.keelson.run/ の URL が払い出されます
- 認証・アクセス制御が適用される — すべてのリクエストは認証プロキシを経由し、ログイン済みの許可されたメンバーだけがアクセスできます
開発者がビルドやインフラの設定を行う必要はありません。keelson.yaml に必要な情報を記述すれば、あとは Keelson が処理します。
Keelson では、1つのアプリが1つの実行単位になります。アプリの種類に応じて、以下の形態で動作します。
HTTP サーバーとして起動し、リクエストを受け付け続けます。ブラウザからアクセスする UI や、JSON API を返すバックエンドがこの形態です。
スケジュールに従って定期的にコマンドを実行します。集計処理、通知送信、データ同期などに使います。Web アプリとは独立して定義でき、Web アプリを持たない cron だけの構成も可能です。
Web アプリと並行して動くバックグラウンド処理です。キュー処理やデータの非同期処理に使います。Web アプリが存在する場合にのみ追加できます。
これらは組み合わせて使えます。
| 構成 | 説明 |
|---|
| Web アプリのみ | もっとも一般的な構成 |
| Web アプリ + cron | アプリに加えて定期処理を実行 |
| Web アプリ + ワーカー | アプリに加えてバックグラウンド処理を実行 |
| cron のみ | UI なしで定期実行だけを行う |
アプリには3つの状態があります。
- running — 実行中。Active Apps 枠を消費
- sleep — 自動スリープ。アクセス時に自動起動
- stop — 手動停止。ダッシュボードから手動で起動
再デプロイすると、新しいコードでアプリが置き換えられます。/data に保存されたデータは再デプロイ後も保持されます。
現時点で以下のランタイムに対応しています。
| ランタイム | 言語 | 用途 |
|---|
python-slim | Python | 軽量(API、テキスト処理、自動化など) |
python-media | Python | メディア処理向け(画像・動画・PDF ライブラリを含む) |
node-slim | Node.js | 軽量(Web アプリ、API など) |
node-media | Node.js | メディア処理向け(画像・PDF 処理ライブラリを含む) |
go-slim | Go | 軽量 |
go-media | Go | メディア処理向け |
keelson.yaml の runtime フィールドで指定します。
依存関係は command 内でインストールします。
Python:
command: "pip install --user -r requirements.txt && python app.py"
Node.js:
command: "npm install && npm start"
Go:
# Keelson 側で deploy 時に `./app` がビルドされます。
keelson.yaml の command で起動コマンドを指定します。
Web アプリは環境変数 PORT で指定されたポートで HTTP リクエストを待ち受けてください。keelson.yaml の env で設定します。
アプリ側のコード例:
port = int(os.environ.get("PORT", 8080))
const port = process.env.PORT || 8080;
HTTP サーバーは必ず 0.0.0.0 で listen してください。127.0.0.1 や localhost ではリクエストが届きません。
uvicorn.run(app, host="0.0.0.0", port=port)
app.listen(port, "0.0.0.0");
Keelson のデプロイには2つのフェーズがあります。
| ビルド時 | 実行時 |
|---|
| 何が起きるか | ソースコードの取得、依存関係のインストール、実行環境の構築 | アプリの起動、リクエストの処理 |
| 環境変数 | keelson.yaml の env で定義した値が利用可能 | 同じ env の値に加え、Keelson が設定するシステム環境変数が利用可能 |
| ネットワーク | 外部パッケージレジストリ(npm, PyPI など)への通信が可能 | 外部 API への通信が可能 |
| データ永続化 | /data はまだ利用できない | /data に書き込んだデータは永続化される |
- ビルドログ — 依存関係のインストールやビルド処理の出力。ビルドが失敗した場合の原因特定に使います
- 実行ログ — アプリの標準出力・標準エラー出力。実行中のエラーやリクエスト処理の確認に使います
いずれもダッシュボードから確認できます。
- CPU とメモリはプランの Compute Class に応じて割り当てられます
- リソースはワークスペース内の全アプリに共通の性能帯が適用されます(アプリごとの個別設定ではありません)
- root 権限は使えません — アプリは非 root ユーザーとして実行されます
- systemd やデーモン管理は使えません — プロセス管理は
command で起動した単一プロセスが基本です
- コンテナ外への永続書き込みはできません — データを永続化するには
/data ディレクトリを使ってください。それ以外のパスへの書き込みは再デプロイ時に失われます
- HTTP リクエストには一般的なタイムアウトが適用されます
- 定期実行ジョブ(cron)の
timeout は 1〜3,600 秒で設定可能です(デフォルト: 300 秒)
- アプリから外部の API やサービスへの通信(Egress)はデフォルトで可能です
- Business プラン以上では、通信先をホスト名単位で制限できます
多くのフレームワークはデフォルトで 127.0.0.1(localhost)で listen します。Keelson ではリクエストがコンテナ外から届くため、0.0.0.0 を明示する必要があります。
uvicorn.run(app, host="127.0.0.1", port=port)
uvicorn.run(app, host="0.0.0.0", port=port)
ポート番号をコードに直接書くと、Keelson の環境で一致しない場合があります。環境変数 PORT から読み取ってください。
app.listen(process.env.PORT || 8080);
command に依存関係のインストールを含め忘れると、実行時にモジュールが見つからずエラーになります。
command: "pip install --user -r requirements.txt && python app.py"
エントリポイントのファイル名やパスが間違っていると、アプリが起動しません。ローカルで同じコマンドを実行して動作を確認してください。
よくある原因:
- ローカルにだけ存在するファイルやディレクトリに依存している
- 環境変数が設定されていない
localhost 前提の外部サービス接続(ローカル DB など)
- ビルドログを確認する — ダッシュボードでビルドの出力を確認し、依存関係のインストールが成功しているか確認
- 実行ログを確認する — アプリの起動時エラーやランタイムエラーがないか確認
keelson.yaml を確認する — runtime、command、env の設定が正しいか見直す
必要ファイル:
keelson.yaml:
command: "pip install --user -r requirements.txt && python app.py"
requirements.txt:
app.py:
from fastapi import FastAPI
return {"message": "Hello from Keelson"}
if __name__ == "__main__":
port = int(os.environ.get("PORT", 8080))
uvicorn.run(app, host="0.0.0.0", port=port)
必要ファイル:
keelson.yaml:
command: "npm install && npm start"
package.json:
"scripts": { "start": "node index.js" },
"dependencies": { "express": "^4" }
index.js:
const express = require("express");
const port = process.env.PORT || 8080;
app.get("/", (req, res) => {
res.json({ message: "Hello from Keelson" });
app.listen(port, "0.0.0.0", () => {
console.log(`Listening on port ${port}`);
デプロイが完了すると https://my-app.keelson.run/ のような URL が発行されます。ブラウザでアクセスし、{"message": "Hello from Keelson"} が表示されれば成功です。
Keelson は AI で生成したアプリをそのままデプロイできるように設計されています。以下のようなプロンプトを AI に渡すと、Keelson 互換のアプリを生成しやすくなります。
Keelson で動く FastAPI アプリを作ってください。環境変数 PORT で指定されたポートで 0.0.0.0 を listen してください。
SQLite データベースを /data/main.db に保存してください。/data は永続化されるディレクトリです。
毎日午前3時にデータを集計するバッチ処理を追加してください。メインの Web アプリとは別に cron ジョブとして実行します。
このアプリ用の keelson.yaml を作成してください。ランタイムは python-slim、起動コマンドは pip install --user -r requirements.txt && python app.py です。
AI にアプリを生成させるとき、以下の3点を伝えるとスムーズです。
- ポート —
PORT 環境変数から読み取り、0.0.0.0 で listen する
- データ保存先 — ファイルや SQLite は
/data ディレクトリに置く
- 起動方法 — 単一のコマンドで起動できるようにする
- 標準的な Node.js / Python / Go アプリ — 特殊なビルドツールチェーンが不要
- AI で生成したアプリをすぐに動かしたい — Dockerfile を書かずにデプロイできる
- 依存関係が pip / npm / go mod で管理されている — command 内でインストールするだけ
- HTTP サーバーとして起動するアプリ — ポートを listen するだけで公開される
- Dockerfile による細かいビルド制御が必要 — Keelson は独自の Dockerfile を使えません
- システムパッケージの追加インストールが必要 —
apt-get 等で追加するパッケージが多い場合は media ランタイムで対応できるか確認してください
- root 権限やデーモンプロセスが前提 — アプリは非 root で動作し、systemd は使えません
- ビルド成果物を細かくキャッシュしたい — ビルドキャッシュの制御は Keelson に委ねる形です
使えません。Keelson はランタイムを選択し、command で起動する方式です。Dockerfile の代わりに keelson.yaml でランタイムと起動コマンドを指定します。
依存関係の量によりますが、一般的な小〜中規模のアプリであれば1〜2分程度です。
はい。アプリから外部への通信(Egress)はデフォルトで可能です。Business プラン以上では通信先をホスト名単位で制限することもできます。
ダッシュボードでビルドログを確認してください。AI エージェントにログを渡して「このビルドエラーを修正して」と依頼するのも有効です。
ストレージとデータ
Keelson のアプリには、2種類のファイルシステム領域があります。
| 領域 | 再デプロイ時 | 用途 |
|---|
| アプリディレクトリ(ソースコード等) | 置き換わる | アプリのコード、依存パッケージ |
/data | 残る | データベース、アップロードファイル、永続データ |
永続化したいものは /data に置いてください。 それ以外の場所に書き込んだデータは、再デプロイ時に失われます。
/data はアプリごとに分離されており、他のアプリからはアクセスできません。ワークスペース単位で容量が管理され、データは東京リージョンに保存されます。
/data には、アプリが必要とするあらゆるファイルを保存できます。
- SQLite データベース — 顧客管理、案件管理、ログなどのアプリデータ
- アップロードファイル — ユーザーがフォームから送信した画像、PDF、CSV など
- 生成済みレポート — 集計結果やエクスポートファイル
- キャッシュデータ — 外部 API のレスポンスや計算結果の再利用
- 設定ファイル — アプリが実行時に生成する設定やステートファイル
社内ツールでよくある使い方:
/data/main.db # アプリのメインデータベース
/data/uploads/ # ユーザーがアップロードしたファイル
/data/reports/ # 日次・週次で生成したレポート
以下は /data 以外の方法を検討してください。
- 巨大なバイナリファイル — 動画ファイルや大容量のデータセットはストレージ容量を圧迫します。外部のオブジェクトストレージ(S3 互換サービスなど)を検討してください
- 一時ファイル — 処理中だけ必要なファイルは
/tmp を使い、処理後に削除してください
- 再生成可能なキャッシュ — npm の
node_modules やビルド成果物は /data に置く必要はありません
- 大規模ログの長期保存 — アプリログは Keelson のログ機能で閲覧できます。独自の大量ログを
/data に蓄積するとストレージを消費します
- 高い可搬性が求められるデータ — 他のシステムとの頻繁なデータ連携が必要な場合は、外部データベースが適しています
SQLite は Keelson でもっとも推奨されるデータベースです。外部の DB サーバーを用意する必要がなく、/data にファイルを置くだけで使えます。
- セットアップ不要 — DB サーバーの構築・接続設定が不要
- AI 生成との相性 — ChatGPT や Claude が生成するアプリの多くは SQLite を使う構成になる
- 永続化が自動 —
/data に置けば再デプロイ後もデータが残る
- バックアップ対象 — 日次スナップショットの対象に含まれる
複数のデータベースを使うこともできます。
- 単一インスタンス前提 — Keelson のアプリは1つのインスタンスで動作します。複数インスタンスからの同時書き込みを考慮する必要はありません
- 書き込みが非常に多い場合 — 秒間数百回以上の書き込みが発生するようなケースでは、外部データベース(PostgreSQL など)を検討してください
- データ量が大きい場合 — 数 GB を超える SQLite ファイルはパフォーマンスに影響する可能性があります。データ量が大きくなる見込みがある場合は、早めに外部 DB への移行を計画してください
ユーザーがアップロードしたファイルは /data 配下に保存します。
│ ├── a1b2c3d4-report.pdf
ユーザーがアップロードしたファイル名をそのまま使うと、同名ファイルが上書きされます。UUID やタイムスタンプをプレフィックスに付けてください。
def save_upload(file, upload_dir="/data/uploads"):
filename = f"{uuid.uuid4().hex}_{file.filename}"
path = os.path.join(upload_dir, filename)
with open(path, "wb") as f:
ストレージ容量はプランによって異なります(Starter: 10 GB 〜 Business: 100 GB)。この容量には /data のデータ、スナップショット、ログの合計が含まれます。
不要になったファイルは定期的に削除する仕組みを入れておくと安心です。定期実行ジョブ(cron)で古いファイルを自動削除するのも有効です。
- アップロードされたファイルの拡張子やサイズを検証してください
- ユーザーが指定したファイル名をそのままパスに使わないでください(ディレクトリトラバーサルの防止)
- Keelson の認証プロキシにより、アプリ自体へのアクセスは保護されていますが、アプリ内でのファイルアクセス制御はアプリ側の責務です
Keelson は /data のスナップショットを毎日自動で取得します。保持日数はプランによって異なります。
| プラン | スナップショット保持 |
|---|
| Starter | 1日分 |
| Plus | 3日分 |
| Team | 7日分 |
| Business | 14日分 |
手動スナップショットは、SQLite 管理画面から任意のタイミングで取得できます(全プラン)。
| 対象 | バックアップされるか |
|---|
/data 配下のファイル(SQLite、アップロードファイルなど) | される |
| アプリのソースコード | されない(デプロイ時に毎回送信される) |
| 環境変数 | されない(ダッシュボードで管理) |
アプリのコードは Git などのバージョン管理で保持し、データは Keelson のスナップショットで保護されます。
スナップショットからの復元が必要な場合は、ダッシュボードから操作できます。復元はアプリ単位で行われ、他のアプリのデータには影響しません。
/data + SQLite は多くの社内アプリに十分ですが、以下のケースでは外部サービスの利用を検討してください。
| ケース | 理由 | 選択肢 |
|---|
| データ量が数 GB を超える | SQLite のパフォーマンスが低下する可能性 | PostgreSQL(アドオンで専用 DB を利用可能) |
| 同時書き込みが非常に多い | SQLite はライター1つの制約がある | PostgreSQL、MySQL |
| BI や基幹系と直接連携する | データを外部システムから参照する必要がある | 共有の PostgreSQL、データウェアハウス |
| 厳密な運用要件がある | ポイントインタイムリカバリや複雑なレプリケーションが必要 | マネージド PostgreSQL |
| 大容量ファイルを大量に扱う | ストレージ容量を超える可能性 | S3 互換オブジェクトストレージ |
顧客管理や在庫管理など。SQLite にデータを保存し、アップロードファイルも /data に配置。
CSV の取込・加工を行うアプリ。入力と出力を分離して管理。
└── processed/ # 処理済みの入力(アーカイブ)
社内 RAG や AI チャットのバックエンド。ナレッジベースのデータや添付資料を /data に配置。
├── knowledge.db # ナレッジのメタデータ
├── documents/ # 参照ドキュメント
└── embeddings.cache # 前処理済みの埋め込みキャッシュ
定期実行ジョブで集計し、結果を /data に保存。Web UI から閲覧。
/tmp やアプリのソースコードと同じディレクトリに書き込んだデータは、再デプロイ時に失われます。永続化したいデータは必ず /data に置いてください。
db_path = "/data/main.db"
SQLite のパスを /data 以外に設定すると、デプロイのたびにデータが消えます。keelson.yaml の databases[].path が /data/ で始まっていることを確認してください。
スナップショットは日次で自動取得されますが、保持日数はプランによって異なります。重要なデータを扱う場合は、プランの保持日数を確認し、必要に応じてアプリ側でもエクスポート機能を用意してください。
不要になったファイルを削除せずに放置すると、ストレージ容量を圧迫します。ストレージ容量にはスナップショットやログも含まれるため、アプリデータだけで上限いっぱいにならないよう注意してください。
/Users/tanaka/Desktop/data.db のようなローカルパスがコードに残っていると、Keelson 上では動作しません。環境変数または /data への相対的なパスを使ってください。
db_path = os.environ.get("DB_PATH", "/data/main.db")
DB_PATH = os.environ.get("DB_PATH", "/data/main.db")
conn = sqlite3.connect(DB_PATH)
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
conn.execute("INSERT INTO items (name) VALUES (?)", ("サンプルアイテム",))
keelson.yaml:
command: "pip install --user -r requirements.txt && python app.py"
const Database = require("better-sqlite3");
const path = process.env.DB_PATH || "/data/main.db";
const db = new Database(path);
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
db.prepare("INSERT INTO items (name) VALUES (?)").run("サンプルアイテム");
from fastapi import FastAPI, UploadFile
UPLOAD_DIR = os.environ.get("UPLOAD_DIR", "/data/uploads")
os.makedirs(UPLOAD_DIR, exist_ok=True)
async def upload(file: UploadFile):
filename = f"{uuid.uuid4().hex}_{file.filename}"
filepath = os.path.join(UPLOAD_DIR, filename)
with open(filepath, "wb") as f:
content = await file.read()
return {"filename": filename, "path": filepath}
const express = require("express");
const multer = require("multer");
const crypto = require("crypto");
const path = require("path");
const fs = require("fs");
const uploadDir = process.env.UPLOAD_DIR || "/data/uploads";
fs.mkdirSync(uploadDir, { recursive: true });
const storage = multer.diskStorage({
filename: (req, file, cb) => {
const prefix = crypto.randomBytes(8).toString("hex");
cb(null, `${prefix}_${file.originalname}`);
app.post("/upload", multer({ storage }).single("file"), (req, res) => {
res.json({ filename: req.file.filename, path: req.file.path });
- 社内アプリの業務データ — 顧客情報、案件、在庫など、SQLite で十分な規模
- ユーザーがアップロードするファイル — PDF、CSV、画像など
- AI で生成したアプリをすぐに動かしたい — 外部 DB の設定なしでデータ永続化が使える
- 小さなアプリを複数動かしたい — アプリごとに
/data が分離されている
- データ量が数十 GB を超える — ストレージ容量とパフォーマンスの両面で外部 DB を検討
- 複数システムからの同時アクセスが必要 —
/data はアプリ内からのみアクセス可能
- ポイントインタイムリカバリが必須 — スナップショットは日次のため、より細かい復元が必要ならマネージド DB を検討
- BI ツールや基幹システムとの直接連携 — 外部からクエリできるデータベースが必要
プランによって異なります(Starter: 10 GB 〜 Business: 100 GB)。この容量には /data のデータ、スナップショット、ログの合計が含まれます。追加ストレージはアドオンで購入できます。
/data に保存したデータは消えません。アプリのソースコード領域は置き換わりますが、/data は再デプロイ後もそのまま残ります。
アプリ内で完結するデータベース(SQLite など)はそのまま使えます。外部の PostgreSQL や MySQL に接続することも可能です。アドオンで専用 PostgreSQL を利用することもできます。
できません。/data はアプリごとに完全に分離されています。アプリ間でデータを共有する必要がある場合は、API 経由でやり取りしてください。
データ量によりますが、一般的な社内アプリの規模であれば数分で完了します。
「データベースは SQLite を使い、/data/main.db に保存してください」
「アップロードされたファイルは /data/uploads/ に UUID 付きのファイル名で保存してください」
「環境変数 DB_PATH からデータベースのパスを読み取るようにしてください。デフォルトは /data/main.db です」
定期実行ジョブ(Scheduled Jobs)
Keelson では、アプリの公開だけでなく、コードを定期的に自動実行できます。Web アプリと同じコードベース・同じ keelson.yaml でジョブを管理でき、社内業務の自動化に使えます。
代表的なユースケース:
- 毎朝のレポート生成 — 売上や KPI を集計して
/data に保存
- 毎時間の API 同期 — 外部サービスからデータを取得して DB を更新
- 毎日の Slack 通知 — 期限切れタスクや承認待ちのリマインド
- 夜間の CSV 取込 — アップロードされた CSV を一括処理
- 定期的なデータクリーンアップ — 古いログや一時ファイルの削除
Scheduled Jobs は Active Apps の枠を消費しません。Web アプリとは独立してカウントされます。
keelson.yaml の crons にジョブを定義する
- デプロイすると、Keelson が定期実行ジョブとして登録する
- 指定したスケジュールに従って、コマンドが自動で実行される
- 実行ごとにログが記録される
ジョブの動作は、Web アプリの有無によって異なります。
| 構成 | 動作 |
|---|
cron のみ(command なし) | ジョブごとに独立して実行される |
Web アプリ + cron(command あり) | Web アプリと同じ実行環境内でジョブが動く |
どちらの構成でも、ジョブの定義方法は同じです。
- 実行結果(成功・失敗)はダッシュボードで確認できます
- 標準出力・標準エラーがログとして記録されます
- 実行回数は成功・失敗・リトライ・手動実行をすべて含みます
keelson.yaml の crons セクションでジョブを定義します。
command: "python report.py"
| フィールド | 必須 | デフォルト | 説明 |
|---|
name | はい | — | ジョブ名。小文字英数字とハイフン、1〜63 文字 |
schedule | はい | — | cron 式(5フィールド) |
command | はい | — | 実行するコマンド |
timeout | いいえ | 300 秒 | タイムアウト。1〜3,600 秒 |
1つのアプリに最大10個のジョブを定義できます。
command: "python sync.py"
command: "python cleanup.py"
command: "python weekly_report.py"
トップレベルの env で定義した環境変数は、ジョブの実行時にも利用できます。
SLACK_WEBHOOK_URL: "https://hooks.slack.com/..."
command: "python notify.py"
スケジュールは5フィールドの cron 式で指定します。
│ │ │ │ ┌───── 曜日(0-6、0=日曜)
| やりたいこと | cron 式 | 説明 |
|---|
| 毎日 9:00 | 0 9 * * * | 毎日午前9時に実行 |
| 30分ごと | */30 * * * * | 毎時0分と30分に実行 |
| 毎時間 | 0 * * * * | 毎時0分に実行 |
| 10分ごと | */10 * * * * | 10分間隔で実行 |
| 平日のみ 9:00 | 0 9 * * 1-5 | 月〜金の午前9時に実行 |
| 毎月1日 0:00 | 0 0 1 * * | 月初に実行 |
| 毎日深夜 3:00 | 0 3 * * * | 夜間バッチ向き |
| 毎分 | * * * * * | テスト・デバッグ用 |
- 入力:
/data/sales/ 配下の CSV ファイル
- 処理: 当日分を集計し、合計・件数を計算
- 出力:
/data/reports/daily-sales-YYYY-MM-DD.json に保存
command: "python aggregate_sales.py"
- 入力: 外部サービスの REST API
- 処理: 最新データを取得し、差分を SQLite に反映
- 出力:
/data/main.db の該当テーブルが更新される
command: "python sync_from_api.py"
- 入力: SQLite のレコード
- 処理:
expired_at が過去のレコードを削除
- 出力: 削除件数をログに出力
command: "python cleanup_expired.py"
- 入力: SQLite の週次データ
- 処理: テンプレートからレポートを生成
- 出力:
/data/reports/weekly-YYYY-WXX.pdf に保存
command: "python generate_weekly_report.py"
ジョブは同じスケジュールで繰り返し実行されます。途中で失敗して再実行されても、データが二重に作成されないように設計してください。
db.execute("INSERT INTO reports (date, total) VALUES (?, ?)", (today, total))
INSERT INTO reports (date, total) VALUES (?, ?)
ON CONFLICT(date) DO UPDATE SET total = excluded.total
デフォルトのタイムアウトは 300 秒(5分)です。処理に時間がかかる場合は timeout を明示的に設定してください。最大 3,600 秒(1時間)まで指定できます。
ジョブが失敗しても自動リトライは行われません。冪等に設計しておけば、次のスケジュールで自然にリカバリされます。重要なジョブでは、失敗時に Slack 通知を送るなどの仕組みを入れておくと安心です。
外部 API を呼び出すジョブでは、レート制限に注意してください。短い間隔(毎分など)で外部 API を叩くと、制限に引っかかる場合があります。
SQLite への書き込みを伴うジョブが、Web アプリと同じデータベースを使う場合、書き込みのタイミングが重なる可能性があります。SQLite は単一ライターの制約があるため、短時間の待ちが発生することがあります。通常の社内ツール規模であれば問題になりませんが、書き込み頻度が高い場合は注意してください。
ジョブの標準出力(print や console.log)と標準エラーはすべてログとして記録されます。ダッシュボードからジョブ単位で確認できます。
デバッグ時は、処理の進捗やデータの状態を print で出力しておくと原因特定がしやすくなります。
print(f"[{datetime.datetime.now()}] ジョブ開始")
print(f"[{datetime.datetime.now()}] ジョブ完了")
- 実行ログを見る — エラーメッセージやスタックトレースを確認
- 環境変数を確認する — API キーやデータベースパスが正しいか
- タイムアウトを確認する — 処理が
timeout の秒数内に終わっているか
- 手元で再現する — 同じコマンドをローカルで実行してみる
Keelson のジョブログをそのまま AI エージェントに渡せば、エラーの原因特定と修正を依頼できます。
「このジョブのエラーログを確認して、原因を特定して修正してください」
AI エージェントがログを読み、コードの修正と再デプロイまで一連で対応できます。
Keelson の強みは、Web アプリ・定期ジョブ・永続データを1つのアプリ内で組み合わせられることです。
Web アプリで設定やデータを入力し、重い処理は夜間ジョブに任せる構成です。
command: "pip install --user -r requirements.txt && python app.py"
DB_PATH: "/data/sales.db"
- name: nightly-aggregate
command: "python aggregate.py"
- 日中: 管理画面から売上データを入力
- 深夜: ジョブが集計処理を実行し、レポートデータを更新
- 翌朝: 管理画面で集計結果を閲覧
ユーザーが Web UI から CSV をアップロードし、ジョブが定期的に処理する構成です。
command: "python process_inbox.py"
- Web アプリ: CSV を
/data/inbox/ にアップロード
- ジョブ(30分ごと):
/data/inbox/ の未処理ファイルを処理し、結果を /data/outbox/ に保存
- Web アプリ: 処理結果を一覧表示・ダウンロード
ジョブが毎朝データを要約し、Web アプリで閲覧する構成です。
command: "python generate_summary.py"
- ジョブ(毎朝 7:00): 前日のデータを AI API で要約し、結果を SQLite に保存
- Web アプリ: 要約を日付別に閲覧
cron 式のフィールド順(分・時・日・月・曜日)を間違えやすいです。「9時に実行したい」場合は 0 9 * * * です。9 0 * * * とすると毎日 0:09 に実行されます。
ジョブの出力を /tmp に保存すると、次回の実行時には消えている場合があります。結果を残したい場合は /data に保存してください。
外部 API を呼び出すジョブで、API キーをローカルの環境変数にだけ設定していると、Keelson 上では認証エラーになります。keelson.yaml の env またはダッシュボードで環境変数を設定してください。
毎分実行のジョブで外部 API を大量に呼ぶと、レート制限で失敗します。実行間隔を広げるか、ジョブ内でリクエスト数を制御してください。
Scheduled Jobs にはプランごとに月間の実行回数上限があります(Starter: 3,000回 〜 Business: 80,000回)。上限に達すると、当月の残りの実行はスキップされます。毎分実行(* * * * *)は月間約43,200回になるため、テスト以外では避けてください。
Web アプリなしで、ジョブだけを動かす最小構成です。
command: "python heartbeat.py"
heartbeat.py:
print(f"OK: {datetime.datetime.now()}")
import sqlite3, json, os, datetime
DB_PATH = os.environ.get("DB_PATH", "/data/main.db")
REPORT_DIR = "/data/reports"
os.makedirs(REPORT_DIR, exist_ok=True)
conn = sqlite3.connect(DB_PATH)
today = datetime.date.today().isoformat()
"SELECT COUNT(*), SUM(amount) FROM sales WHERE date = ?", (today,)
report = {"date": today, "count": row[0], "total": row[1] or 0}
report_path = os.path.join(REPORT_DIR, f"daily-{today}.json")
with open(report_path, "w") as f:
json.dump(report, f, ensure_ascii=False)
const Database = require("better-sqlite3");
const DB_PATH = process.env.DB_PATH || "/data/main.db";
const API_URL = process.env.SYNC_API_URL;
const res = await fetch(API_URL);
const items = await res.json();
const db = new Database(DB_PATH);
CREATE TABLE IF NOT EXISTS synced_items (
synced_at DATETIME DEFAULT CURRENT_TIMESTAMP
const stmt = db.prepare(`
INSERT INTO synced_items (id, data) VALUES (?, ?)
ON CONFLICT(id) DO UPDATE SET data = excluded.data, synced_at = CURRENT_TIMESTAMP
for (const item of items) {
stmt.run(item.id, JSON.stringify(item));
console.log(`同期完了: ${items.length} 件`);
console.error("同期失敗:", err);
import os, json, urllib.request, datetime
SLACK_WEBHOOK = os.environ["SLACK_WEBHOOK_URL"]
"text": f"日次レポート準備完了: {datetime.date.today()}"
req = urllib.request.Request(
data=json.dumps(message).encode(),
headers={"Content-Type": "application/json"},
urllib.request.urlopen(req)
keelson.yaml:
SLACK_WEBHOOK_URL: "https://hooks.slack.com/services/..."
command: "python notify.py"
- 定型業務の自動化 — 毎日・毎時間の集計、通知、データ同期
- Web アプリと組み合わせた業務フロー — 日中は入力、夜間にバッチ処理
- 外部サービスとの定期的なデータ連携 — API からの取得や Webhook 送信
- 社内データの定期メンテナンス — 古いデータの削除、レポート生成
- リアルタイム処理 — イベント駆動で即座に反応する必要がある場合は、Web アプリ内で処理してください
- 1時間を超える長時間処理 — タイムアウトの上限は 3,600 秒です
- 複雑なジョブチェーン — ジョブ間の依存関係やワークフロー制御が必要な場合は、専用のワークフローエンジンを検討してください
- 秒単位の精度が必要 — cron 式は分単位の指定です
されません。次のスケジュールで再実行されます。ジョブを冪等に設計しておけば、自然にリカバリされます。
はい。keelson.yaml で command を省略し、crons だけを定義すれば、ジョブ専用のアプリとしてデプロイできます。
ダッシュボードから、ジョブごとの実行履歴・成功/失敗のステータス・ログを確認できます。
当月の残りの実行はスキップされます。翌月にリセットされます。上限はプランによって異なります(Starter: 3,000回 〜 Business: 80,000回)。
cron 式の時刻はサーバーのタイムゾーンに従います。
「毎朝9時に売上データを集計するジョブを追加してください。keelson.yaml の crons に定義してください」
「30分ごとに外部 API からデータを取得して SQLite に同期するバッチ処理を作ってください」
「このアプリに、毎日深夜3時に古いデータを削除するクリーンアップジョブを追加してください」
keelson.yaml の設定
keelson.yaml は、Keelson がアプリをどのようにビルドし、起動し、公開するかを判断するための設定ファイルです。
このページでは、keelson.yaml が何のためにあるのか、何を書けばよいのか、どう使われるのかを説明します。各フィールドの完全な定義については keelson.yaml リファレンス を参照してください。
ただし、keelson.yaml は Keelson の Agent Skill 機能を使えば AI エージェントが自動生成してくれるため、通常は自分で作成する必要はありません。
keelson.yaml は、アプリごとに用意する設定ファイルです。プロジェクトのルートディレクトリに配置します。
Keelson はこのファイルを読み取り、次のことを判断します。
- アプリの識別子(URL の一部になる)
- どのランタイムで動かすか
- どのように起動するか
- 永続ストレージやデータベースを使うか
- 定期実行ジョブやバックグラウンドワーカーがあるか
- 静的アセット配信を行うか
keelson.yaml は、アプリのコードそのものではなく、そのアプリを Keelson 上で動かすための説明書です。すべての設定項目を覚える必要はなく、まずは最小限の構成から始められます。
同じ Web アプリでも、使用する言語、起動コマンド、必要な機能はアプリごとに異なります。
Keelson は keelson.yaml を通じてその違いを理解し、適切な方法でアプリをデプロイします。このファイルがないと、Keelson はそのアプリをどう扱えばよいか判断できません。
AI エージェントでデプロイする場合も、keelson.yaml はアプリの構成を理解するための重要な手がかりになります。エージェントがアプリのコードを読み取って keelson.yaml を自動生成することもできます。
keelson.yaml は、デプロイの開始時に読み取られます。
Keelson はこの設定をもとに、次の処理を行います。
- 設定の検証 — フィールドの値やフィールド間の制約をチェックする
- ビルド — ランタイムに応じたコンテナイメージを作成する
- 起動 —
command で指定されたコマンドでアプリを開始する
- 機能の有効化 — ストレージ、データベース、定期実行ジョブなど、設定された機能を準備する
- 公開 —
slug に基づいた URL でアプリにアクセスできるようにする
設定がアプリの実際の構成と合っていない場合、ビルドに失敗したり、ビルドは成功しても起動できなかったりすることがあります。
keelson.yaml のフィールドはすべてトップレベルに配置します。
| フィールド | 説明 | 例 |
|---|
slug | アプリの識別子。URL の一部になる | my-app |
runtime | 実行環境 | python-slim, node-slim, go-slim |
command | 起動コマンド | "python app.py" |
command は、依存パッケージのインストールと起動を 1 つのコマンドにまとめて書きます。
command: "python -m pip install -r requirements.txt && python app.py"
| フィールド | 説明 |
|---|
env | 環境変数(キーと値のペア) |
storage | 永続ストレージの設定 |
databases | SQLite データベースの設定 |
crons | 定期実行ジョブ |
workers | バックグラウンドワーカー |
assets | 静的アセット配信 |
type | アプリ種別(web を指定すると静的サイトモード) |
各フィールドの型、制約、指定可能な値については keelson.yaml リファレンス を参照してください。
command と assets の組み合わせによって、デプロイモードが自動的に決まります。
| パターン | command | assets | 動作 |
|---|
| 通常のアプリ | あり | なし | コンテナとして起動 |
| 静的サイト / SPA | なし | あり | 静的ファイルを配信 |
| ハイブリッド | あり | あり | 静的ファイル + バックエンド API |
API キー、トークン、パスワードなどの秘密情報は keelson.yaml に直接書かないでください。
keelson.yaml はソースコードと一緒にリポジトリに含まれるファイルです。秘密情報は環境変数またはシークレットとして、コンソールから設定します。
OPENAI_API_KEY: "sk-xxxxxxxxxxxxx"
# OK: 値はコンソールで設定し、keelson.yaml には書かない
環境変数の管理については 環境変数とシークレット を参照してください。
まずは slug、runtime、command の 3 つだけで始められます。
command: "python -m pip install -r requirements.txt && python app.py"
command: "npm install && npm start"
# Keelson が deploy 時に Linux 向け binary を `./app` としてビルドします。
ランタイムには -slim(軽量)と -media(画像・動画処理ライブラリ含む)の 2 種類があります。迷った場合は -slim から始めてください。
アプリの種類によって、使うフィールドが変わります。
データベースを使うアプリでは、storage と databases を追加します。
command: "python -m pip install -r requirements.txt && python app.py"
storage を設定しないと、データは永続化されず Pod の再起動時に失われます。
type: web を指定し、assets でアセットディレクトリを設定します。
Web サーバーなしで、定期的にスクリプトを実行するだけのアプリです。
command: "python report.py"
フロントエンドの静的ファイルとバックエンド API を 1 つのアプリで提供します。
command: "npm install && node server.js"
各構成パターンの完全な例は keelson.yaml リファレンス を参照してください。
デプロイと設定
デプロイする
このページでは、あなたが作ったアプリをKeelsonにデプロイする方法を説明します。クイックスタートでサンプルアプリを試した方が、自分のアプリを載せるときに読むことを想定しています。
Keelsonにおけるデプロイとは、コードを渡して終わりではありません。アプリがビルドされ、起動し、アプリURLでアクセスできる状態になるまでを指します。
デプロイは次の流れで進みます。
- アプリを用意する — ソースコードが手元にある状態にする
- keelson.yaml を作成する — Keelsonにアプリの動かし方を伝える設定ファイルを置く
- AIエージェントにデプロイを依頼する — Agent Skillを使ってデプロイを実行する
- Keelsonがビルド・起動・確認を行う — コンテナイメージのビルド、Pod起動、ヘルスチェックが自動で走る
- アプリURLで利用できるようになる —
https://<slug>.keelson.run でアプリにアクセスできる
デプロイを始める前に、以下を確認してください。
keelson.yaml は、Keelsonがアプリをどう動かすかを判断するための設定ファイルです。プロジェクトのルートディレクトリに配置します。
このファイルには、アプリの識別子、使用するランタイム、起動コマンドなど、デプロイに必要な情報を記述します。
最小構成の例:
slug — アプリの識別子。アプリURLの一部になります(my-app.keelson.run)
runtime — 実行環境。python-slim、node-slim、go-slim など
command — アプリの起動コマンド
これ以外にも、環境変数、データベース、定期実行ジョブなどのフィールドがあります。全項目の詳細は keelson.yaml リファレンス を参照してください。
対象のアプリフォルダをAIエージェント(Claude Code、Codexなど)で開いた状態で、デプロイを依頼します。
依頼の例:
「このアプリをKeelsonにデプロイして」
「keelson.yaml がなければ作成してから、Keelsonにデプロイして」
「起動エラーが出たら原因を調べて修正し、再デプロイして」
AIエージェントは keelson.yaml を読み取り、ビルドとデプロイを自動で実行します。keelson.yaml がない場合は、アプリの構成を判断して作成することもできます。
デプロイを実行すると、Keelsonは以下の処理を順に行います。
- 設定の確認 —
keelson.yaml の内容を検証する
- ビルド — ソースコードからコンテナイメージを作成する
- 起動 — コンテナを起動し、アプリのプロセスを開始する
- ヘルスチェック — アプリが正常にリクエストを受け付けるか確認する
- アプリURLの発行 —
https://<slug>.keelson.run でアクセス可能になる
ユーザーがこれらの手順を個別に操作する必要はありません。AIエージェントが進行状況を確認しながら完了まで進めます。
デプロイが成功したとは、次の状態を指します。
- アプリのコンテナが起動している
- ヘルスチェックに通過している
- アプリURLでアクセスできる
ビルドが通っただけでは完了ではありません。起動して、URLで正常に開ける状態が「デプロイ成功」です。
デプロイに失敗した場合、AIエージェントはビルドログやランタイムログを確認して原因を調査できます。設定ミスや起動エラーがあれば、修正して再デプロイします。
まずはエラーメッセージを確認し、必要に応じてAIエージェントに修正を依頼してください。
| 原因 | 対処 |
|---|
keelson.yaml の不足や記述ミス | ファイルの有無と内容を確認する |
| 起動コマンドの不一致 | command がアプリの実際のエントリポイントと合っているか確認する |
| 必要な環境変数が未設定 | コンソールまたは keelson.yaml の env で設定する |
| アプリが期待するポートで起動していない | アプリがポート 8080 でリッスンしているか確認する |
| ビルドは通るが実行時エラーで落ちる | ランタイムログを確認し、依存関係や設定の不備を調べる |
環境変数とシークレット
アプリが外部サービスと連携するには、APIキーや接続情報が必要です。これらの値をコードに直接書くのではなく、環境変数として管理することで、安全かつ柔軟に設定を切り替えられます。
このページでは、Keelsonで環境変数とシークレットを設定・管理する方法を説明します。
Keelsonでは、環境変数を2つの方法で設定できます。
keelson.yaml の env フィールドに記述した値は、ビルド時と実行時の両方で利用できます。
秘密にする必要のない設定値(ポート番号、動作モードなど)はここに書きます。
APIキーやアクセストークンなどの機密情報は、コンソールからシークレットとして設定します。シークレットは暗号化されてデータベースに保存され、実行時にアプリへ注入されます。
シークレットの値はコンソール上で再表示されません。キー名と最終更新日時のみ確認できます。
シークレットは、ワークスペース単位とアプリ単位の2つのスコープで設定できます。
コンソールの シークレット ページで設定します。ワークスペース内のすべてのアプリから参照できます。
複数のアプリで共通して使う値(共有APIキーなど)に適しています。
コンソールのアプリ詳細画面で設定します。そのアプリだけに適用されます。
特定のアプリだけ別の値を使いたい場合や、ワークスペースシークレットを上書きしたい場合に使います。
同じキー名の環境変数が複数の場所で設定されている場合、次の順で優先されます。
| 優先度 | 設定場所 | 説明 |
|---|
| 高 | アプリシークレット | そのアプリだけに適用される |
| 中 | ワークスペースシークレット | ワークスペース全体に適用される |
| 低 | keelson.yaml の env | ソースコードに含まれる静的な値 |
たとえば、ワークスペースシークレットに API_KEY を設定し、特定のアプリだけ別の API_KEY を使いたい場合は、そのアプリにアプリシークレットとして設定すれば上書きできます。
keelson.yaml の env も同様に、変更後は再デプロイで反映されます。
| タイミング | keelson.yaml の env | シークレット |
|---|
| ビルド時 | 利用できる | 利用できない |
| 実行時 | 利用できる | 利用できる |
フロントエンドのビルドで環境変数が必要な場合(例: VITE_API_URL)は、keelson.yaml の env に記述してください。シークレットはビルドプロセスには渡されません。
シークレットと keelson.yaml の env は、どちらも通常の環境変数としてアプリから参照できます。
Python:
api_key = os.environ["API_KEY"]
Node.js:
const apiKey = process.env.API_KEY;
Go:
apiKey := os.Getenv("API_KEY")
以下のような値は、keelson.yaml ではなくコンソールのシークレットとして設定してください。
- APIキー・アクセストークン
- OAuth クライアントシークレット
- データベース接続文字列
- 外部サービスの認証情報
- Webhook のシークレットキー
Keelsonは、以下の環境変数を自動的にアプリに設定します。ユーザーが同じキー名で値を設定する必要はありません。
| 変数名 | 内容 |
|---|
TZ | タイムゾーン |
KEELSON_APP_ID | アプリの識別子 |
KEELSON_TENANT_ID | ワークスペースの識別子 |
アプリURL
デプロイが完了すると、Keelsonはアプリに専用のURLを自動で発行します。このページでは、そのURLがどう決まり、どのような性質を持つかを説明します。
アプリURLは次の形式で発行されます。
https://{ワークスペースslug}--{アプリslug}.keelson.run
たとえば、ワークスペースのslugが acme、アプリのslugが dashboard の場合:
https://acme--dashboard.keelson.run
アプリのslugは keelson.yaml の slug フィールドで指定した値が使われます。
アプリURLは以下の場所で確認できます。
- コンソール — アプリ詳細画面にURLが表示されます
- デプロイ完了時 — AIエージェントがデプロイ結果としてURLを通知します
URLをコピーして、チームメンバーに共有できます。
アプリURLへのアクセスは、権限が付与されたユーザーのみに制限されます。すべての接続はHTTPSで暗号化されており、証明書の取得や更新をユーザーが行う必要はありません。
アクセス制御の詳細は以下を参照してください。
カスタムドメイン
Keelson では、デプロイしたアプリに独自のドメイン名を設定できます。
通常、アプリには Keelson が発行する公開 URL が割り当てられます。カスタムドメインを使うと、app.example.com のような自社ドメインでアプリを公開できます。
カスタムドメインは、社内ポータルや業務ツールを既存の社内ドメイン配下で運用したい場合に便利です。
- 社内ツールを自社ドメイン配下で公開したい
- ユーザーに Keelson の標準 URL ではなく、わかりやすい URL を案内したい
- 既存の社内ポータルや社内サイトと URL を揃えたい
Keelson では、デプロイに成功すると標準の公開 URL が発行されます。
カスタムドメインは、その標準 URL に加えて、独自のドメイン名でも同じアプリへアクセスできるようにする機能です。
カスタムドメインを設定しても、アクセス制御のルールは変わりません。
認証や IP 制御を有効にしている場合は、カスタムドメイン経由のアクセスにも同じ制限が適用されます。
カスタムドメインを設定するには、次のものが必要です。
- 利用するドメイン名またはサブドメイン名
- そのドメインの DNS を変更できる権限
- 対象アプリがすでに Keelson にデプロイされていること
一般的には、ルートドメインそのものよりも、app.example.com のようなサブドメインを使う方が扱いやすくなります。
- Keelson のコンソールで対象アプリを開きます
- カスタムドメインとして使いたいドメイン名を追加します
- 画面に表示される DNS 設定内容を確認します
- ご利用中の DNS プロバイダで、必要な DNS レコードを追加します
- DNS の反映後、Keelson 側で設定が有効になります
- カスタムドメインの URL でアプリにアクセスできることを確認します
DNS の反映には時間がかかることがあります。設定直後にアクセスできない場合は、しばらく待ってから再度確認してください。
たとえば、tool.example.com をアプリに割り当てる場合、Keelson の画面に表示された内容に従って DNS レコードを追加します。
必要なレコードの種類や値は、Keelson の表示内容をそのまま使ってください。
設定値は環境や構成によって異なるため、手作業で推測して設定しないことをおすすめします。
カスタムドメインを設定したアプリも、通常は HTTPS でアクセスします。
- 例: Keelson が TLS 証明書を自動的に管理します
- 例: 証明書の発行まで数分かかることがあります
- 例: DNS 設定が正しくない場合、証明書の発行が完了しません
Keelson に表示された値と、DNS プロバイダ側に設定した値が一致しているか確認してください。
DNS の反映には時間がかかることがあります。設定直後はまだアクセスできない場合があります。
同じホスト名に対して、別の A / AAAA / CNAME レコードが設定されていると、期待どおりに動作しないことがあります。
カスタムドメインの設定が正しくても、認証設定や IP 制御によってアクセスできない場合があります。
- カスタムドメインは、公開 URL の代わりに使うための機能です
- URL が変わっても、アプリの認証や権限設定はそのまま引き継がれます
- 外部に公開する URL を自社ドメインにしたい場合に便利ですが、アクセス制御の設定は別途確認してください
IP制御
Keelson では、アプリにアクセスできる送信元 IP アドレスを制限できます。
IP 制御を使うと、特定のオフィス、VPN、社内ネットワークなど、許可したネットワークからのアクセスだけを受け付けることができます。
認証とあわせて使うことで、社内アプリをより安全に公開できます。
- 社内ネットワークや VPN からのアクセスだけを許可したい
- 認証に加えて、ネットワーク単位でもアクセスを制限したい
- URL を知っているだけではアクセスできないようにしたい
IP 制御を有効にすると、許可リストに含まれる IP アドレスまたは IP 範囲からのアクセスだけが許可されます。
許可されていない IP アドレスからアクセスした場合、認証画面を含め、アプリには一切アクセスできません。
正しいアカウントを持っていても、許可されたネットワーク外からはアクセスできません。
つまり、IP 制御は認証の代わりではなく、認証に追加するネットワーク制限です。
- Keelson のコンソールで対象アプリを開きます
- IP 制御の設定画面を開きます
- 許可する IP アドレスまたは IP 範囲を追加します
- 設定を保存します
- 許可されたネットワークと、許可されていないネットワークの両方から動作を確認します
IP 制御では、通常は次の形式で IP アドレスを指定します。
- 単一の IP アドレス
例:
203.0.113.10
- CIDR 形式の IP 範囲
例:
203.0.113.0/24
203.0.113.10
特定の 1 台だけを許可する例です
203.0.113.0/24
203.0.113.x の範囲をまとめて許可する例です
CIDR の意味がわからない場合は、ネットワーク管理者に確認してください。
オフィスや VPN の固定グローバル IP を登録するケースが一般的です。
IP 制御と認証は独立した仕組みですが、IP 制御が先に評価されます。
許可されていないネットワークからは、認証画面にも到達しません。
より安全に運用したい場合は、次の組み合わせをおすすめします。
- 認証を有効にする
- 必要なメンバーだけにアプリ権限を付与する
- 必要に応じて IP 制御を有効にする
アクセス制御
認証とログイン
Keelson にデプロイされたアプリは、すべて認証が必要です。
アプリの URL を知っているだけではアクセスできず、ログインしたうえで、そのアプリへの権限を持つユーザーだけが利用できます。
このページでは、Keelson における認証の仕組みとログインの流れを説明します。
Keelson では、アプリの前段に認証プロキシが配置されています。
ユーザーのリクエストは必ずこのプロキシを経由し、認証と権限の確認が行われたうえでアプリに到達します。
この仕組みにより、アプリのコードに認証ロジックを書く必要はありません。
どの言語・フレームワークで作ったアプリでも、デプロイするだけで認証つきの状態になります。
AI ツールで生成したアプリをそのまま載せても、認証なしで外部に公開されることはありません。
Keelson では、次のアカウントでログインできます。
- Google アカウント
- Microsoft アカウント
ワークスペースのメンバーとして登録されているユーザーだけがログインできます。
ワークスペースに参加していないユーザーは、正しいアカウントを持っていてもアプリにアクセスできません。
メンバーの追加方法については、メンバーとアプリ権限 を参照してください。
- ユーザーがアプリの URL にアクセスします
- ログインしていない場合、ログイン画面に移動します
- Google または Microsoft アカウントで認証します
- ログイン後、元のアプリに戻ります
- そのアプリへの権限がある場合、アプリが表示されます
- 権限がない場合、アクセスが拒否されます
ログイン状態は一定期間保持されます。有効期間中は、同じワークスペース内の他のアプリにもログインなしでアクセスできます。
ログインできることと、アプリを使えることは同じではありません。
Keelson では、次の順序でアクセスが判断されます。
- ログインしているか — ユーザーが認証済みかどうか
- アプリへの権限があるか — そのユーザーが対象アプリのメンバーかどうか
- ネットワーク条件を満たしているか — IP 制御が設定されている場合、許可された IP アドレスからのアクセスかどうか
ログインに成功しても、対象アプリへの権限がなければ利用できません。
認証済みのリクエストには、認証プロキシがユーザー情報をヘッダーとして付与します。
アプリのコード内で X-Keelson-User-Id ヘッダーを読み取ることで、現在のログインユーザーを識別できます。
# Python (Flask / FastAPI など)
user_id = request.headers.get("X-Keelson-User-Id")
const userId = req.headers["x-keelson-user-id"];
認証ヘッダーや Cookie は、プロキシがアプリ到達前に除去します。
アプリが受け取るのは Keelson が付与したヘッダーだけです。
認証は「誰がアクセスするか」を制御します。
IP 制御は「どのネットワークからアクセスするか」を制御します。
IP 制御を設定している場合、許可されていないネットワークからはログイン画面にも到達しません。
認証と IP 制御は独立した仕組みですが、組み合わせることでより安全に運用できます。
IP 制御について詳しくは IP制御 を参照してください。
メンバーとアプリ権限
Keelson では、アプリへのアクセスをワークスペース単位で制御します。
ワークスペースのメンバーになっているユーザーは、そのワークスペース内のすべてのアプリにアクセスできます。
このページでは、メンバーの管理方法、ロールの違い、参加方法について説明します。
Keelson のアクセス制御は、ワークスペースへの所属で決まります。
- ワークスペースに参加しているメンバーは、そのワークスペースのアプリすべてにアクセスできる
- ワークスペースに参加していないユーザーは、どのアプリにもアクセスできない
ログインの仕組みについては 認証とログイン を参照してください。
ワークスペースのメンバーには、4 種類のロールがあります。
| ロール | コンソール | アプリ利用 | メンバー管理 |
|---|
| Owner | すべての機能 | 可 | すべてのロールを管理できる |
| Admin | すべての機能 | 可 | Owner 以外を管理できる |
| Builder | 読み取りのみ | 可 | 不可 |
| App User | アクセス不可 | 可 | 不可 |
ワークスペースの全権限を持ちます。メンバーの追加・削除、ロールの変更、アプリの管理など、すべての操作が可能です。
ワークスペースには最低 1 人の Owner が必要です。
Owner とほぼ同等の権限を持ちますが、Owner ロールのメンバーを管理することはできません。
チームの管理者に適したロールです。
コンソールを閲覧できますが、メンバー管理などの変更操作はできません。
アプリの開発・デプロイを行うメンバーに適したロールです。
デプロイされたアプリを利用できますが、コンソールにはアクセスできません。
アプリのエンドユーザーに適したロールです。開発者枠を消費しません。
ワークスペースにメンバーが参加する方法は 3 つあります。
管理者がメールアドレスを指定してメンバーを招待します。
招待時にロールを指定でき、招待されたユーザーがリンクを承認するとメンバーになります。
招待の操作方法については メンバーを招待する を参照してください。
企業のメールドメインを登録すると、そのドメインのメールアドレスを持つユーザーが自動的にワークスペースに参加できます。
- DNS TXT レコードによるドメインの所有権確認が必要です
- 自動参加したメンバーには App User ロールが付与されます
- Gmail や Outlook など、パブリックなメールドメインでは利用できません
- 1 つのドメインにつき、自動参加を設定できるワークスペースは 1 つだけです
社内メンバーを一括でオンボーディングしたい場合に便利です。
企業のメールドメインに対して承認制ポリシーを設定すると、ユーザーが参加をリクエストし、管理者が承認する形でメンバーになれます。
- ユーザーがアプリにアクセスすると、参加リクエストが作成されます
- Owner または Admin がリクエストを承認すると、App User としてメンバーになります
- 承認されるまでアプリにはアクセスできません
自動参加ほどオープンにしたくないが、招待の手間を減らしたい場合に適しています。
ドメインごとの参加ポリシーは、コンソールから設定できます。
| ポリシー | 動作 | ドメイン検証 |
|---|
| 招待のみ(デフォルト) | 招待されたユーザーだけが参加できる | 不要 |
| 自動参加 | 対象ドメインのユーザーが自動で参加できる | 必要(DNS TXT) |
| 承認制 | 参加リクエスト → 管理者承認で参加できる | 必要(DNS TXT) |
ドメインポリシーを変更しても、既存メンバーのステータスには影響しません。
不要になったメンバーは、コンソールからブロックできます。
- ブロックされたメンバーは、ワークスペース内のすべてのアプリにアクセスできなくなります
- アカウントの削除ではなく、アクセス権の無効化です
- 最後の Owner をブロックすることはできません
- 自分自身をブロックすることはできません
退職者や異動メンバーのアクセスを停止する場合に使います。
ワークスペースのメンバーになっていないユーザーはアプリにアクセスできません。管理者に招待を依頼してください。
以前は参加していたが、ブロックされている可能性があります。コンソールのメンバー一覧で確認してください。
複数の Google / Microsoft アカウントを使い分けている場合、ワークスペースに登録されていないアカウントでログインしている可能性があります。
承認制のワークスペースでは、管理者が参加リクエストを承認するまでアクセスできません。
メンバーシップの問題ではなく、ネットワークの制限でアクセスできない場合があります。
はい。現在、アクセス制御はワークスペース単位です。メンバーはワークスペース内のすべてのアプリにアクセスできます。
App User はデプロイされたアプリだけを利用できます。Builder はコンソールの閲覧もできますが、メンバー管理などの変更操作はできません。
はい。自動参加時は App User ロールが付与されますが、Owner または Admin がコンソールからロールを変更できます。
そのメンバーはワークスペース内のすべてのアプリにアクセスできなくなります。ブロックは即時反映されます。
リファレンス
Keelson Deploy Spec
Spec version: 2025-03-14 / Raw text (AI向け): /ja/docs/reference/deploy-spec.txt
この文書は、Keelson にアプリをデプロイする際の対応ランタイム・制約・成立条件を定義する正本です。デプロイの可否判断は、この文書に従ってください。
クイックスタートや操作手順は デプロイする を参照してください。
Keelson におけるデプロイ成功とは、ビルドが完了することではありません。次の条件をすべて満たした場合にのみ、デプロイは成功とみなされます。
- アプリのビルドが完了している
- アプリのプロセスが起動している
- ヘルスチェックに通過している
- アプリ URL(
https://<slug>.keelson.run)が発行されている
- アプリ URL にアクセスできる状態である
ビルドが成功しても、起動に失敗した場合やヘルスチェックに通らない場合は、デプロイ成功ではありません。
すべてのデプロイには keelson.yaml が必要です。プロジェクトのルートディレクトリに配置します。
最小構成:
command: "pip install --user -r requirements.txt && python app.py"
各フィールドの詳細は keelson.yaml リファレンス を参照してください。
Keelson は、以下のランタイム上でのみアプリを実行できます。
| ランタイム | 言語 | 用途 |
|---|
python-slim | Python | 軽量。API、テキスト処理、自動化など |
python-media | Python | メディア処理向け。画像・動画ライブラリを含む |
node-slim | Node.js | 軽量。Web アプリ、API など |
node-media | Node.js | メディア処理向け。画像処理ライブラリを含む |
go-slim | Go | 軽量 |
go-media | Go | メディア処理向け |
keelson.yaml の runtime フィールドで指定します。迷った場合は -slim から始め、メディア処理系ライブラリが必要になったら -media に切り替えてください。
- slim — 言語ランタイムと標準ライブラリのみ。ビルドが速く、イメージサイズが小さい
- media — slim に加え、画像処理(Pillow、sharp 等)や動画処理に必要なシステムライブラリがプリインストールされている
特定のフレームワークに依存しません。command で起動でき、HTTP サーバーとしてリクエストを受け付けるアプリであれば動作します。
例: FastAPI、Flask、Express、Next.js、Hono、Gin など。
以下の言語・ランタイムはサポート対象外です。
- Ruby
- Java / Kotlin / Scala
- PHP
- Rust
- .NET / C#
- Elixir / Erlang
- Swift
非対応ランタイムのアプリは、修正や変換を行っても Keelson へデプロイできません。
Keelson は固定されたビルド環境・実行環境を提供します。アプリはその環境上でビルドおよび起動できる必要があります。
- OS: Linux
- CPU: x86_64 (amd64)
アプリは非 root ユーザーとして実行されます。sudo、apt-get install、システムレベルの変更は実行できません。
使用できません。Keelson はランタイムを選択し、command で起動する方式です。Dockerfile の代わりに keelson.yaml でランタイムと起動コマンドを指定します。
| パス | 書き込み | 永続化 | 用途 |
|---|
/data | 可 | storage 設定時のみ | SQLite、ファイルアップロード、アプリデータ |
| アプリディレクトリ | 可(一時的) | 不可 | ソースコード、依存関係 |
/tmp | 可(一時的) | 不可 | 一時ファイル |
| その他 | 不可 | — | — |
- 再デプロイ時に
/data 以外の書き込みは失われます
/data を永続化するには keelson.yaml の storage を設定してください
- 詳細は 永続ストレージ を参照
- Web アプリは環境変数
PORT で指定したポートで HTTP リクエストを待ち受けてください
0.0.0.0 で listen する必要があります。127.0.0.1 や localhost ではリクエストが届きません
- HTTPS 終端は Keelson が行います。アプリは HTTP で listen してください
Keelson は任意の OS パッケージ追加を前提とした環境ではありません。
-slim ランタイムには最小限のシステムライブラリのみ含まれます
-media ランタイムには画像・動画処理に必要な一般的なライブラリが含まれます
- それ以外のシステムライブラリが必要な場合、アプリは動作しない可能性があります
apt-get 等によるパッケージ追加はできません(非 root のため)
command で起動した単一プロセスが基本です
- systemd やデーモン管理は使えません
- バックグラウンド処理が必要な場合は
workers を使ってください
- CPU とメモリはプランの Compute Class に応じて割り当てられます
- アプリごとの個別設定ではなく、ワークスペース内の全アプリに共通の性能帯が適用されます
言語ランタイムが対応していても、依存ライブラリやシステム要件によってはデプロイできない場合があります。
以下のパッケージマネージャで管理される純粋な言語パッケージは問題なくインストールできます。
- Python: pip(
requirements.txt)
- Node.js: npm(
package.json)
- Go: go mod(
go.mod)
依存関係は command 内でインストールします。
command: "pip install --user -r requirements.txt && python app.py"
command: "npm install && npm start"
# Go (Keelson 側で deploy 時に `./app` がビルドされます)
一部のパッケージは、C ライブラリやシステムレベルの依存を必要とします。
-media ランタイムで動作するもの: Pillow、opencv-python、sharp、ffmpeg 関連など、一般的なメディア処理ライブラリ
- 動作しない可能性があるもの: ランタイムに含まれないシステムライブラリに依存するパッケージ
| パターン | 理由 |
|---|
apt-get install が必要 | 非 root でパッケージ追加不可 |
| 特殊な C ライブラリに依存 | ランタイムに含まれていない可能性 |
| GPU を前提とした推論ライブラリ | GPU インスタンス未提供 |
| データベースサーバー(PostgreSQL、MySQL、Redis) | 外部サービスとして接続は可能だが、Keelson 上での起動は不可 |
| systemd やバックグラウンドデーモン前提 | プロセスモデルが異なる |
command と assets の組み合わせにより、デプロイモードが決まります。
| モード | command | assets | 説明 |
|---|
| コンテナ | あり | なし | 通常のアプリデプロイ |
| 静的サイト | なし | あり(fallback なし) | 静的ファイルのみ |
| SPA | なし | あり(fallback あり) | SPA(フォールバック付き) |
| ハイブリッド | あり | あり(fallback 必須) | 静的ファイル + バックエンド API |
アプリの起動に必要な API キー、トークン、接続情報は、コードに直接埋め込まず、環境変数またはシークレットとして設定してください。
keelson.yaml の env — バージョン管理に含めてよい値
- コンソールのシークレット — API キーやトークンなど、コードに含めたくない値
必要な値が未設定の場合、アプリは正常に起動できないことがあります。
詳細は 環境変数とシークレット を参照してください。
| 変数名 | 説明 |
|---|
TZ | タイムゾーン(Asia/Tokyo) |
KEELSON_APP_ID | アプリの内部 ID |
KEELSON_TENANT_ID | テナントの内部 ID |
| 対象 | 制限 |
|---|
| HTTP リクエスト | 一般的なタイムアウトが適用 |
| 定期実行ジョブ(cron) | 1〜3,600 秒(デフォルト 300 秒) |
| ビルド | 制限あり(依存関係の量による) |
- アプリから外部 API やサービスへの通信(Egress)はデフォルトで可能です
- Business プラン以上では、通信先をホスト名単位で制限できます
| 症状 | 原因 | 対処 |
|---|
| ビルド成功、起動後すぐ落ちる | 0.0.0.0 で listen していない | host="0.0.0.0" を明示 |
| ポートに接続できない | ポート番号がハードコード | 環境変数 PORT から読み取る |
| モジュールが見つからない | command に依存インストールが含まれていない | pip install / npm install を command に含める |
| ネイティブモジュールのビルド失敗 | システムライブラリ不足 | -media ランタイムに変更、または依存を見直す |
/data に書き込めない | storage 未設定 | keelson.yaml に storage を追加 |
| 起動コマンドが見つからない | エントリポイントのパスが間違い | ファイル名・パスを確認 |
- ビルドログを確認 — 依存関係のインストールが成功しているか
- 実行ログを確認 — 起動時エラーやランタイムエラーがないか
keelson.yaml を確認 — runtime、command、env の設定が正しいか
AI エージェントは、Keelson へのデプロイ時に以下の順序で判断してください。
- ランタイム確認 — アプリの言語がこの仕様の対応ランタイムに含まれるか確認する
- 依存関係確認 — ネイティブ依存やシステムライブラリの要件が制約内か確認する
- keelson.yaml 確認 — ファイルの有無と設定内容の妥当性を確認する。なければ作成する
- 環境変数確認 — 必要な環境変数やシークレットが不足していないか確認する
- デプロイ実行 — CLI または Skill を使ってデプロイを実行する
- 完了確認 — ビルド完了だけでなく、起動・ヘルスチェック・URL アクセスまで確認する
- 失敗時対応 — ログを確認し、修正可能な範囲で対処する。制約違反がある場合は理由を明示して停止する
- 非対応ランタイムの場合は、デプロイを試行しない。理由を明示して停止する
- 必須設定が不足している場合は、必要事項を提示する
- ビルド成功のみで完了扱いにしない
- 起動失敗時は必ずログを参照する
- Web 上の最新 Keelson Deploy Spec(この文書)
- Web 上の最新 CLI バージョン情報
- Skill 同梱版の仕様
- 一般知識・推測
Web 上の正本と Skill 同梱の情報が矛盾する場合は、Web 上の正本を優先してください。
keelson.yaml
keelson.yaml は、プロジェクトルートに配置するデプロイ設定ファイルです。アプリのランタイム、起動コマンド、環境変数、データベース、定期実行ジョブなどを定義します。
デプロイ時に Keelson はこのファイルを読み取り、その内容に基づいてビルドと実行環境を決定します。
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|
slug | string | はい | — | アプリの識別子(URLの一部になります) |
type | string | — | null | アプリ種別。"web" のみ指定可。指定時は crons・workers 不可 |
runtime | string | はい | — | 実行環境。対応ランタイムを参照 |
command | string | list | 条件付き | — | 起動時に実行するコマンド。crons がない場合は必須 |
env | map | — | {} | 環境変数 |
databases | list | — | [] | SQLite データベースの設定 |
crons | list | 条件付き | [] | 定期実行ジョブ。command がない場合は必須 |
workers | list | — | [] | バックグラウンドワーカー |
storage | object | — | {} | 永続ストレージの設定 |
assets | object | — | null | 静的アセット配信の設定 |
アプリの識別子です。公開URLの一部として使われます(例: my-app.keelson.run)。
ルール:
- 使用できる文字: 小文字英数字とハイフン(
a-z, 0-9, -)
- 長さ: 1〜63文字
--(連続ハイフン)は使用不可
- 予約語:
api, console, www, admin(これが現時点での完全な一覧です)
アプリ種別を指定します。省略可能です。
指定できる値は "web" のみです。type: web を指定すると、静的アセット配信(assets)が有効になり、command なしでのデプロイが可能になります。
制約:
type: web を指定した場合、crons および workers は使用できません
アプリの実行環境を指定します。静的サイトのみのデプロイでも必須です。
| ランタイム | 言語 | 用途 |
|---|
python-slim | Python | 軽量。テキスト処理、API など |
python-media | Python | メディア処理向け(画像・動画ライブラリ含む) |
node-slim | Node.js | 軽量 |
node-media | Node.js | メディア処理向け |
go-slim | Go | 軽量 |
go-media | Go | メディア処理向け |
迷った場合は -slim から始めてください。メディア処理系のライブラリが必要になった場合に -media へ切り替えます。
起動時に実行するコマンドです。依存パッケージのインストールなどの準備処理を含めることもできます。文字列またはリスト形式で指定できます。
command: "python -m pip install -r requirements.txt && python app.py"
ルール:
command と crons のどちらかは必須です(両方指定も可)
type: web で assets のみのデプロイでは省略可
環境変数をキーと値のペアで定義します。値はすべて文字列として扱われます。
YAML の自動型変換を避けるため、値はすべて引用符で囲むことを推奨します。
SQLite データベースの設定です。databases で宣言したファイルは、storage で定義された永続ストレージ上に配置されます。storage を省略した場合、データは永続化されず Pod の再起動時に失われます。データを保持したい場合は storage も合わせて設定してください。
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|
name | string | — | db-{index} | データベースの識別名 |
type | string | はい | — | sqlite のみ対応 |
path | string | はい | — | ファイルのマウントパス |
ルール:
path は /data/ で始まる必要があります
name と path はそれぞれ重複不可
定期実行ジョブを定義します。Keelson 内部では Kubernetes CronJob として実行されます。
command: "python cleanup.py"
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|
name | string | はい | — | ジョブ名。小文字英数字とハイフン、1〜63文字 |
schedule | string | はい | — | cron 式(5フィールド形式) |
command | string | list | はい | — | 実行コマンド |
timeout | int | — | 300 | タイムアウト(秒)。1〜3600 |
ルール:
- 最大 10 個まで定義可能
name の重複不可
type: web との併用不可
| 式 | 意味 |
|---|
* * * * * | 毎分 |
0 * * * * | 毎時 0 分 |
0 3 * * * | 毎日 3:00 |
0 0 * * 1 | 毎週月曜 0:00 |
バックグラウンドワーカープロセスを定義します。Web アプリとは別のプロセスとして実行されます。
command: "python worker.py"
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|
name | string | はい | — | ワーカー名。小文字英数字とハイフン、1〜63文字 |
command | string | list | はい | — | 実行コマンド |
replicas | int | — | 1 | レプリカ数。0 または 1 |
resources | object | — | null | リソース制約(下記参照) |
replicas を 0 にすると、ワーカーの定義は保持されますが起動しません。一時的にワーカーを無効化したい場合に使用します。
ルール:
- 現在のバージョンでは最大 1 つまで定義可能
- トップレベルの
command が設定されている場合のみ使用可
type: web との併用不可
ワーカーの CPU・メモリの制約を指定できます。
command: "python worker.py"
requests と limits のいずれかに、cpu または memory を1つ以上指定してください。
永続ストレージの設定です。コンテナ内の /data にマウントされます。databases で定義する SQLite ファイルもこの領域を使用します。
storage を省略した場合、/data は一時領域となり、Pod の再起動時にデータが失われます。データを永続化するには storage を設定してください。
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|
disk_id | string | — | null | ストレージ識別子。小文字英数字とハイフン、1〜32文字 |
静的アセット配信の設定です。静的サイトや SPA のデプロイ、バックエンド API とのハイブリッド構成に使用します。
| フィールド | 型 | 必須 | デフォルト | 説明 |
|---|
dir | string | はい | — | アセットディレクトリ(プロジェクトルートからの相対パス) |
fallback | string | — | null | SPA 用フォールバックファイル(例: index.html) |
api | string | — | null | バックエンド API のパスプレフィックス(例: /api) |
api を指定すると、そのパス配下のリクエストはバックエンドアプリへ転送され、それ以外は静的アセットとして配信されます。
ルール:
dir に .. を含むパスは使用不可
api は / で始まる必要があります
api に /__keelson 配下のパスは使用不可
api はトップレベルの command が設定されている場合のみ使用可
- ハイブリッド構成(
assets + command)では fallback が必須
command と assets の組み合わせにより、デプロイモードが自動的に決まります。
| モード | command | assets | fallback | 説明 |
|---|
| コンテナ | あり | なし | — | 通常のアプリデプロイ |
| 静的サイト | なし | あり | なし | 静的ファイルのみ |
| SPA | なし | あり | あり | SPA(フォールバック付き) |
| ハイブリッド | あり | あり | 必須 | 静的ファイル + バックエンド API |
設定の組み合わせには以下の制約があります。
| ルール | 説明 |
|---|
command または crons が必須 | 少なくとも一方を指定してください(type: web の静的サイトデプロイを除く) |
type: web の排他制約 | crons および workers とは併用できません |
workers には command が必要 | トップレベルの command がない場合、workers は使用できません |
assets.api には command が必要 | API プレフィックスはバックエンドがある場合のみ指定できます |
ハイブリッドには fallback が必要 | assets と command を両方指定する場合、fallback は必須です |
command: "python -m pip install --user -r requirements.txt && python app.py"
PYTHONUSERBASE: "/deps/.local"
DB_PATH: "/data/customers.db"
command: "python heartbeat.py"
command: "python -m pip install --user -r requirements.txt && python app.py"
PYTHONUSERBASE: "/deps/.local"
DB_PATH: "/data/tasks.db"
disk_id: task-worker-data
command: "python -m pip install --user -r requirements.txt && python worker.py"
command: "python -m pip install --user -r requirements.txt && python app.py"
PYTHONUSERBASE: "/deps/.local"
# Keelson が deploy 時に Linux 向け binary を `./app` としてビルドします。
command: "npm install && npm start"
DB_PATH: "/data/notes.db"
| エラー原因 | 説明 |
|---|
path が /data/ で始まっていない | databases.path は /data/ 配下である必要があります |
api が / で始まっていない | assets.api は / で始まる必要があります |
command も crons もない | 少なくとも一方を指定してください(type: web の静的デプロイを除く) |
workers があるのに command がない | workers はトップレベルの command が必要です |
env の値が引用符で囲まれていない | true/false/数値は YAML に型変換されます。すべて引用符で囲んでください |
storage なしで databases を使っている | データは永続化されず Pod 再起動時に失われます |