jpskill.com
📦 その他 コミュニティ

saas-controller

devenvプロジェクトでZuploやFronteggなどのクラウドサービス設定、ローカル開発環境の起動、デプロイ、シークレット管理、トラブルシューティングなど、saas-controllerサービスの設定と運用を支援するSkill。

📜 元の英語説明(参考)

Configure and operate saas-controller services in devenv projects. Use when configuring cloud services (Zuplo, Frontegg), running sc up for local dev, deploying with sc deploy, managing secrets with secretspec profiles, or troubleshooting saas-controller.

🇯🇵 日本人クリエイター向け解説

一言でいうと

devenvプロジェクトでZuploやFronteggなどのクラウドサービス設定、ローカル開発環境の起動、デプロイ、シークレット管理、トラブルシューティングなど、saas-controllerサービスの設定と運用を支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o saas-controller.zip https://jpskill.com/download/10039.zip && unzip -o saas-controller.zip && rm saas-controller.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10039.zip -OutFile "$d\saas-controller.zip"; Expand-Archive "$d\saas-controller.zip" -DestinationPath $d -Force; ri "$d\saas-controller.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して saas-controller.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → saas-controller フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

SaaS Controller

devenv のためのマルチクラウドサービスオーケストレーションです。プラグイン可能なプロバイダーによる宣言的なサービス定義を行います。ローカル開発(Tailscale HTTPS を使用した sc up)とクラウドデプロイメント(sc deploy)を管理します。

アーキテクチャ

プロバイダーは、サービスライフサイクル全体を所有します。各プロバイダーは、tailnet 上で HTTPS を行うための Tailscale サイドカーを持つ独自の docker-compose スタックを生成します。

┌──────────────────────────────────────────────────────┐
│                  saas-controller                      │
│                                                       │
│  ┌────────────────────────────────────────────────┐  │
│  │              Providers (WHAT)                   │  │
│  │  Each provider owns up() + deploy()            │  │
│  ├────────────────────────────────────────────────┤  │
│  │  zuplo          │ API gateway + docs portal    │  │
│  │  docker-compose │ Generic compose stacks       │  │
│  │  [your own]     │ via externalProviders        │  │
│  └────────────────────────────────────────────────┘  │
│                                                       │
│  sc up topology (per service):                        │
│  ┌──────────────────────────────────────────┐        │
│  │ docker-compose stack                      │        │
│  │  ┌───────────┐  ┌──────────────────────┐ │        │
│  │  │ tailscale │  │ app container(s)     │ │        │
│  │  │ sidecar   │◀─│ network_mode:        │ │        │
│  │  │           │  │   service:tailscale  │ │        │
│  │  │ HTTPS:443 │  │ PORT=3000            │ │        │
│  │  └───────────┘  └──────────────────────┘ │        │
│  │  URL: https://sc-<slug>-<service>.<tailnet> │     │
│  └──────────────────────────────────────────┘        │
└──────────────────────────────────────────────────────┘

インポート

# devenv.yaml
imports:
  - github:afterthought/saas-controller

または、flake 入力として:

# flake.nix
inputs.saas-controller.url = "github:afterthought/saas-controller";
# In your devenv module:
imports = [ inputs.saas-controller.outPath ];

例 A:最小限のサービス

Tailscale HTTPS でローカルで実行される hello-world サービス:

# devenv.nix
{ pkgs, lib, config, ... }:
{
  imports = [ /* saas-controller module */ ];

  saas-controller.services.hello-world = {
    enable = true;
    provider = "hello-world";
    providerConfig = {
      path = "examples/hello-world";  # dir with server.mjs + Dockerfile
    };
    environments = {
      local.enable = true;
    };
  };
}
sc up              # Starts compose stack with tailscale sidecar
                   # Prints: https://sc-<slug>-hello-world.<tailnet>:443

例 B:シークレットを持つ Zuplo ゲートウェイ

secretspec プロファイル、複数の環境、およびシークレット管理を備えた Zuplo API ゲートウェイ:

{ pkgs, lib, config, ... }:
{
  imports = [ /* saas-controller module */ ];

  saas-controller.services.my-gateway = {
    enable = true;
    displayName = "My API Gateway";
    provider = "zuplo";
    providerConfig = {
      project = "my-gateway";       # Zuplo project name
      account = "my-account";       # Zuplo account
      path = "services/my-gateway"; # Path to zuplo project in repo
    };

    environments = {
      local.enable = true;
      production.enable = true;
      preview.enable = true;
    };

    # Secret management
    secretspec = {
      auth.provider = "client-myorg";  # SecretSpec provider alias
      auth.saToken = "client-myorg";   # 1Password SA token alias
      environments = {
        local = {
          serviceProfiles = [ "tailscale" ];
          # → validates TS_CLIENT_SECRET, TS_CLIENT_ID
        };
        production = {
          serviceProfiles = [ "zuplo-backend" ];
          # → validates zuplo secrets for production
        };
      };
      tags = [ "tailscale" "zuplo" ]; # For filtered checking
    };
  };
}
sc up                              # Start locally with tailscale HTTPS
sc deploy my-gateway -e production  # Deploy to production
sc check-secrets --tag tailscale   # Validate tailscale secrets

シークレットプロファイル

シークレットは、コントローラーレベルのプロファイル定義とサービスごとの構成の2つのレイヤーで管理されます。

コントローラーレベル:プロファイルの定義

saas-controller.secretProfiles = {
  tailscale = {
    TS_CLIENT_SECRET = {
      description = "Tailscale OAuth client secret";
      required = true;
      providers = [ "saas-controller" ];
    };
    TS_CLIENT_ID = {
      description = "Tailscale OAuth client ID";
      required = false;
      providers = [ "saas-controller" ];
    };
  };
  my-api-keys = {
    API_KEY = {
      description = "External API key";
      providers = [ "saas-controller" ];
    };
  };
};

サービスレベル:環境ごとのプロファイルの構成

services.my-service.secretspec = {
  auth.provider = "client-myorg";      # SecretSpec provider alias
  auth.saToken = "client-myorg";       # 1Password SA token alias
  environments = {
    local = {
      serviceProfiles = [ "tailscale" ];
      # Only tailscale secrets needed locally
    };
    production = {
      serviceProfiles = [ "my-api-keys" ];
      # API keys needed for production deployment
    };
  };
  tags = [ "tailscale" ];            # For sc check-secrets --tag
};

プロバイダーの自動エクスポート

プロバイダーは、実装で secretProfiles を宣言できます。これらは自動的に saas-controller.secretProfiles にマージされます。サービスがプロバイダーを使用すると、そのプロバイダーのプロファイルが自動的に含まれます。手動での配線は不要です。

たとえば、zuplo プロバイダーは zuplo および zudoku プロファイルをエクスポートします。provider = "zuplo" を持つサービスは、これらのプロファイルを自動的に利用できるようになります。

シークレットの確認

sc check-secrets                         # Check all services
sc check-secrets --tag tailscale         # Only tailscale-tagged services
sc check-secrets --service my-gateway    # Specific service
sc secret-status                         # Show secret-to-service mapping

(原文がここで切り詰められています)
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

SaaS Controller

Multi-cloud service orchestration for devenv. Declarative service definitions with pluggable providers. Manages local dev (sc up with Tailscale HTTPS) and cloud deployment (sc deploy).

Architecture

Providers own the full service lifecycle. Each provider generates its own docker-compose stack with a Tailscale sidecar for HTTPS on the tailnet.

┌──────────────────────────────────────────────────────┐
│                  saas-controller                      │
│                                                       │
│  ┌────────────────────────────────────────────────┐  │
│  │              Providers (WHAT)                   │  │
│  │  Each provider owns up() + deploy()            │  │
│  ├────────────────────────────────────────────────┤  │
│  │  zuplo          │ API gateway + docs portal    │  │
│  │  docker-compose │ Generic compose stacks       │  │
│  │  [your own]     │ via externalProviders        │  │
│  └────────────────────────────────────────────────┘  │
│                                                       │
│  sc up topology (per service):                        │
│  ┌──────────────────────────────────────────┐        │
│  │ docker-compose stack                      │        │
│  │  ┌───────────┐  ┌──────────────────────┐ │        │
│  │  │ tailscale │  │ app container(s)     │ │        │
│  │  │ sidecar   │◀─│ network_mode:        │ │        │
│  │  │           │  │   service:tailscale  │ │        │
│  │  │ HTTPS:443 │  │ PORT=3000            │ │        │
│  │  └───────────┘  └──────────────────────┘ │        │
│  │  URL: https://sc-<slug>-<service>.<tailnet> │     │
│  └──────────────────────────────────────────┘        │
└──────────────────────────────────────────────────────┘

Import

# devenv.yaml
imports:
  - github:afterthought/saas-controller

Or as a flake input:

# flake.nix
inputs.saas-controller.url = "github:afterthought/saas-controller";
# In your devenv module:
imports = [ inputs.saas-controller.outPath ];

Example A: Minimal Service

A hello-world service running locally with Tailscale HTTPS:

# devenv.nix
{ pkgs, lib, config, ... }:
{
  imports = [ /* saas-controller module */ ];

  saas-controller.services.hello-world = {
    enable = true;
    provider = "hello-world";
    providerConfig = {
      path = "examples/hello-world";  # dir with server.mjs + Dockerfile
    };
    environments = {
      local.enable = true;
    };
  };
}
sc up              # Starts compose stack with tailscale sidecar
                   # Prints: https://sc-<slug>-hello-world.<tailnet>:443

Example B: Zuplo Gateway with Secrets

A Zuplo API gateway with secretspec profiles, multiple environments, and secret management:

{ pkgs, lib, config, ... }:
{
  imports = [ /* saas-controller module */ ];

  saas-controller.services.my-gateway = {
    enable = true;
    displayName = "My API Gateway";
    provider = "zuplo";
    providerConfig = {
      project = "my-gateway";       # Zuplo project name
      account = "my-account";       # Zuplo account
      path = "services/my-gateway"; # Path to zuplo project in repo
    };

    environments = {
      local.enable = true;
      production.enable = true;
      preview.enable = true;
    };

    # Secret management
    secretspec = {
      auth.provider = "client-myorg";  # SecretSpec provider alias
      auth.saToken = "client-myorg";   # 1Password SA token alias
      environments = {
        local = {
          serviceProfiles = [ "tailscale" ];
          # → validates TS_CLIENT_SECRET, TS_CLIENT_ID
        };
        production = {
          serviceProfiles = [ "zuplo-backend" ];
          # → validates zuplo secrets for production
        };
      };
      tags = [ "tailscale" "zuplo" ]; # For filtered checking
    };
  };
}
sc up                              # Start locally with tailscale HTTPS
sc deploy my-gateway -e production  # Deploy to production
sc check-secrets --tag tailscale   # Validate tailscale secrets

Secret Profiles

Secrets are managed in two layers: controller-level profile definitions and per-service composition.

Controller Level: Define profiles

saas-controller.secretProfiles = {
  tailscale = {
    TS_CLIENT_SECRET = {
      description = "Tailscale OAuth client secret";
      required = true;
      providers = [ "saas-controller" ];
    };
    TS_CLIENT_ID = {
      description = "Tailscale OAuth client ID";
      required = false;
      providers = [ "saas-controller" ];
    };
  };
  my-api-keys = {
    API_KEY = {
      description = "External API key";
      providers = [ "saas-controller" ];
    };
  };
};

Service Level: Compose profiles per environment

services.my-service.secretspec = {
  auth.provider = "client-myorg";      # SecretSpec provider alias
  auth.saToken = "client-myorg";       # 1Password SA token alias
  environments = {
    local = {
      serviceProfiles = [ "tailscale" ];
      # Only tailscale secrets needed locally
    };
    production = {
      serviceProfiles = [ "my-api-keys" ];
      # API keys needed for production deployment
    };
  };
  tags = [ "tailscale" ];            # For sc check-secrets --tag
};

Provider Auto-Export

Providers can declare secretProfiles in their implementation. These are automatically merged into saas-controller.secretProfiles. When a service uses a provider, that provider's profiles are auto-included — no manual wiring needed.

For example, the zuplo provider exports zuplo and zudoku profiles. Any service with provider = "zuplo" automatically gets those profiles available.

Checking Secrets

sc check-secrets                         # Check all services
sc check-secrets --tag tailscale         # Only tailscale-tagged services
sc check-secrets --service my-gateway    # Specific service
sc secret-status                         # Show secret-to-service mapping table

CLI Reference

# Local development
sc up                                    # Start all local services
sc up my-gateway                         # Start specific service

# Deployment
sc deploy                                # Deploy all to production (default)
sc deploy --environment production       # Deploy all to production
sc deploy my-gateway -e preview          # Deploy specific service to preview
sc undeploy my-gateway                   # Remove persistent service

# Secret management
sc check-secrets                         # Validate all service secrets
sc check-secrets --tag tailscale         # Filter by tag
sc check-secrets --service my-gateway    # Filter by service
sc secret-status                         # Secret-to-service mapping table

# Secret reconciliation
sc setup-env production                  # Check all secrets for production
sc diff-secrets local production         # Compare secrets between environments
sc reconcile-secrets                     # Show all secrets across all environments
sc reconcile-secrets -e production       # Show secrets for one environment

# Other
sc help                                  # Show help
provision-projects                       # One-time project setup

Task Integration

# sc up is also available as a devenv task
devenv tasks run saas:up

# Deploy with environment via task input
DEVENV_TASK_INPUT='{"environment": "production"}' devenv tasks run saas-deploy:my-gateway

Provider Summary

Provider providerConfig keys sc up? Auto-exported profiles
zuplo project, account, path Yes zuplo, zudoku
docker-compose path, composeFile(opt), tailscale(opt) Yes (none)

For detailed provider documentation: read references/provider-reference.md

Extensibility

Register custom providers:

saas-controller.externalProviders.my-provider = ./providers/my-provider.nix;

See EXTENDING.md for provider authoring guide and template.

Tailscale Setup

sc up requires one-time Tailscale setup (ACL tags, OAuth client). See references/tailscale-setup.md for step-by-step instructions.

SA Token Provider Setup

Services with secretspec.auth.saToken need the sa-tokens secretspec provider alias configured. The secretspec.toml is auto-generated from service configs at nix eval time — developers only configure the provider backend once.

One-time setup per machine:

secretspec config provider add sa-tokens "keyring://"   # macOS Keychain
secretspec config provider add sa-tokens "env://"       # Environment variables (CI)

Naming: saToken = "client-willdan" maps to OP_SA_CLIENT_WILLDAN.

Verify: secretspec config provider list

Deeper Questions

For questions not covered here, use DeepWiki MCP:

ask_question("afterthought/saas-controller", "<your question>")

Or read the source at github:afterthought/saas-controller.