Skip to main content

Get Started

Semaphore UI is a web interface and API for running repeatable automation with Ansible, Terraform/OpenTofu, Bash, PowerShell, and Python. It brings together automation stored in Git, credentials, variables, schedules, workflows, and execution environments, then keeps the status and log for every run.

This guide uses Ansible for the first working example. Use a playbook from your own repository, or follow the reproducible example shown in the screenshots with the public semaphoreui/semaphore-demo repository.

1. Install Semaphore​

Choose the installation method that matches where Semaphore will run. The native package is selected by default.

For Debian or Ubuntu on amd64:

wget https://github.com/semaphoreui/semaphore/releases/download/v2.19.12/semaphore_2.19.12_linux_amd64.deb
sudo apt install ./semaphore_2.19.12_linux_amd64.deb

For RHEL, Fedora, Rocky Linux, AlmaLinux, or CentOS Stream on amd64:

curl -LO https://github.com/semaphoreui/semaphore/releases/download/v2.19.12/semaphore_2.19.12_linux_amd64.rpm
sudo dnf install ./semaphore_2.19.12_linux_amd64.rpm

Configure the database and first administrator, then start Semaphore with the generated configuration:

semaphore setup --config ./config.json
semaphore server --config ./config.json

For a local evaluation, choose SQLite, accept or set the database and playbook paths, enter the public URL, and create the first administrator when prompted.

For a guided setup, use the official Semaphore Installation page to select the release, build the configuration, and get the matching download or run commands.

Not sure which installation method to choose?
Installation methodChoose it forDetailed guide
Native packageA supported Linux serverPackage manager installation
Docker ComposeA quick isolated setup or container hostDocker installation
Binary archivemacOS, Windows, FreeBSD, or Linux without a suitable packageBinary installation
Kubernetes with HelmAn existing Kubernetes clusterKubernetes installation

The detailed guides cover production databases, services, secrets, storage, ingress, and upgrades.

For this Ansible walkthrough, git --version and ansible-playbook --version must work on the Semaphore server or runner. If either command is unavailable there, install Git and Ansible before continuing.

Production installation

Before using Semaphore in production, review Configuration, Security, Runners, High availability, and Upgrading.

2. Sign in​

  1. Open Semaphore in a browser. A local installation normally uses http://localhost:3000.
  2. Enter the administrator login and password created by semaphore setup or the Docker administrator variables.
  3. Select Sign In.

Semaphore sign-in screen

Use the administrator account for the first setup because it can create projects and users. Regular users sign in on the same page after an administrator creates their account and grants project access. See User management.

3. Create a project​

After you sign in to an empty Semaphore instance, the New Project page opens automatically. If projects already exist, open the project selector and select New Project.... Complete the form:

FieldWhat to enter
Project NameA recognizable workspace name, for example Production infrastructure or your application name.
Max number of parallel tasksOptional. Limits simultaneous tasks in this project; leave it empty to use the server limit.
Telegram Chat IDOptional. Used when Telegram notifications are configured for the project.
Allow alerts for this projectOptional. Enables configured project notifications.
Select Create.

Do not select Create Demo Project: it adds sample resources, while this guide builds a clean project. When you create another project later, the same option appears as a Demo switch in the New Project dialog.

Empty New Project form with all available fields

The new project opens with sections for Task Templates, Workflows, Schedule, Inventory, Variable Groups, Key Store, and Repositories. See Projects for project settings, team access, activity, and history.

Watch this step

Creating the first project on an empty Semaphore instance

4. Understand the core concepts​

The new project opens on an empty Dashboard. The sidebar is the main navigation for this project:

Clean Semaphore project interface before resources and tasks are added

  • Dashboard shows run history, statistics, activity, and project settings.
  • Task Templates, Workflows, and Schedule define what runs and when.
  • Repositories, Inventory, Variable Groups, and Key Store provide code, targets, variables, and credentials.
  • Integrations, Team, and Runners connect external systems, users, and execution hosts.

The diagram shows how these resources produce a run:

How Semaphore resources and triggers become a task run

A UI action, API request, or schedule can start a Task Template directly or start a Workflow that uses task templates. Semaphore creates a task run—shown as a Task in the UI—and sends it to the Semaphore server or an eligible remote runner. For Ansible, that execution host runs ansible-playbook; the Inventory lists the systems Ansible manages.

ConceptWhat it does
ProjectAn isolated workspace containing automation resources, permissions, and run history.
RepositoryPoints to the Git branch or tag containing the automation files used by a task.
Key StoreStores reusable SSH keys, login credentials, tokens, and Ansible Vault passwords outside Git and task input.
InventoryTells Ansible which hosts and groups to manage and which credentials to use.
Variable GroupStores reusable Ansible variables, environment variables, and secrets for one or more templates.
Task TemplateSaves what to run: automation type, file, repository, inventory, variables, prompts, and execution options.
Task (task run)One execution, with its own inputs, status, timestamps, log, details, and result.
WorkflowConnects task templates into a multi-step path with success, failure, approval, and note branches.
ScheduleStarts a task template or workflow once or repeatedly from a cron expression.
RunnerRuns queued tasks outside the main Semaphore server, for example in another network or security boundary.

5. Connect the repository​

A Repository connects Semaphore to automation stored in Git; Semaphore does not store the playbook itself. Connect your own repository, or use the public demo values below to follow the example exactly. Integrations are a separate feature for starting automation from GitHub, GitLab, or another webhook source.

  1. Open Repositories and select New Repository.

  2. Enter your repository name, URL, branch, and credential. If you are following the public demo, use:

    FieldValue
    NameDemo
    URL or pathhttps://github.com/semaphoreui/semaphore-demo.git
    Branch / Tagmain
    Access KeyNone because this repository is public
  3. Select Create.

Repository form filled with the public Semaphore demo repository

Your repository should now appear in the list. Semaphore clones or updates it on the execution host when a task starts, not when you create the Repository record. The screenshot shows the demo values used in this guide.

Connected Demo repository in the project repository list

For a private repository, select a suitable Key Store credential instead of None. See Repositories for local paths, HTTPS, SSH, branches, credentials, and requirements files.

6. Add an SSH key for a remote managed host​

This SSH credential lets Ansible connect from the Semaphore server or runner to a remote host in the Inventory. If you are following the localhost demo, no SSH key is needed; continue to step 7.

The demo uses localhost with ansible_connection=local, so it does not open an SSH connection. When your own playbook manages a remote host, add its key:

  1. Add the public half of the key to ~/.ssh/authorized_keys on the managed host.
  2. Open Key Store and select New Key.
  3. Enter a recognizable name, for example Production hosts, keep Local selected, and choose SSH Key.
  4. Enter the account Ansible should use on the host, for example ubuntu or ec2-user.
  5. Paste the complete private key, including its BEGIN and END lines, and add the passphrase when required.
  6. Select Create. In the next step, choose this key under Inventory → User Credentials.

New SSH Key form for the account used on managed hosts

The screenshot contains a placeholder, not a working secret. Never publish a private key in documentation, screenshots, task arguments, or source control.

Semaphore can store secrets locally or use external secret-storage integrations such as HashiCorp Vault and Devolutions Server. See Key Store for all supported credential types and storage options.

7. Create the Ansible inventory​

Every Ansible task needs an inventory. For a first local run, add a file such as inventory.ini to your repository:

[local]
localhost ansible_connection=local

Here, localhost means the execution host—the Semaphore server, container, or runner—not necessarily the computer where your browser is open. ansible_connection=local tells Ansible not to use SSH. The demo repository uses the equivalent file invs/prod/hosts with a group named site.

If you created inventory.ini in your own repository, commit and push it to the branch connected to Semaphore before continuing.

  1. Open Inventory and select New Inventory → Ansible Inventory.

  2. Enter values that match your inventory. For example:

    FieldValue
    NameLocal (Prod in the demo)
    User CredentialsNone for localhost; use your host SSH credential for a remote inventory
    TypeFile
    Path to Inventory fileinventory.ini (invs/prod/hosts in the demo)
  3. Leave Runner tag, Sudo Credentials, and Repository empty, then select Create.

Ansible file inventory configured with the demo repository values

Leaving Repository empty means Semaphore resolves this relative inventory path from the Repository selected in the Task Template. Select a Repository here only when the inventory lives elsewhere. For a remote host, use the SSH key from step 6 as User Credentials.

See Inventory for static, file-based, and dynamic inventories.

8. Add a Variable Group (optional)​

A Variable Group is a reusable set of values that you can attach to one or more Task Templates. Use Extra variables for Ansible variables, Environment variables for values exported to the process, and Secrets for sensitive values that should be encrypted and masked. This keeps environment-specific configuration out of the playbook and avoids entering the same values in every template.

The first task works without a Variable Group. As an example, create one that sets ansible_python_interpreter=auto_silent; Ansible will still discover Python automatically but will not print its informational discovery warning.

  1. Open Variable Groups and select New Group.

  2. Set Group Name to a descriptive name, for example Ansible defaults.

  3. Under Variables → Extra variables, keep Table selected and select +.

  4. Enter:

    NameTypeValue
    ansible_python_interpreterStringauto_silent
  5. Select Save.

Variable Group configured in the table editor

See Variable Groups for precedence rules and secret-storage options.

9. Create the Ansible task template​

Review the playbook in Git​

If the repository you connected already contains an Ansible playbook, use it. Otherwise, add a small example such as get-started.yml:

- name: Verify Semaphore setup
hosts: all
gather_facts: false
tasks:
- name: Check the Ansible connection
ansible.builtin.ping:

If you are following the demo, use its ping.yml instead. It targets the demo inventory's site group and runs the included ping role.

The demo downloads that role from a Git submodule and sends one ICMP request to semaphoreui.com, so the execution host needs GitHub access and outbound ICMP. If ICMP is blocked, use the local get-started.yml example instead.

ping.yml in the connected GitHub repository

The screenshot shows the playbook in the public demo repository. Keeping automation in Git makes changes reviewable and lets Semaphore record the exact commit used for each run.

If you created get-started.yml in your own repository, commit and push it to the branch connected to Semaphore before continuing.

Configure the template​

  1. Open Task Templates and select New template → Applications.

  2. Enable Ansible Playbook, then return to Task Templates.

  3. Select New template → Ansible Playbook.

  4. Keep the Task tab selected. Build and Deploy are versioned CI/CD template types and are not needed for this independent run.

  5. Configure the template with values that match your files. For example:

    FieldValueWhy it matters
    NameRun first playbookIdentifies the reusable template and its task history.
    RepositoryYour repository (Demo in the example)Supplies the playbook and related files.
    Path to playbook fileget-started.yml (ping.yml in the demo)Resolves from the repository root.
    InventoryLocal (Prod in the demo)Supplies the local target for this first run.
    Variable GroupsAnsible defaults, if createdAdds the optional reusable Ansible setting.
    Runner tagLeave emptyUses local execution or the default runner, depending on server configuration.
  6. Under Ansible options, enable Skip Galaxy install for the small playbook above or the public demo: neither needs Galaxy dependencies for this task. Leave it off when your own repository requires roles or collections from a requirements.yml file.

  7. Select Create.

Ansible task template with its repository, inventory, and Variable Group

Watch this step

Enabling Ansible and creating the first Ansible task template

Other useful fields include:

  • Vaults selects Key Store passwords for encrypted Ansible content.
  • Limit, Tags, and Skip tags narrow what the playbook runs.
  • Prompts allow a UI user, schedule, or API request to override enabled values for a specific run.
  • Runner tag controls where the task executes; it does not select an Ansible target.

See Ansible templates and Task Templates for all fields and execution options.

10. Run the template and inspect the task​

  1. Open the Task Template you created and select Run.
  2. Add an optional message such as First Semaphore run.
  3. Leave Dry Run and Diff off, then select Run.

Clean New Task dialog for the Ansible playbook

Semaphore queues the task, prepares the repository, applies the inventory and optional Variable Group, and runs the selected playbook. The status moves through Waiting and Running before finishing as Success or Failed.

Log​

Log is the source of truth for command output. Read the final PLAY RECAP, not only the green status badge.

Successful Ansible task log with ping output and PLAY RECAP

The exact counters depend on your playbook. A successful first run should end with unreachable=0 and failed=0 for localhost. If the demo log shows changed=1, it means its shell-based ping step ran and reported a change; it is not an error.

Details and Summary​

TabWhat to check
LogLive execution phases, module output, errors, and the final PLAY RECAP.
DetailsTemplate type, Git commit, run message, author, timestamps, and duration.
SummaryHost-level Ansible results and errors after completion, when the task-summary feature is available.

Task Details with template, commit, and timing information

Task Summary with OK and Not OK host counts

If Summary is unavailable, verify the run in Log; PLAY RECAP remains the authoritative Ansible result.

Watch the run and result

Running the Ansible task and inspecting its log and details

Find previous runs​

Close the task window to return to the template's Tasks tab. Every run has its own task number, status, user, start time, duration, and preserved log. Dashboard → History shows runs from every template in the project. See Tasks and Project history for more detail.

Ansible template history with successful task runs

If the task fails, use the last meaningful Log line to choose the next check:

  • A clone error points to the repository URL, branch, Access Key, or network access from the execution host.
  • ansible-playbook: command not found means Ansible is missing from the Semaphore server or selected runner.
  • UNREACHABLE points to inventory addressing, host credentials, SSH reachability, or host-key verification.
  • A failed Ansible step normally includes its task name, host, and module error immediately above PLAY RECAP.

11. Run the task on a schedule​

After the task succeeds from the UI, you can run it automatically. For example, the cron expression 0 3 * * * starts it every day at 03:00 in the timezone shown by Semaphore.

  1. Open Schedule and select New Schedule → Cron.
  2. Enter a descriptive name, for example Nightly playbook.
  3. Select the Task Template you want to run.
  4. Keep Show cron format enabled and enter a cron expression, for example 0 3 * * *.
  5. Keep Enabled selected and choose Save.

Cron schedule configured to run the example task every day at 03:00

Semaphore shows the configured timezone and calculates the next run before you save. A scheduled run uses the same repository, inventory, Variable Groups, and execution settings as the template. If the template exposes prompts, the schedule can provide values for them. See Schedules for cron syntax, timezone configuration, one-time runs, and scheduled parameters.

After saving, verify that the schedule is Enabled and that Next run shows the expected time. Scheduled tasks appear in the template's Tasks tab and in Dashboard → History.

What to try next​

Once the first Ansible task succeeds:

  • Add the appropriate private credential in Key Store when your Repository requires authentication.
  • Build a Workflow when several templates need ordered success, failure, approval, or note paths.
  • Use Integrations for authenticated webhook triggers from GitHub, GitLab, or another system.
  • Use the API to manage resources and start templates programmatically.
  • Add a remote runner when execution must happen in another network, operating system, or security boundary.

For production, put Semaphore behind HTTPS, back up the database and access-key encryption secret together, configure centralized authentication, and review Security, Logs, and Upgrading.