---
title: "Semaphore UIとは？Ansible・TerraformのWeb UIの導入手順と料金、AWXとの違い【v2.19】"
url: "https://www.issoh.co.jp/tech/details/12399/"
published: 2026-06-08
updated: 2026-10-23
categories: ["IaC"]
publisher: "株式会社一創"
---

# Semaphore UIとは？Ansible・TerraformのWeb UIの導入手順と料金、AWXとの違い【v2.19】

Semaphore UIは、Ansibleのプレイブックや Terraform・OpenTofu、Bash、PowerShell、Python のスクリプトを、ブラウザとREST APIから実行・記録できるセルフホスト型のツールです。2026年10月23日時点の安定版は v2.19.17（2026年10月20日公開、[GitHub Releases](https://github.com/semaphoreui/semaphore/releases)）で、本体はMITライセンスのOSSとして無料で使えます。この記事では、構成要素の関係、Dockerでの導入手順、APIとWebhookでのタスク起動、Runnerの登録、Terraformでの設定管理、有料版との機能差、AWXとの選び方を、v2.19.17のCommunityビルドを手元で起動して確かめた結果と公式情報をもとに整理します。

## まとめ：Semaphore UIの要点と選び方

- 旧称は「Ansible Semaphore」。GitHubの旧リポジトリ ansible-semaphore/semaphore は現在 semaphoreui/semaphore へ転送されます。
- テンプレートで選べる組み込みアプリは Ansible・Terraform・OpenTofu・Terragrunt・Bash・PowerShell・Python の7種です。
- 試すだけなら `docker run` 1行（SQLite）で起動し、`http://localhost:3000` を開けば使えます。1台・1チームならSQLiteのままでよく、複数チームで使う、既存のDB基盤でバックアップを取る、HAを予定する場合はPostgreSQLかMySQLにします。
- 料金は Community $0、Pro が月額$20から（管理ノード数とTerraformリソース数で決まる容量課金）、Enterprise が個別見積もりです。2FA・LDAP・OIDC は料金表ではPro以上に載っています。
- GitHubなど外部からの起動は Integration（受信Webhook）で行います。HMAC署名が合わなくても応答は204のままで、タスクが作られないだけなので、疎通確認はタスク一覧かサーバーログで行います。
- Runnerは登録しただけでは使われません。有効化し、タグ指定の無いテンプレート用に「既定」のRunnerを1台決めておく必要があります。
- AWXは2024年7月2日の24.6.1を最後にリリースを止めています。Kubernetesを用意せずにAnsibleをチームで回したいなら、Semaphore UIが第一候補になります。

以下、仕組み→導入→APIとWebhook→Terraformでの設定管理→料金→AWXとの比較→運用の落とし穴の順に説明します。

## Semaphore UIの位置づけと「Ansible Semaphore」との関係

Semaphore UIはGo製のサーバーで、単一バイナリかDockerイメージとして配布されます。公式ドキュメントはLinux・macOS・Windowsでの動作をうたっており、v2.19.17のリリースにも darwin・linux・windows 向けのアーカイブ、deb、rpm が並んでいます。データの保存先はSQLite・MySQL・PostgreSQLの3種です。

### 7種の組み込みアプリと実行マシンに必要なツール

もともとはAnsible用のWeb UIでしたが、現在はテンプレートごとに「アプリ」を選んで任意の自動化ツールを呼び出す作りです。[公式ドキュメントのアプリ一覧](https://semaphoreui.com/docs/user-guide/apps)は次のとおりです。

| アプリ               | ID         | 実行されるもの          | 公式Dockerイメージに同梱 |
| ----------------- | ---------- | ---------------- | --------------- |
| Ansible Playbook  | ansible    | ansible-playbook | あり              |
| Terraform Code    | terraform  | terraform        | あり              |
| OpenTofu Code     | tofu       | tofu             | あり              |
| Terragrunt Code   | terragrunt | terragrunt       | なし              |
| Bash Script       | bash       | /bin/bash        | あり              |
| PowerShell Script | powershell | pwsh で .ps1      | なし              |
| Python Script     | python     | python3 で .py    | あり              |

公式ドキュメントは「ツール自体はタスクを実行するマシン（サーバーかRunner）に入っている必要がある」と明記し、公式Dockerイメージに入っているのは Ansible・Terraform・OpenTofu・Bash・Python だと書いています。つまり既定のタグのままでは PowerShell と Terragrunt は動きません。PowerShellについては、Docker Hubの semaphoreui/semaphore に `v2.19.17-powershell7.5.0` のようなPowerShell入りのタグも公開されています。PowerShellテンプレートを作る前に、実行するマシンで `pwsh --version` が通るかを確かめてください。OpenTofu と Terraform の使い分けは[OpenTofuとTerraformのライセンス・機能差](/tech/details/15299/)、Terragrunt の役割は[Terragruntの基本概念と導入メリット](/tech/details/12477/)で扱っています。

### 旧称Ansible Semaphoreと別製品Semaphore CIの見分け方

「ansible semaphore」で検索して出てくる記事の多くは、改称前の名前で同じ製品を指しています。GitHub APIで `ansible-semaphore/semaphore` を引くと `semaphoreui/semaphore` が返り、リポジトリの作成日は2014年8月23日です。古い記事にある `ansible-semaphore` 名義の手順やDockerイメージ名は、現行版では読み替えが必要です。

一方、semaphore.io の「Semaphore」はCI/CDのSaaSで、まったく別の製品です。料金や「Enterprise版の無料条件」を調べると semaphore.io の情報が混ざるので、ドメインが semaphoreui.com かどうかで見分けてください。

## Semaphore UIの構成要素：プロジェクト・キーストア・インベントリ・テンプレートの関係

画面の項目が多く見えますが、実体は「プロジェクトの中に、テンプレートが参照する部品を登録する」構造です。テンプレートを1本作るまでに次の部品が要ります。

| 部品             | 中身                    | APIのパス                         |
| -------------- | --------------------- | ------------------------------ |
| Key Store      | SSH鍵・パスワード・Vaultパスワード | /api/project/{id}/keys         |
| Repository     | Gitリポジトリとブランチ         | /api/project/{id}/repositories |
| Inventory      | 静的・ファイル・動的インベントリ      | /api/project/{id}/inventory    |
| Variable Group | 追加変数と環境変数             | /api/project/{id}/environment  |
| Task Template  | アプリ・実行ファイル・上記の組み合わせ   | /api/project/{id}/templates    |

権限はプロジェクト単位で付与するので、本番と検証を別プロジェクトに分けておけば、検証用の鍵や変数を本番のテンプレートが参照することはありません。Variable Group（APIでは environment）に入れた環境変数は、タスク実行時にプロセスへ渡されます。v2.19.16と2.19.17で `GREETING=hi` を登録したBashテンプレートを実行すると、スクリプトの出力に `GREETING=hi` がそのまま現れました。

### タスクテンプレートとcronスケジュールの既定タイムゾーン

テンプレートは手動実行のほか、cron式のスケジュールで定期実行できます。cronは5フィールド固定で、4フィールドで登録すると `Cron: expected exactly 5 fields, found 4` の400エラーが返ります。

見落としやすいのはタイムゾーンです。v2.19.17のソース（util/config.go）では `SEMAPHORE_SCHEDULE_TIMEZONE` の既定値が UTC で、起動直後の `/api/info` も `"schedule_timezone":"UTC"` を返します。日本時間の深夜3時に流すつもりで `0 3 * * *` と書くと、実際には正午に動きます。国内運用なら最初に `SEMAPHORE_SCHEDULE_TIMEZONE=Asia/Tokyo` を設定してください。

### Runnerでサーバーと実行場所を分ける仕組み

Runnerを定義しない場合、タスクはSemaphore UIサーバー自身の上で、サーバーのファイルシステムにアクセスできる状態で実行されます。Runnerは GitLab Runner や GitHub Actions のランナーと同じ考え方で、別サーバーで `semaphore runner start` を動かすと、サーバーからジョブを受け取り、リポジトリをcloneして実行し、結果を返します。サーバー側では `SEMAPHORE_USE_REMOTE_RUNNER=True` と登録トークン（`SEMAPHORE_RUNNER_REGISTRATION_TOKEN`）を設定します。

料金表上、全プロジェクト共通のGlobal RunnerはCommunityでも使え、プロジェクト専用のProject RunnerはPro以上の機能です。閉じたサブネットのサーバーを操作したいだけなら、まずGlobal Runnerを1台置く構成で足ります。v2.19.17のCommunityビルドで、サーバーと同じマシンにGlobal Runnerを登録した手順は次のとおりです。

```
# Runner側：サーバーのURLとトークンの保存先を決めて登録する
# 事前に保存先ディレクトリを作り、Runner実行ユーザーに書き込み権限を与える
# REGISTRATION_TOKENにはサーバー側に設定した登録トークンを渡す
export SEMAPHORE_WEB_ROOT=http://semaphore.example.internal:3000
export SEMAPHORE_RUNNER_TOKEN_FILE=/etc/semaphore/runner.token
echo "$REGISTRATION_TOKEN" | semaphore runner register --no-config \
  --stdin-registration-token --name runner-1

# 登録後、サーバーにポーリングしてジョブを待つ（間隔は2.19.17で追加された設定）
export SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS=1
semaphore runner start --no-config
```

ここで詰まりやすい点が3つありました。1つ目に、サーバーで `SEMAPHORE_USE_REMOTE_RUNNER` を有効にすると、使えるRunnerが無い間のタスクはすべて即座に `error` になり、出力に「Failed to run task: no runners available」と出ます。サーバー自身で実行する動きには戻りません。2つ目に、登録直後のRunnerは `/api/runners` で `"active":false`・`"is_default":false` でした。有効化してもまだ同じエラーが続き、Runnerを「既定」にして初めてタスクが割り当たりました。ソース（services/tasks/RemoteJob.go）を見ると、Runnerタグを指定していないテンプレートは、既定に設定したRunnerだけを探す作りです。3つ目は、テンプレートの実行に必要なツールがRunner側に要る点で、これはサーバー単体のときと同じです。

v2.19.17で追加された `SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS`（既定1秒）は、Runnerが新しいジョブを問い合わせる間隔です。Runnerが多いサーバーでリクエスト数を減らすための設定で、生存確認の通信は1秒間隔のまま変わりません。手元で各6回測ると、タスク作成から開始までは1秒設定で3.9〜6.4秒（平均5.7秒）、10秒設定で4.9〜12.2秒（平均7.7秒）でした。Runnerが数台なら既定のままで構いません。

## Semaphore UIをDockerで導入する手順と本番前に変える設定

公式ドキュメントのクイックスタートはSQLiteを使う1コマンドです。DBは、サーバー1台・チーム1つならSQLite（既定）で足ります。公式の前提条件ページは、利用者が少人数を超える場合、既存のDB基盤でバックアップや監視をしたい場合、複数ノードで動かす場合にPostgreSQLかMySQLを勧めています。HA構成はPostgreSQLかMySQLに加えてRedisが必要で、SQLiteでは組めません。

### SQLiteで1コマンド起動するクイックスタート

公式のクイックスタートをもとに、公開先をローカルホストに限定した例です（公式は `-p 3000:3000` で、全インターフェースに公開されます）。起動後に `http://localhost:3000` を開き、admin / changeme でログインします。

```
docker run -d -p 127.0.0.1:3000:3000 \
  -e SEMAPHORE_DB_DIALECT=sqlite \
  -e SEMAPHORE_ADMIN=admin \
  -e SEMAPHORE_ADMIN_PASSWORD=changeme \
  -e SEMAPHORE_ADMIN_NAME=Admin \
  -e SEMAPHORE_ADMIN_EMAIL=admin@localhost \
  -v semaphore-data:/var/lib/semaphore \
  semaphoreui/semaphore:latest
```

このまま社内に公開しないでください。パスワードが公式ドキュメントに載っている既定値で、鍵類も未指定です。検証用と割り切り、確認が済んだら下の構成へ移します。

### Docker ComposeでPostgreSQLへ切り替える構成

公式のCompose例はMySQL 8.0版で、コメントを外せばPostgreSQLに切り替わる形になっています。PostgreSQLで書き直すと次のようになります。`${DB_PASS}` などの値は、同じディレクトリの `.env` に `DB_PASS`・`ADMIN_PASS`・`ACCESS_KEY_ENCRYPTION` の3行で書き、`docker compose up -d` で起動します（公式のMySQL版の例を、変数名はそのままにPostgreSQL向けへ書き換えたものです）。

```
services:
  postgres:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_USER: semaphore
      POSTGRES_PASSWORD: ${DB_PASS}
      POSTGRES_DB: semaphore
    volumes:
      - semaphore-postgres:/var/lib/postgresql/data
  semaphore:
    image: semaphoreui/semaphore:v2.19.17
    restart: unless-stopped
    ports:
      # 社内公開時はHTTPSを終端するリバースプロキシを別途設定する
      - "127.0.0.1:3000:3000"
    environment:
      SEMAPHORE_DB_DIALECT: postgres
      SEMAPHORE_DB_HOST: postgres
      SEMAPHORE_DB_PORT: 5432
      SEMAPHORE_DB_USER: semaphore
      SEMAPHORE_DB_PASS: ${DB_PASS}
      SEMAPHORE_DB: semaphore
      SEMAPHORE_ADMIN: admin
      SEMAPHORE_ADMIN_NAME: admin
      SEMAPHORE_ADMIN_EMAIL: admin@example.com
      SEMAPHORE_ADMIN_PASSWORD: ${ADMIN_PASS}
      SEMAPHORE_ACCESS_KEY_ENCRYPTION: ${ACCESS_KEY_ENCRYPTION}
      SEMAPHORE_SCHEDULE_TIMEZONE: Asia/Tokyo
    depends_on:
      - postgres
volumes:
  semaphore-postgres:
```

公式ドキュメントが「必ず指定する」としている機密値は、DBパスワード、管理者パスワード、`SEMAPHORE_ACCESS_KEY_ENCRYPTION` の3つです。最後の値はKey Storeに保存するSSH鍵やパスワードを暗号化する鍵で、`head -c32 /dev/urandom | base64` で生成します。イメージのタグは `latest` でなく版番号で固定しておくと、`docker compose pull` でイメージを取り直してコンテナを作り直したときに、意図せず版が上がる事故を防げます。Docker Swarmなら環境変数名に `_FILE` を付けてDocker Secretsから読ませる方式も公式に用意されています。MySQLを選ぶ場合のタグ選定とCompose定義は[DockerでMySQLを構築する手順](/tech/details/17642/)が参考になります。

### バイナリ直起動で詰まる管理者作成とCookie鍵

Dockerを使わずバイナリを直接起動する場合、Composeと同じ環境変数を渡しても管理者は作られません。`SEMAPHORE_ADMIN` 系の変数を読んで管理者を作っているのはDockerイメージの起動スクリプト（deployment/docker/server/server-wrapper）で、バイナリ本体ではないためです。v2.19.16と2.19.17のCommunityビルドを `--no-config` とSQLiteで起動したところ、環境変数だけではログインが401になり、CLIでユーザーを足して初めて入れました。

SQLiteのファイルの場所にも注意が要ります。公式Compose例のコメントにある `SEMAPHORE_DB` でパスを渡しても、バイナリ直起動ではその値が使われず、作業ディレクトリに「0.0.0.0」という名前のDBファイルができました。SQLiteのファイルパスを受け取るのは `SEMAPHORE_DB_HOST` です（ソースでは既定値が 0.0.0.0）。保存先のディレクトリは事前に作り、実行ユーザーに書き込み権限を与えておきます。次の例は、初回だけ鍵を生成してファイルに保存し、2回目以降の起動でも同じ鍵を読み込む形にしています。起動のたびに鍵を作り直すと、保存済みの鍵やパスワードを復号できなくなるためです。

```
# 初回だけ：鍵を3つ生成してファイルに保存する（このファイルはバックアップ対象）
if [ ! -f semaphore-secrets.env ]; then
  for k in ACCESS_KEY_ENCRYPTION COOKIE_HASH COOKIE_ENCRYPTION; do
    echo "SEMAPHORE_$k=$(head -c32 /dev/urandom | base64)"
  done > semaphore-secrets.env
  chmod 600 semaphore-secrets.env
fi

# 毎回：保存した鍵を読み込み、SQLiteのパスはDB_HOSTで渡す
set -a; . ./semaphore-secrets.env; set +a
export SEMAPHORE_DB_DIALECT=sqlite
export SEMAPHORE_DB_HOST=/var/lib/semaphore/semaphore.sqlite

# 初回だけ：管理者を作る
semaphore users add --no-config --admin \
  --login admin --name admin --email admin@example.com --password '変更する'

semaphore server --no-config
```

もう1つの落とし穴が `SEMAPHORE_COOKIE_HASH` です。未設定のまま起動するとサーバーは立ち上がりますが、ログイン時に500エラーになり、ログに `securecookie: hash key is not set` が出ます。対話式の `semaphore setup` を使えば、ソース上の GenerateSecrets がこれらの鍵を生成して設定ファイルに書き込むので、環境変数だけで組むときに限って起きる問題です。

### BoltDBからSQLite・PostgreSQLへの移行経路と対応バージョン

古い記事ではBoltDBが選択肢に挙がっていますが、v2.19.17のソースではBoltDBのドライバに `Deprecated: replaced with sqlite` と注記されています。公式ドキュメントによると、BoltDBからSQLite・MySQL・PostgreSQLへ移す移行機能は2.17と2.18にしかありません。BoltDBで動いている古い環境は、いきなり2.19へ上げず、2.18で移行を済ませてから上げる順番になります。2.18系は2026年10月時点でもセキュリティ修正の対象で、v2.18.31が2026年10月7日に出ています。

## Semaphore UIのREST APIでタスクを起動する手順

画面でできる操作はREST APIでも行えます。起動中のサーバーの `/swagger/` にSwagger UIが同梱されているので、パラメータはそこで確認できます。CIやチャットボットから既存テンプレートを起動する場合、流れは「ログイン→APIトークン発行→タスク作成→出力取得」です。

```
B=http://localhost:3000/api

# 1. ログインしてセッションCookieを得る（成功は204）
curl -s -c ck -H 'Content-Type: application/json' \
  -d '{"auth":"admin","password":"changeme"}' $B/auth/login

# 2. APIトークンを発行する
TOKEN=$(curl -s -b ck -X POST $B/user/tokens | jq -r .id)

# 3. プロジェクト1のテンプレート1をタスクとして実行し、作成されたタスクIDを取る
TASK_ID=$(curl -fsS -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"template_id":1}' "$B/project/1/tasks" | jq -er .id)

# 4. そのタスクの状態と出力を取得する
curl -fsS -H "Authorization: Bearer $TOKEN" "$B/project/1/tasks/$TASK_ID"
curl -fsS -H "Authorization: Bearer $TOKEN" "$B/project/1/tasks/$TASK_ID/output"
```

v2.19.17でこの手順を流すと、タスクは `success` で終わり、出力APIには「Task hello added to queue」から始まる実行ログが1行ずつ返りました。テンプレートが参照するGitリポジトリは実行のたびに取得し直されるため、コミットを追加してからもう一度タスクを作ると、新しいコミットの内容で実行されます。トークンは発行したユーザーの権限でAPIを呼ぶため、管理者のトークンをCIに渡すと全プロジェクトを操作できてしまいます。CI用には専用ユーザーを作り、必要なプロジェクトだけに参加させてから発行してください。

### Integration（受信Webhook）によるGitHubなどからのテンプレート起動

APIトークンを外部サービスに渡したくない場合は、プロジェクトの Integrations を使います。受け口のURLは `/api/integrations/<ランダムな文字列>` の形で、GETかPOSTでタスクが起動します。URLには2種類あります。Integrations一覧の上に出るプロジェクト共通のURLは、全Integrationの Matchers（受信内容の条件）を照合し、一致したものを起動します。Integrationごとに発行する個別のURLは、Matchersを評価せずにそのIntegrationを起動します。ブランチやイベントで絞るなら共通URL、常に同じテンプレートを動かすなら個別URLです。[公式ドキュメント](https://semaphoreui.com/docs/user-guide/integrations)によると、認証方式は GitHub Webhooks・トークン・HMAC（SHA-256/SHA-512）・認証なしから選べます。HMACの秘密鍵には、Key Storeに登録したログイン/パスワード型の鍵の「パスワード」が使われます。

送信側は、リクエスト本文のHMACを16進数でヘッダーに入れます。ドキュメントの例をSHA-256に置き換えると次の形です。

```
SECRET='Key Storeに登録したパスワード'
BODY='{"ref":"refs/heads/release-1.2"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')

curl -X POST "https://semaphore.example.com/api/integrations/<alias>" \
  -H 'Content-Type: application/json' \
  -H "X-Signature: ${SIG}" \
  --data "$BODY"
```

v2.19.17で、認証ヘッダーを `X-Signature` にしたHMAC（SHA-256）のIntegrationを作り、個別のURLへ4通りの送り方を試しました。

| 送り方                      | HTTPの応答 | タスク    | サーバーログ                 |
| ------------------------ | ------- | ------ | ---------------------- |
| 正しい署名                    | 204     | 1件作成   | －                      |
| GitHub式の `sha256=` 接頭辞つき | 204     | 作成されない | Invalid HMAC signature |
| 誤った署名                    | 204     | 作成されない | Invalid HMAC signature |
| 署名なし                     | 204     | 作成されない | Invalid HMAC signature |

署名が通らなくても応答は204で、送信側からは成功と見分けがつきません。存在しないURLに送った場合も200が返りました。GitHubのWebhook設定画面で配信が成功と表示されても、タスクが作られているとは限らないので、最初の疎通はタスク一覧とサーバーログで確かめてください。GitHubから送るなら、接頭辞の扱いが違うHMACではなく、認証方式「GitHub Webhooks」を選びます。

本文の値をタスクへ渡すには Value Extractors を使います。種類を Environment にした値は、Variable Groupの変数と同じ扱いでタスクに入ります。Ansibleなら追加変数になりますが、Bashテンプレートでは環境変数にならず、`REF=refs/heads/release-1.2` という文字列がスクリプトの引数として渡されました（`$REF` は空で、`$1` に入る）。Bashで受けるときは引数を解析する前提で書きます。

## Terraform providerによるSemaphore UI設定のコード管理

プロジェクト・鍵・リポジトリ・インベントリ・テンプレートを画面で作ると、検証環境と本番環境で設定がずれていきます。Semaphore UIの設定そのものはTerraformで管理できます。プロバイダは公式の [semaphoreui/semaphore](https://registry.terraform.io/providers/semaphoreui/semaphore/latest)（2026年10月6日公開の0.3.10。まだ1.0未満）と、第三者製の CruGlobal/semaphoreui（1.5.0）の2つがTerraform Registryにあります。ここでは公式のほうを使いました。

```
terraform {
  required_providers {
    semaphoreui = {
      source  = "semaphoreui/semaphore"
      version = "0.3.10"
    }
  }
}

# 接続先とトークンは環境変数 SEMAPHOREUI_API_BASE_URL / SEMAPHOREUI_API_TOKEN で渡す
provider "semaphoreui" {}

resource "semaphoreui_project" "ops" {
  name = "ops"
}

resource "semaphoreui_project_key" "none" {
  project_id = semaphoreui_project.ops.id
  name       = "none"
  none       = {}
}

resource "semaphoreui_project_repository" "scripts" {
  project_id = semaphoreui_project.ops.id
  name       = "scripts"
  # mainブランチにhello.shを置いた、実行環境から取得可能なリポジトリURLへ置換する
  url        = "https://github.com/example/ops-scripts.git"
  branch     = "main"
  ssh_key_id = semaphoreui_project_key.none.id
}

resource "semaphoreui_project_inventory" "localhost" {
  project_id = semaphoreui_project.ops.id
  name       = "localhost"
  ssh_key_id = semaphoreui_project_key.none.id
  static = {
    inventory = "localhost ansible_connection=local"
  }
}

resource "semaphoreui_project_environment" "prod" {
  project_id  = semaphoreui_project.ops.id
  name        = "prod"
  environment = { GREETING = "from-terraform" }
}

resource "semaphoreui_project_template" "hello" {
  project_id     = semaphoreui_project.ops.id
  name           = "hello"
  app            = "bash"
  playbook       = "hello.sh"
  repository_id  = semaphoreui_project_repository.scripts.id
  inventory_id   = semaphoreui_project_inventory.localhost.id
  environment_id = semaphoreui_project_environment.prod.id
}
```

Terraform 1.17.0とv2.19.17のサーバーで `terraform apply` すると6リソースが作られ、続けて `terraform plan -detailed-exitcode` を流すと差分なし（終了コード0）でした。画面側でテンプレート名を変えてからもう一度planを流すと、終了コード2で `name = "hello-edited-in-ui" -> "hello"` という戻す差分が出ます。CIで定期的にplanを流せば、画面からの手作業の変更を検出できます。

APIトークンはproviderのドキュメントでも環境変数で渡すよう勧められています。tfファイルには書かないでください。鍵の中身も同様です。`semaphoreui_project_key` の `private_key` や `password` は、ドキュメントに「Persisted to Terraform state」と書かれているとおりstateファイルに残ります。Vaultなどから値を渡すなら、stateに残らない `private_key_wo`・`password_wo`（write-only引数）を使います。ただし、取得元が通常のTerraform data sourceなら、その取得値がstateに残る可能性があります。値の取得側もephemeral対応にし、他のリソースやoutputへ保存しない構成にします。

## Community・Pro・Enterpriseの料金と機能差（2026年10月時点）

3プランとも自社環境で動かすセルフホスト型です。[公式料金ページ](https://semaphoreui.com/pricing)の比較表から、選定に効く行を抜き出しました。

| 機能                              | Community | Pro       | Enterprise |
| ------------------------------- | --------- | --------- | ---------- |
| 価格                              | $0        | $20/月から   | 個別見積もり     |
| 7種のアプリ・cron・Webhook・REST API    | ○         | ○         | ○          |
| Global Runner                   | ○         | ○         | ○          |
| Project Runner・Docker実行         | －         | ○         | ○          |
| Terraform/OpenTofuのHTTP backend | －         | ○         | ○          |
| 2FA（TOTP）・LDAP/AD・OIDC          | －         | ○         | ○          |
| HashiCorp Vault・OpenBao         | －         | ○         | ○          |
| Kubernetes実行・高可用性構成             | －         | －         | ○          |
| カスタムロール・テンプレート単位の権限             | －         | －         | ○          |
| IdPグループとロールの連携                  | －         | －         | ○（要確認）     |
| サポートSLA                         | －         | 48時間（営業日） | 個別         |

旧来の解説に多い「Terraform連携はPro版」という説明は現行の表と合いません。Terraform・OpenTofuの実行そのものはCommunityでできます。Proで足されるのは、stateをSemaphore UIに置くHTTP backendです。

### Proの課金単位：管理ノード数とTerraformリソース数

Proの価格は、管理ノード数とTerraformリソース数で決まる容量の段階に、追加のProユーザー・Project Runner・インスタンスの料金を足して決まります。最小構成は管理ノード50台・Terraformリソース500個で月額$20（年払いは17%引き）、以降は100台/1,000個、200台/2,000個と段階が上がります。どの段階にもProユーザー1名・Project Runner1台・インスタンス1つが含まれ、追加分は別料金です。

数え方は公式FAQに細かく書かれています。同じノードを何度実行しても1と数え、インベントリに載っているだけのホストは数えません。ただし、月の途中で50台のVMを作り直して別の50台を管理すれば100台です。オートスケールで台数が入れ替わる環境では、想定より上の段階になりやすいので注意してください。上限を超えても自動化は止まらず、利用量は現状手動で確認すると説明されています。30日間の評価版はクレジットカード不要です。

### 料金表と公式ドキュメントで食い違う機能（LDAP・Workflows・IdPグループ連携・MCP）

購入前に確かめておきたいのが、料金表とドキュメント・ソースの記載が揃っていない4項目です。

LDAPは、料金表ではPro以上の機能です。一方で公式のDocker Compose例には `SEMAPHORE_LDAP_ACTIVATED` などのLDAP設定が載ったままで、v2.19.17のOSSソースにもLDAPログインの処理が残っています。Workflows（複数テンプレートをつなぐ機能）は逆で、料金表ではCommunityにも○が付いていますが、ドキュメントの目次は「Schedules and Workflows (Pro)」です。手元で起動したv2.19.16と2.19.17のCommunityビルドでは、`/api/info` の `features.workflows` が `false` でした。

3つ目はIdPグループ連携です。料金表はEnterpriseの機能として「Custom roles and identity group mapping」を挙げていますが、[公式のTeamsガイド](https://semaphoreui.com/docs/user-guide/team)は「現在サポートしていないもの」の欄に、LDAP/OIDCのグループをカスタムロールへ割り当てる機能を挙げています。

4つ目はMCPです。料金表には「MCP server for AI-based automation workflows」という行があり、3プランすべてに○が付いています。一方、v2.19.17のソースツリーで名前に mcp を含むのはテスト用のディレクトリだけで、READMEの関連プロジェクト欄に載っているMCPサーバーは第三者製の [cloin/semaphore-mcp](https://github.com/cloin/semaphore-mcp)（AGPL-3.0）です。公式のドキュメントにも、2026年10月23日時点で設定手順は見当たりませんでした。

どの機能も、使うつもりのエディションの環境で動作を確かめ、ライセンス上その版で使ってよいかは販売元に確認してから決めてください。Enterpriseで使う予定なら、採用するバージョンと必要なマッピング方式を示して問い合わせるのが確実です。

## Semaphore UIとAWXの違いと選び方

「awx semaphore」で比較されるAWXは、Red HatのAnsible Automation Platform（AAP）の上流にあたるOSSです。違いは機能の多さより、前提となるインフラと開発の状況にあります。

| 観点                       | Semaphore UI           | AWX                     |
| ------------------------ | ---------------------- | ----------------------- |
| 導入                       | 単一バイナリかDocker          | Kubernetes＋AWX Operator |
| 最小推奨リソース（Semaphore公式ブログ） | 512MB RAM・1コア          | 8GB RAM・4コア             |
| Ansible以外のネイティブ実行        | Terraform・Bash・Python等 | Ansibleが中心              |
| SAML                     | なし                     | あり                      |
| 権限の細かさ                   | 4ロール（Enterpriseで独自ロール） | オブジェクト単位                |
| ライセンス                    | MIT                    | Apache 2.0              |
| 直近のリリース                  | v2.19.17（2026-10-20）   | 24.6.1（2024-07-02）      |

リソースの行は、Semaphore UIの公式ブログ「[Ansible AWX vs. Semaphore UI](https://semaphoreui.com/blog/awx-vs-semaphore)」（2026年4月4日）が載せている最小推奨値で、現行の[公式比較ページ](https://semaphoreui.com/vs/awx)にはこの数値はありません。どちらもSemaphore UI側の資料で、中立な第三者の計測ではありません。実際に必要な量は、同時に流すタスクの数と中身で見積もってください。それでも、Kubernetesを前提にするかどうかの差は構成図の段階で効いてきます。

### AWXのリリース停止が選定に与える影響

AWXのGitHubリポジトリのREADMEには「最後のリリースは2024年7月2日」「大規模なリファクタリングのためリリースを一時停止している」という注意書きがあります。リリース一覧の最新も24.6.1のままです。リポジトリ自体への変更は続いていますが、新規にAWXを入れると、2年以上前の版を自前で保守することになります。サポート付きでAWX系を使いたいなら、選択肢は有償のAAPです。AAPの費用と契約条件は[Ansible Automation Platformの費用と導入判断](/column/details/18090/)で、AWX側の導入手順は[Ansible AWXとは：AWX OperatorでKubernetesへ導入する手順とAAPとの違い](/tech/details/18461/)で解説しています。

### AWXから移るときの用語の対応

AWXの設定をSemaphore UIへ移すときは、次の対応で読み替えます。名前が同じでも単位が違うものがあるので、特に「Project」と「通知」に注意してください。

| AWX                   | Semaphore UI  | 違い                                                        |
| --------------------- | ------------- | --------------------------------------------------------- |
| Organization          | （相当なし）        | 最上位はプロジェクトで、権限もプロジェクト単位                                   |
| Project（SCM）          | Repository    | Semaphore UIのProjectは権限と部品をまとめる入れ物                        |
| Inventory             | Inventory     | 静的・ファイル・Terraform/OpenTofuのworkspace型がある                  |
| Credential            | Key Store     | SSH鍵・ログイン/パスワード・なしの3種                                     |
| Job Template          | Task Template | Ansible以外のアプリも選べる                                         |
| Survey                | Survey変数      | テンプレートに定義し、実行時に入力させる                                      |
| Workflow Job Template | Workflows     | ドキュメント上はPro機能                                             |
| Notification Template | サーバー設定の通知     | メール・Slack・Microsoft Teams等の送り先はサーバーの設定で決め、プロジェクトで通知を有効にする |

### Semaphore UIを選ばない方がよい条件

次のどれかに当てはまるなら、Semaphore UIは外します。社内のIdPがSAMLしか提供していない場合（Semaphore UIはOIDCとLDAPのみ）。テンプレート単位で権限を分ける監査要件があるのに、Enterpriseを契約する予算が無い場合（CommunityとProはプロジェクト単位の4ロールまでで、テンプレート単位の権限はv2.17以降のEnterpriseの機能）。Red Hatのサポート契約が調達の条件になっている場合。SAMLとRed Hatのサポートは、Enterpriseを契約しても満たせません。

逆に、AnsibleとTerraformを1チームで扱い、プロジェクト単位の権限で足り、SSOが不要なら、Semaphore UIのCommunity版から始められます。Terraformのプルリクエスト単位で plan と apply を回したいだけなら、[AtlantisでTerraformをPR運用する構成](/tech/details/16549/)の方が合う場合もあります。構成管理ツールそのものの比較は[構成管理ツールの比較と選び方](/column/details/15293/)を参照してください。

## Semaphore UIの運用で起きやすい失敗と対策

導入後に問題になりやすいのは機能不足より、既定値のまま本番に入れたことによる事故です。影響の大きい順に挙げます。

- **暗号鍵の紛失**：`SEMAPHORE_ACCESS_KEY_ENCRYPTION` を失うと、Key Storeに保存したSSH鍵やパスワードを復号できません。DBのバックアップと同じ場所に鍵を置かず、別のシークレット管理に保管します。
- **Runner無しでの実行**：Runnerを置かないと、タスクはSemaphore UIサーバー上でサーバーのファイルシステムに触れる状態で動きます。プロジェクトに参加できる人が任意のスクリプトを登録できる運用なら、Runnerを別サーバーに分けます。
- **cronのUTC**：前述のとおり既定はUTCです。夜間バッチが日中に走る事故は、設定1行で防げます。
- **サポート対象外の版で放置**：公式のセキュリティポリシーでサポートされるのは2.19.xと2.18.xで、2.18未満は対象外です。2.20系は2026年10月23日時点でまだプレリリース（v2.20.16-beta2）なので、本番は2.19系に置きます。
- **Webhookの失敗に気づかない**：Integrationは署名が合わなくても204を返します。送信側の配信履歴だけで判断せず、設定直後に1回送ってタスク一覧に載るかを確かめます。
- **SSHのホスト鍵確認で止まる**：Ansibleは既定で接続先のホスト鍵を確認するため、初めて接続するホストでは「Host key verification failed」で失敗します。確認を切る `ANSIBLE_HOST_KEY_CHECKING=False` は中間者攻撃への備えも外すので、実行するマシンの known\_hosts に接続先の鍵を登録しておく方法を先に検討します（[Ansibleの設定リファレンス](https://docs.ansible.com/ansible/latest/reference%5Fappendices/config.html#host-key-checking)）。
- **Ansibleの冪等性頼み**：画面から誰でも実行できるようになると、ガードの無い `shell` タスクが何度も実行されます。チェックモードや冪等性の考え方は[Ansibleとは？エージェントレスの仕組み](/tech/details/6533/)で解説しています。

Terraformのテンプレートを置く場合は、apply前にplanの差分を誰が確認するかも決めておきます。差分の読み方は[terraform planの差分の読み方](/tech/details/16531/)にまとめています。Semaphore UIとTerraformを含む自動化基盤の設計から相談したい場合は、[DevOps・CI/CD導入支援](/service/system/devops/)でも承っています。

## Semaphore UIについてよくある質問

### Semaphore UIは無料で使えますか？

使えます。Community版はMITライセンスのOSSで、Ansible・Terraform・OpenTofu・Terragrunt・Bash・PowerShell・Pythonの実行、cronスケジュール、REST API、Webhook、Global Runner、プロジェクト単位の権限まで費用はかかりません。2FA、LDAP/AD、OIDCでのログイン、Project Runner、HashiCorp Vault連携が必要になった時点で、月額$20からのPro版が候補になります。Proには30日間の評価版があります。

### Ansible SemaphoreとSemaphore UIは同じものですか？

同じ製品です。以前は「Ansible Semaphore」と呼ばれ、GitHubのリポジトリも ansible-semaphore/semaphore でしたが、現在は semaphoreui/semaphore に移っており、旧URLは新リポジトリへ転送されます。なお、semaphore.io の「Semaphore」はCI/CDサービスで、Semaphore UIとは関係がありません。

### Semaphore UIはWindowsで動きますか？

動きます。v2.19.17のリリースには windows\_amd64・windows\_arm64・windows\_386 のzipがあり、公式ドキュメントもLinux・macOS・Windowsを対応OSに挙げています。注意点はAnsibleで、Ansibleのコントロールノードは Windows ネイティブでは動きません。Windows上のSemaphore UIでAnsibleテンプレートを使うなら、ansible-playbook を入れたLinuxのRunnerなど、別の実行環境でタスクを動かします。公式のGetting startedも、Ansibleの手順にはLinux・macOS・WSL・コンテナ・LinuxのRunnerのいずれかが必要だと書いています。

### Semaphore UIでPowerShellスクリプトを実行するには何が必要ですか？

タスクを実行するマシンに pwsh（PowerShell 7系）が入っている必要があります。PowerShellテンプレートは .ps1 ファイルを pwsh で実行する仕組みで、公式Dockerイメージの既定タグには pwsh が入っていません。Docker版で使うなら、`v2.19.17-powershell7.5.0` のようなPowerShell入りの公式タグを選ぶか、pwshを入れたサーバーをRunnerとして登録し、そのRunnerでテンプレートを実行します。

### GitHubへのpushをきっかけにSemaphore UIのテンプレートを実行できますか？

できます。プロジェクトの Integrations でテンプレートを紐づけて受け口のURLを発行し、GitHubのWebhookの送信先に設定します。認証方式は「GitHub Webhooks」を選びます。Matchersでブランチを絞る場合は、Integrations一覧の上に表示されるプロジェクト共通URLを送信先にします。Integration個別のaliasではMatchersが評価されません。HMAC方式で試した限りでは、署名が合わないときも応答は204でした。最初の1回はタスク一覧で起動を確かめてください。

### Docker以外の方法でSemaphore UIをインストールできますか？

できます。GitHubのリリースには、Linux向けの deb と rpm、各OS向けの tar.gz と zip が用意されています。バイナリで導入する場合は、対話式の `semaphore setup` を実行すると、DB接続とCookie・暗号化の鍵を含む設定ファイルが作られます。環境変数だけで起動する場合は、管理者を `semaphore users add --admin` で作り、`SEMAPHORE_COOKIE_HASH` と `SEMAPHORE_COOKIE_ENCRYPTION` も設定してください。

## 関連記事

- [Ansibleとは？エージェントレスの仕組みとメリット・デメリット、Red Hat AAPの制約](/tech/details/6533/)
- [Ansible Automation Platformの費用と導入判断：AWX・ansible-coreとの違いと契約すべき条件](/column/details/18090/)
- [OpenTofuとは？Terraformとのライセンス・機能差と移行判断を実装視点で解説](/tech/details/15299/)
- [構成管理ツールの比較と選び方｜Ansible・Terraform・Chef・Puppet・OpenTofuの選定条件](/column/details/15293/)
- [Ansible AWXとは：AWX OperatorでKubernetesへ導入する手順とAAPとの違い【2.19.1】](/tech/details/18461/)

---

出典: [Semaphore UIとは？Ansible・TerraformのWeb UIの導入手順と料金、AWXとの違い【v2.19】](<https://www.issoh.co.jp/tech/details/12399/>)（株式会社一創）
