mcpField
A
appgarden

appgarden

github.com/lukastkクラウド・DevOps0492 回インストール8 週間前に更新
リポジトリ

appgarden について

appgarden は、`appgarden` CLI と SSH を使ってリモートサーバー上の Web アプリをデプロイ・運用するスキルです。複数のデプロイ方式に対応し、プロジェクト設定で環境ごとの管理ができます。

主な機能

  1. 01SSH 経由のアプリデプロイ
  2. 02静的・コマンド・Docker 方式
  3. 03appgarden.toml による環境設定
  4. 04アプリ状態とログの確認
  5. 05アプリのライフサイクル管理

活用シーン

  1. 01静的サイトのリモートサーバーへの配置
  2. 02staging と production 環境への公開
  3. 03状態確認とログによるトラブル調査
  4. 04アプリの再起動・停止・再デプロイ

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lukastk/appgarden --skill appgarden

インストール後、Claude Code で/appgardenを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

.env.sample
.envrc
CLAUDE.md
.gitignore
README.md
NBLITE_INSTRUCTIONS.md
nblite.toml
.github/workflows/
ci.yml
release.yml
dev_scripts/
clean-project
publish-new
run-tests
pts/appgarden/
01_remote.pct.py
03_routing.pct.py
00_config.pct.py
06_apps.pct.py
05_deploy.pct.py
04_server.pct.py
08_environments.pct.py
07_auto_docker.pct.py
02_ports.pct.py
09_tunnel.pct.py
_dir_server.pct.py
10_cli.pct.py
pts/tests/
test_cli.pct.py
test_deploy.pct.py
test_apps.pct.py
test_environments.pct.py
pts/tests/integration/
test_server_init.pct.py
conftest.pct.py

詳細

AppGarden CLI スキル

appgarden CLI を使用して Web アプリケーションをデプロイまたは運用する際に、このスキルを使用します。

AppGarden はエージェントレスのデプロイツールです。ローカルの CLI が SSH 経由で接続し、リモートサーバーを準備して、アプリのソースをアップロードまたはクローンし、Caddy/systemd/Docker のファイルを書き込み、サーバーの AppGarden ルート(デフォルトは /srv/appgarden)に状態を記録します。

コマンドを実行する前に

  • AppGarden 自体を開発/テストする場合は、AppGarden リポジトリのチェックアウトから実行することを推奨します。

    cd /path/to/appgarden && uv run appgarden ...
    

    AppGarden が環境にインストールされている場合は、appgarden ... を使用してもかまいません。

  • 読み取り専用の安全な確認コマンドは、確認なしで実行してかまいません:appgarden --help、appgarden version、appgarden config show、appgarden server list、appgarden server ping、appgarden apps list、appgarden apps status、appgarden apps logs、appgarden tunnel list。

  • 作成、変更、デプロイ、再起動、停止、削除、またはサービスの公開を行うコマンドを実行する前に、確認してください:server add、server remove、server default、server init、deploy、apps start|stop|restart|redeploy|remove、apps meta set|replace|remove、tunnel open|close|cleanup。

  • 次のコマンドには特に注意してください。

    • appgarden server init --include ssh:SSH の設定を強化し、sshd を再読み込みします。
    • appgarden server init --include firewall:UFW を有効にし、ファイアウォールポリシーを変更します。
    • appgarden apps remove NAME --yes:アプリのリソースを削除します。アプリの data/ ディレクトリを保持する意図がある場合に限り、--keep-data を追加してください。
    • appgarden deploy:既存アプリのアップロード済みソースを上書きし、Caddy/systemd/Docker のリソースを更新する場合があります。
    • appgarden tunnel open:停止するまで、設定済みサーバーを介してローカルのポート/ファイル/ディレクトリをパブリックに公開します。

設定の保存場所

ローカル設定は次の場所に保存されます。

~/.config/appgarden/config.toml

サーバー設定の形式:

default_server = "myserver"

[defaults]
method = "dockerfile"
container_port = 3000

[servers.myserver]
host = "203.0.113.10"              # or hcloud_name + hcloud_context
ssh_user = "root"
ssh_key = "~/.ssh/id_rsa"
domain = "apps.example.com"
app_root = "/srv/appgarden"        # optional; defaults to /srv/appgarden

[servers.myserver.init]
skip = ["upgrades"]               # optional persistent init skips

リモートの状態とリソースは app_root の下にあり、通常は次の場所です。

/srv/appgarden/garden.json          # app registry
/srv/appgarden/apps/<name>/         # per-app files/source/app.json/.env/data
/srv/appgarden/caddy/apps/*.caddy   # deployed app Caddy snippets
/srv/appgarden/caddy/tunnels/*.caddy
/srv/appgarden/tunnels/active.json

appgarden config show はローカル設定を表示します。サーバーを対象とするコマンドでは、--server <name>/-s <name> または APPGARDEN_SERVER を使用してください。指定がない場合、AppGarden は default_server を使用します。

1 台のホスト上に複数のガーデンを設置する場合:各 app_root(例:/srv/appgarden と /srv/appgarden-proto)を個別に指定することで、同じマシン上で複数の AppGarden ガーデンを実行できます。ガーデンごとの状態(garden.json)、Caddy スニペット、/etc/caddy/Caddyfile の管理対象ブロックは、すべて app_root ごとに管理されるため、あるガーデンで server init を実行しても、別のガーデンには影響しません。ただし、ポートはホスト全体で共有されるリソースです。すべてのガーデンがホストの TCP ポート空間を共有するため、ポートの割り当ては /var/lib/appgarden/ports.json にある単一のホストレベルのレジストリで管理され、すべてのガーデンが 1 つのロックを共有します。これにより、2 つのガーデンが同じホストポートを割り当てることを防ぎます。ポート範囲を設定する必要はありません。注意点:systemd ユニット名と Docker コンテナ名(appgarden-<name>)はホスト全体で共有されるため、1 台のホスト上にあるすべてのガーデン間でアプリ名を一意にする必要があります。共有レジストリ導入前のホストをアップグレードする場合は、既存のガーデンごとに 1 回 appgarden server init を実行してください。init は各ガーデンですでにデプロイされているアプリのポートを共有レジストリに反映します(べき等)。

サーバーのセットアップ

サーバーを設定し、SSH 経由で到達可能にし、DNS をそのサーバーに向ける必要があります。

appgarden server add myserver \
  --host <server-ip-or-hostname> \
  --ssh-user root \
  --ssh-key ~/.ssh/id_rsa \
  --domain apps.example.com

# Hetzner alternative: resolve IP through hcloud instead of --host
appgarden server add myserver \
  --hcloud-name <hetzner-server-name> \
  --hcloud-context <hcloud-context> \
  --domain apps.example.com

appgarden server list
appgarden server ping myserver
appgarden server default myserver

サブドメインへのデプロイやトンネルを使用する場合は、*.apps.example.com などのワイルドカード DNS レコードを作成し、サーバーの IP アドレスを指定してください。明示的に指定するカスタムホスト名にも、サーバーを指す DNS レコードが必要です。

サーバーの初期化

サーバーごとに一度だけ実行します。

appgarden server init myserver

現在の server init の動作:

  • デフォルトで有効な任意の手順。有効な手順を省略するには --skip を指定します:update、docker、caddy、upgrades。
  • デフォルトで無効なオプトイン手順。有効にするには --include を指定します:firewall、ssh、fail2ban、group。
  • 必須の手順は常に実行されます:AppGarden の Caddyfile インポートブロックの設定、ディレクトリの作成、特権ヘルパー/sudoers エントリーのインストール、デプロイユーザーへの所有権設定、状態ファイルの初期化、利用可能な場合は Docker/Caddy の起動。

例:

appgarden server init myserver --minimal              # essential steps only
appgarden server init myserver --skip upgrades        # skip unattended-upgrades
appgarden server init myserver --include group        # create/use appgarden group for non-root deploy users
appgarden server init myserver --include firewall     # configure UFW; confirm first
appgarden server init myserver --include ssh          # harden sshd; confirm first

root 以外の SSH ユーザーの場合、server init は /usr/local/bin/appgarden-privileged と、AppGarden の特権操作に限定した sudoers ルールをインストールします。

推奨デプロイフロー:appgarden.toml

プロジェクトのルートに appgarden.toml を作成し、名前付き環境をデプロイします。

[app]
name = "myapp"
slug = "my-app"                  # optional; used by {app.slug}; falls back to name
server = "myserver"
method = "dockerfile"            # static | command | dockerfile | docker-compose | auto
source = "."                     # local path or git URL
container_port = 3000
subdomain = "{app.slug}"         # or path/url; supports placeholders
exclude = ["node_modules", ".git"]
gitignore = true                  # local uploads honor .gitignore by default
meta = { team = "frontend" }

[environments.production]
branch = "main"
subdomain = "{app.slug}"
env = { NODE_ENV = "production" }

[environments.staging]
branch = "staging"
subdomain = "{app.slug}-staging"
env_file = ".env.staging"
meta = { visibility = "internal" }

デプロイ:

appgarden deploy production
appgarden deploy staging
appgarden deploy --all-envs
appgarden deploy --project /path/to/project production

appgarden.toml が存在し、環境名も名前も指定されていない場合、appgarden deploy はすべての環境をデプロイします。位置引数で環境を指定した場合、その環境が存在している必要があります。

appgarden.toml のセマンティクス
  • [app].name は必須です。デプロイされるアプリ名はこの値から決まります:production ではベース名を使用し、それ以外の環境では <name>-<env> を使用します。例:myapp および myapp-staging。
  • 値は次の順序で適用されます:ハードコードされたデフォルト値 < ~/.config/appgarden/config.toml のグローバルな [defaults] < [app] のデフォルト値 < [environments.<name>] < CLI フラグ/APPGARDEN_* 環境変数。
  • env および meta の辞書フィールドはキーごとにマージされます。環境/CLI の値は先に設定されたキーを上書きします。
  • exclude および volumes のリストフィールドは、各レイヤーの内容を連結して重複を削除します。
  • プロジェクト/環境設定の文字列値では、プレースホルダー {app.name}、{app.slug}、{env.name} を使用できます。
  • 相対パスのローカルな source および env_file の値は、プロジェクトディレクトリ、または明示的に指定した --project ファイルを含むディレクトリを基準に解決されます。

[app] または [environments.<name>] で使用できるフィールド:

フィールド意味
server設定済みのサーバー名。
methodstatic、command、dockerfile、docker-compose、または auto。デフォルトは static です。
sourceローカルディレクトリ/パス、または Git URL。static、dockerfile、docker-compose、auto では必須で、command では省略可能です。
url明示的に指定する公開ホスト名/パス。例:example.com または example.com/docs。
subdomaindomain またはサーバーのドメインと組み合わせるプレフィックス。例:docs -> docs.apps.example.com。
pathdomain またはサーバーのドメイン配下のパス。例:docs -> apps.example.com/docs。
domainsubdomain/path に使用するサーバーのベースドメインを上書きします。
portホストポート。省略すると、AppGarden がポートの状態から自動割り当てします。
container_portDockerfile/auto コンテナー内で公開するポート。デフォルトは 3000 です。
cmdcommand および auto メソッドの起動コマンド。どちらのメソッドでも必須です。
setup_cmdauto 用のインストール/ビルドコマンド。検出されたランタイムのデフォルト値を上書きします。
branchGit ソースのブランチ。
envインライン環境変数。
env_fileローカルの dotenv ファイル。
metaアプリとともに保存され、ステータスに表示される任意のメタデータ。
excludeローカルアップロード用の Rsync 除外パターン。apps redeploy でも再利用されます。
gitignoreローカルアップロードで Rsync の .gitignore フィルターを適用するかどうか。デフォルトは true です。CLI で上書きするには --no-gitignore を指定します。
volumesdockerfile および auto 用の Docker ボリュームマウント(host:container[:opts])。
created_at、updated_at、repo任意のメタデータ上書き値。日付には短縮形式の日付、ISO 文字列、または TOML の日付を指定できます。repo は、可能な場合、ローカル Git の origin から自動検出されます。

URL の解決順序は次のとおりです:明示的な url、それがない場合は subdomain + ドメイン、それもない場合は path + ドメイン。サブディレクトリルーティング(domain/path)では、同じドメイン上の複数のアプリが生成された Caddy 設定を共有し、AppGarden が URL の競合をチェックします。

appgarden.toml を使わないアドホックデプロイ

--name とフラグを使います。ほとんどのフラグには、対応する APPGARDEN_* 環境変数(APPGARDEN_NAME、APPGARDEN_SERVER、APPGARDEN_METHOD、APPGARDEN_SOURCE、APPGARDEN_URL、APPGARDEN_SUBDOMAIN、APPGARDEN_PATH、APPGARDEN_DOMAIN、APPGARDEN_PORT、APPGARDEN_CONTAINER_PORT、APPGARDEN_CMD、APPGARDEN_SETUP_CMD、APPGARDEN_BRANCH、APPGARDEN_ENVVAR_FILE、APPGARDEN_PROJECT、APPGARDEN_ALL_ENVS)があります。

# Static site / SPA
appgarden deploy --name mysite --method static --source ./dist --subdomain mysite

# Dockerfile app
appgarden deploy --name myapp --method dockerfile --source . --container-port 3000 --subdomain myapp

# Auto-generated Dockerfile; runtime is detected from package.json, requirements.txt,
# pyproject.toml, Gemfile, go.mod, or Cargo.toml. --cmd is required.
appgarden deploy --name myapp --method auto --source . --cmd "npm start" --subdomain myapp

# Bare process managed by systemd. --source is optional; --cmd is required.
appgarden deploy --name myapi --method command --source ./api --cmd "python app.py" --subdomain myapi

# Docker Compose stack; your compose file is used directly.
appgarden deploy --name mystack --method docker-compose --source ./project --subdomain mystack

# Explicit path routing instead of subdomain routing
appgarden deploy --name docs --method static --source ./docs --url apps.example.com/docs

# Env, metadata, excludes, and volumes
appgarden deploy --name myapp --method dockerfile --source . --subdomain myapp \
  --envvar NODE_ENV=production \
  --envvar-file .env.production \
  --meta team=backend --meta visibility=internal \
  --exclude node_modules --exclude .git \
  --volume ./data:/app/data \
  --no-gitignore

デプロイ方法に関する注意事項:

方法用途必須の入力実行時の動作
staticHTML/CSS/JS/SPAsourceソースをアップロード/クローンし、Caddy で直接配信します。
commandDocker を使わないローカルプロセスcmd(source は任意)割り当て済み/明示的なポートを PORT に設定して systemd サービスを作成します。
dockerfileDockerfile があるプロジェクトsourceリモートでイメージをビルドし、AppGarden の compose ファイルを書き込み、systemd 経由で実行します。
docker-compose既存の compose プロジェクトsourcedocker compose up/down を systemd 経由で実行します。volumes の設定は注入されません。
autoシンプルな Node/Python/Ruby/Go/Rust プロジェクトsource、cmdランタイムを検出し、Dockerfile を書き込み、イメージをビルドして、compose ファイルを書き込みます。

ローカルからアップロードする場合、AppGarden は --delete を指定して rsync を使い、デフォルトで .gitignore を適用し、--exclude/exclude パターンも適用します。Git ソースの場合は、リモートでリポジトリをクローンし、必要に応じて指定されたブランチをチェックアウトします。

デプロイするアプリの .env ファイルでは、環境変数の優先順位は appgarden.toml の env < env_file の内容 < CLI の --envvar 値です。

デプロイ済みアプリの管理

appgarden apps list [-s server] [--short]
appgarden apps status <name> [-s server]
appgarden apps logs <name> [-s server] [-n 100]
appgarden apps restart <name> [-s server]
appgarden apps redeploy <name> [-s server]
appgarden apps stop <name> [-s server]
appgarden apps start <name> [-s server]
appgarden apps remove <name> [-s server] [--keep-data] [--yes]

運用上のガイダンス:

  • アプリ名が正確にわからない場合は、まず apps list を使います。

  • apps status を使うと、URL、ルーティング、方法、ポート、リポジトリ/ソース、タイムスタンプ、メタデータを確認できます。

  • デバッグ時は、再起動する前に apps logs NAME -n 200 を使います。

  • apps redeploy はソースを更新します。Git アプリでは git pull を実行し(保存済みのブランチがある場合はそのブランチを使用)、ローカルソースのアプリでは保存済みの exclude/gitignore を使って再アップロードします。Dockerfile/auto アプリではイメージを再ビルドし、保存済みのボリュームを保持します。static アプリでは Caddy を再読み込みします。

  • appgarden.toml でアプリ名を変更する場合は、URL/Caddy の競合を避けるため、先に古いアプリを削除します。

    appgarden apps remove old-name --yes
    appgarden deploy production
    

メタデータ

メタデータは、アプリとともに保存される任意の JSON 互換キー/値データです。

appgarden apps meta get myapp [-s server]
appgarden apps meta set myapp --meta team=backend --meta tier=premium [-s server]
appgarden apps meta replace myapp --json '{"team":"frontend"}' [-s server]
appgarden apps meta remove myapp tier visibility [-s server]

appgarden.toml では、meta ディクショナリは env ディクショナリと同様にマージされます。

[app]
name = "myapp"
meta = { team = "backend", visibility = "internal" }

[environments.production]
meta = { visibility = "public" }
# result: { team = "backend", visibility = "public" }

Localhost トンネル

トンネルを使用すると、ローカルの開発サーバー、ファイル、ディレクトリ、またはコマンドを、HTTPS を使ってリモートサーバー経由で公開できます。--cmd/--serve とともに --close-on-cmd-exit を指定しない限り、トンネルは Ctrl+C が押されるまで終了しません。

# Expose an existing local server. URL omitted => random three-word subdomain.
appgarden tunnel open 3000

# Use server domain subdomain shorthand or an explicit URL
appgarden tunnel open 3000 --subdomain preview
appgarden tunnel open 3000 --url preview.apps.example.com

# Run a local command while the tunnel is open
appgarden tunnel open 3000 --cmd "npm run dev"
appgarden tunnel open 3000 --cmd "npm run dev" --close-on-cmd-exit

# Serve a local file or directory. LOCAL_PORT is optional with --serve.
appgarden tunnel open --serve ./dist --subdomain docs-preview
appgarden tunnel open --serve ./dist --include "*.html" --exclude "node_modules"

# Reclaim a URL a dead run still holds, then open (idempotent re-open)
appgarden tunnel open 3000 --url preview.apps.example.com --replace

appgarden tunnel list [-s server]
appgarden tunnel list --json [-s server]      # machine-readable, for scripting
appgarden tunnel close <tunnel-id> [-s server]
appgarden tunnel cleanup [-s server]

--cmd と --serve は同時に指定できません。--include/--exclude は、--serve の対象がディレクトリの場合にのみ適用されます。トンネルはリモートポートを割り当て、caddy/tunnels に Caddy の設定スニペットを書き込み、tunnels/active.json に状態を登録します。クリーンアップ時に、これらのリソースは削除されます。

無人で再オープンするには、--replace が必要です。 トンネルの Caddy 設定スニペットは、トンネル固有の ID をキーとしているため、クリーンアップせずにプロセスが終了した場合(再起動や SIGKILL など)、スニペットがホスト名を占有したまま残ります。その状態で同じ --url を指定して次に tunnel open を実行すると、Caddy の再読み込みが ambiguous site definition エラーで失敗し、トンネルはロールバックされます。--replace を指定すると、その URL に登録済みのトンネルがあれば先に閉じます。明示的な --url/--subdomain が必要です。サブドメインを自動生成する場合は照合できるものがないため、何もせずに処理を続けるのではなく、拒否されます。なお、tunnel cleanup は代わりにはなりません。リモートポートで待ち受けているプロセスがないトンネルだけを削除します。

トンネルは Ctrl+C だけでなく SIGTERM でも正常に終了するため、supervisord、systemd、docker stop などで監視対象を停止すると、登録、Caddy の設定スニペット、リモートポートが解放され、残存しません。

tunnel list --json は JSON 配列を出力します(トンネルがない場合は空の配列を出力し、人間向けの「No active tunnels.」という行は出力しません)。テーブルではなく、こちらを解析してください。

トラブルシューティングのワークフロー

  1. 設定とサーバーの指定先を確認します。

    appgarden config show
    appgarden server list
    appgarden server ping <server>
    
  2. アプリの状態とログを確認します。

    appgarden apps list --short
    appgarden apps status <app>
    appgarden apps logs <app> -n 200
    
  3. エラーを読んでから、再デプロイまたは再起動します。

    appgarden apps redeploy <app>
    appgarden apps restart <app>
    
  4. ローカルのソースをアップロードする際によくある問題:

    • ローカルに rsync がインストールされている必要があります。
    • 暗号化された SSH キーにはエージェントが必要です:eval $(ssh-agent) && ssh-add ~/.ssh/id_rsa。
    • root 以外でデプロイする際の権限エラーは、通常、appgarden server init --include group を再実行するか、リモートの所有者を修正する必要があることを示します。

このリポジトリのリファレンスファイル

生成された src/appgarden/*.py ファイルには「AUTOGENERATED」と記載されています。実装を変更する場合は通常、対応するソースファイル pts/appgarden/*.pct.py を編集してください。スキルや使用方法については、必要に応じて以下のファイルを参照してください。

  • README.md — ユーザー向けガイドと CLI リファレンス。
  • src/appgarden/cli.py / pts/appgarden/10_cli.pct.py — コマンド定義とオプション。
  • src/appgarden/config.py / pts/appgarden/00_config.pct.py — ローカル設定モデルとデフォルトの設定パス。
  • src/appgarden/environments.py / pts/appgarden/08_environments.pct.py — appgarden.toml の解析、マージの仕様、プレースホルダー。
  • src/appgarden/server.py / pts/appgarden/04_server.pct.py — サーバーの初期化手順。
  • src/appgarden/deploy.py / pts/appgarden/05_deploy.pct.py — デプロイの動作とリモートの状態。
  • src/appgarden/apps.py / pts/appgarden/06_apps.pct.py — アプリのライフサイクルと再デプロイの動作。
  • src/appgarden/routing.py / pts/appgarden/03_routing.pct.py — Caddy のルーティングと URL の競合時の動作。
  • src/appgarden/tunnel.py / pts/appgarden/09_tunnel.pct.py — トンネルの動作。

コメント