Self-hosted service
semaphoreui/semaphore avatar
semaphoreui/semaphore

Semaphore UI puts your Ansible runs, cron schedules and secrets in one database

Modern UI and powerful API for Ansible, Terraform/OpenTofu/Terragrunt, PowerShell and other DevOps tools.

14,411 stars1,351 forksGoMIT

At a glance

What is it?
Semaphore UI is a Go web interface for Ansible, Terraform, OpenTofu, Terragrunt and PowerShell runs, MIT licensed and shipping as a single binary or container. Two details decide whether it fits you: Variable Groups store your task secrets in Semaphore itself, and the default docker run in the README leaves the admin password as changeme.
Who is it for?
Semaphore UI fits a team whose terminal-first deployment has stopped scaling, provided someone on the team owns the Semaphore database as a secret store and rotates the credentials the container creates.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • semaphoreui/semaphore14,411 ★ · +234
Star history
Repository2026-09-222026-11-14
semaphoreui/semaphore14.2k14.4k

234 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The README's docker run leaves the admin password as changeme

Docker is described as the most popular install path, and the command given is short enough to paste without reading:

bash
docker run -p 3000:3000 --name semaphore \
	-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 \
	-d semaphoreui/semaphore:latest

Four of those environment variables create the first administrator, and one of them is the literal word changeme. The image tag is also :latest rather than a pinned version, so two installs run months apart can be on different builds.

Nothing here is wrong as a demonstration, and everything here matters operationally: a container published on port 3000 with a known default password is the configuration to fix before it faces a network. The README points at a Container Configurator as the recommended way to get a proper Docker configuration, which is the more careful route.

SEMAPHORE_DB_DIALECT decides where your task history lives

The example sets SEMAPHORE_DB_DIALECT=sqlite, and the dependency list shows that this is a choice rather than a constraint. MySQL, Postgres and SQLite drivers all sit in go.mod, along with the squirrel query builder, so one binary serves all three.

The SQLite driver is modernc.org/sqlite, a pure Go implementation, which is what lets a single static binary serve a database without a C toolchain.

The consequence is that the dialect is a data durability decision, not a checkbox. Task history, project configuration and Variable Group contents all land in whichever database you name, so an instance started on sqlite for a trial has to be migrated before it carries a team's real inventory. config.schema.yaml at the repository root is where the rest of the settings are described.

Variable Groups turn Semaphore into part of your secret store

Of the six key concepts, the one with consequences is the Variable Group, described as a configuration context holding sensitive information such as environment variables and secrets used by tasks during execution.

That moves credentials out of your repository and into the Semaphore database. Which is a reasonable trade for a team that wants one place to manage deployment values, and a new obligation for whoever runs Semaphore: a backup of that database is now a backup of your secrets.

The remaining concepts define the shape of a run. A Project collects related resources and tasks. A Task Template is a reusable definition that runs on demand or on a schedule, and a Task is one execution of it. Inventory is the target hosts, servers, virtual machines or containers, and Schedules automate execution at times or intervals.

LDAP, NTLM, OIDC and TOTP are dependencies, not plugins

Semaphore ships its own identity machinery. The dependency list includes go-ldap for LDAP (with Azure go-ntlmssp listed as an indirect dependency), coreos go-oidc for OpenID Connect, gorilla securecookie for session cookies, and pquerna otp with qrterminal for time-based one-time passwords, which together point to QR-code enrolment for one-time passwords.

Two example directories sit alongside them: examples/authentik_ldap/ and examples/openldap/.

The reason this matters for a decision is access control. The feature list claims Semaphore lets you control access to your deployment system, and that claim rests on these packages rather than on an external gateway. For an organisation with an existing directory, nothing has to be built.

The pro module is replaced into the main build with one go.mod line

go.mod contains a replace directive pointing the pro module path at a local directory:

go
replace github.com/semaphoreui/semaphore/pro => ./pro

The tree contains pro/ and pro_interfaces/ directories, so that code compiles from this repository rather than being fetched from a module proxy. Whatever edition differences exist between the community build and the pro build, the source is here and the build is local.

That has a practical consequence for anyone doing a licence review. The project is MIT, credited to Denis Gukov, with the full text in LICENSE. An in-tree pro directory next to an MIT notice is exactly the situation where you check what pro/ contains rather than assuming the top-level licence settles it.

Two minor versions shipped on the same afternoon

The release list shows v2.19.18 and v2.20.17-rc1 published on 2026-11-02, and v2.20.16-beta9 on 2026-10-28 before them. A stable 2.19 line and 2.20 pre-releases are moving on the same day.

For an operator that is good news with a caveat. You can stay on 2.19 patch releases while 2.20 is still in beta and release-candidate builds. The caveat is that you now track two lines and have to notice which one your instance is on.

The default branch is develop, not master, and the last push was on 2026-11-02. Building from source and running a released container are two different code paths, and the CONTRIBUTING guide is written against the develop branch.

Four ways to drive Semaphore that do not involve the browser

The interface is the headline, and the interesting part is how much of Semaphore can be used without it. There is an API reference built from api-docs.yml at the repository root, a published Postman collection, a Terraform provider called terraform-provider-semaphoreui, and a PowerShell module called PSSemaphore that works against the Ansible Semaphore REST API.

There is also an MCP server listed among the community projects, which is how an assistant-driven workflow would reach the same endpoints.

The consequence is a choice about where the truth lives. A team that manages everything through the Terraform provider and the REST API keeps its inventory in version control and uses Semaphore as an execution and audit layer. A team that clicks through the UI keeps the inventory in the database. Both are supported, and the repository holds a cli/ directory built on cobra, so the first decision is yours rather than the project's.

websocket, Prometheus and robfig/cron are what make it a service

Reading go.mod tells you what the running process actually does. gorilla websocket is how live task output reaches the browser instead of being polled. prometheus client_golang is how metrics leave the process. robfig cron is what runs Schedules. creack pty exists because a shell task needs a pseudo-terminal to behave like one, and logrus with lumberjack is logging with rotation.

There is also thedevsaddam gojsonq, a JSON query library, and go-git, a Go implementation of git.

Taken together, those packages describe the operational profile: a long-running service that starts tasks on a cron schedule, streams their output, exposes metrics for alerting, and keeps logs on disk. Failure notifications are part of the feature list for the same reason. What the README does not document is the metrics endpoint path or which metrics are exported, so wiring Prometheus needs a look at the running instance.

Editorial conclusion

Semaphore UI fits a team whose terminal-first deployment has stopped scaling, provided someone on the team owns the Semaphore database as a secret store and rotates the credentials the container creates. Verify three things before exposing it: change SEMAPHORE_ADMIN_PASSWORD away from changeme, decide whether SEMAPHORE_DB_DIALECT=sqlite is acceptable for your task history or whether you need Postgres, and check the pro/ directory, since the go.mod replaces the pro module with a local directory and the MIT notice sits alongside it. Releases v2.19.18 and v2.20.17-rc1 both landed on 2026-11-02, the same day as the last push to develop.

Frequently asked questions

How do I install Semaphore UI?

The README lists Docker as the most popular method and recommends a Container Configurator for a proper configuration. It also lists marketplace VMs from AWS, Cloudzy, DigitalOcean, Vultr, Yandex Cloud and RepoCloud, plus Snap, a binary file, and Debian or RPM packages.

How do I install Semaphore UI on Ubuntu?

The Debian or RPM package is the route for Ubuntu-class systems, linked from the README's install list alongside the binary download. Docker is also offered and is the one the project calls most popular.

How do I use Semaphore UI with Ansible?

Ansible playbooks are one of the named task types, alongside Terraform and OpenTofu code and Bash and PowerShell scripts. A Task Template holds the reusable playbook definition, Inventory holds the target hosts, and a Variable Group supplies secrets and environment variables at execution time.

How do I set up Semaphore?

The container run in the README creates the first administrator through SEMAPHORE_ADMIN, SEMAPHORE_ADMIN_PASSWORD, SEMAPHORE_ADMIN_NAME and SEMAPHORE_ADMIN_EMAIL, and SEMAPHORE_DB_DIALECT picks the database. A Dev Container is offered for contributors with the default user admin and the password changeme.

Does Semaphore UI have an API I can use instead of the web interface?

Yes. The project publishes an API reference generated from api-docs.yml plus a Postman collection, and the community maintains a Terraform provider and a PowerShell module called PSSemaphore that works against the REST API.

How do I install Ansible with Semaphore?

The README does not say how Ansible itself gets installed; Ansible playbooks are one of the task types Semaphore runs, against a Task Template and an Inventory. The README documents the Semaphore install methods and leaves the playbook side to your own repositories.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. semaphoreui/semaphore on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/semaphoreui-semaphore.svg)](https://hysenlabs.com/projects/semaphoreui-semaphore)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/semaphoreui-semaphore.svg)](https://hysenlabs.com/projects/semaphoreui-semaphore)

Was this useful?