Howto install Ansible SemaphoreUI on Debian 12 (2023-11-05):
This mini How-To guide describes how to install Semaphore UI 2.8.75 in addition to Ansible 8.5 on Linux Debian 12 (Bookworm). Semaphore provides a modern and responsive webUI for running Ansible playbooks as an alternative to Ansible AWX (Tower) and the new Automation Platform. Semaphore is an open-source project written in GoLang and easy to use, install & to maintain. MySQL/MariaDB, PostgreSQL and BoltDB are supported as backend DBs. Within this HowTo MariaDB is used. Please also see the official docs here.

* Build, deploy & rollback
* Group playbooks to projects
* Manage environments, inventories, repositories and access keys
* Run playbooks from the browser
* Responsive UI allows the use of Semaphore on mobile devices
* Run playbooks by schedule
* View detailed logs of any playbook runs, at any time
* Delegate other users the running of playbooks
* Get notifications about playbook runs

Prerequisites: In order to install Ansible Semaphore on a Debian based system, additional packages need to be installed. This also includes the MardiaDB server. Next to this, a dedicated semaphore user is created and the needed systemd units are being enabled. apt-get install useradd python3-pip wget git sudo nginx mariadb-server useradd -m semaphore systemctl enable mariadb systemctl start mariadb systemctl enable nginx systemctl start nginx /usr/bin/mysql_secure_installation

Semaphore Versions:
Semaphore provides ready to use packages for Debian/Ubuntu and CentOS/RedHat based Linux distributions for AMD64 and ARM64 hardware architecture. Please select the corresponding version for your hardware architecture to proceed.

# Debian/Ubuntu ARM64

# Debian/Ubuntu AMD64

# CentOS/RedHat ARM64

# CentOS/RedHat AMD64

Afterwards, the installation procedure can start. Therefore, this is done by the newly created user semaphore.
su --login semaphore
A requirements.txt file for additional PiP modules will be created in /home/semaphore/requirements.txt containing the following modules:
A requirements.yaml file for additional Ansible modules will be created in /home/semaphore/requirements.yaml containing the following modules:
  - 'community.general'
  - 'ansible.posix'
  - 'community.mysql'
  - 'community.crypto'
In order to install the modules for PiP and Ansible, the following commands are executed. Afterwards, the semaphore package can be installed.
python3 -m pip install --user --upgrade -r /home/semaphore/requirements.txt
ansible-galaxy collection install --upgrade -r /home/semaphore/requirements.yaml
ansible-galaxy role install --force -r /home/semaphore/requirements.yaml
dpkg -i semaphore*.deb
Semaphore setup can be executed and configured to your needs. The created config.json must be copied to /etc/semaphore after creation to match the systemd unit file.
semaphore setup
sudo mkdir /etc/semaphore
sudo chown semaphore:semaphore /etc/semaphore
sudo cp /home/semaphore/config.json /etc/semaphore
Now, the semaphore systemd unit file can be created in /etc/systemd/system/semaphore.service with the following content:
Description=Ansible Semaphore
ExecStart=/usr/bin/semaphore service --config /etc/semaphore/config.json
ExecReload=/bin/kill -HUP $MAINPID
The newly created service should be started
systemctl daemon-reload
systemctl enable semaphore
systemctl start semaphore
Validate that the service is up and running.
systemctl status semaphore.service 
● semaphore.service - Ansible Semaphore
     Loaded: loaded (/etc/systemd/system/semaphore.service; enabled; preset: enabled)
     Active: active (running) since Sat 2023-11-04 17:45:49 EDT; 18min ago
   Main PID: 4521 (semaphore)
      Tasks: 5 (limit: 6991)
     Memory: 38.9M
        CPU: 515ms
     CGroup: /system.slice/semaphore.service
             └─4521 /usr/bin/semaphore service --config /etc/semaphore/config.json

Nov 04 17:45:49 ansible-semaphore-srv01 systemd[1]: Started semaphore.service - Ansible Semaphore.
Nov 04 17:45:49 ansible-semaphore-srv01 semaphore[4521]: MySQL semaphore@ semaphore
Nov 04 17:45:49 ansible-semaphore-srv01 semaphore[4521]: Tmp Path (projects home) /tmp/semaphore
Nov 04 17:45:49 ansible-semaphore-srv01 semaphore[4521]: Semaphore v2.8.75
Nov 04 17:45:49 ansible-semaphore-srv01 semaphore[4521]: Interface
Nov 04 17:45:49 ansible-semaphore-srv01 semaphore[4521]: Port :3000
Nov 04 17:45:49 ansible-semaphore-srv01 semaphore[4521]: Server is running
Semaphore is now running on port tcp/3000. Keep in mind, that this in an unencrypted connection endpoint which should be secured by a reverse-proxy.

Semaphore doesn’t provide transport encryption by default. Therefore, a reverse-proxy should be used for securing the webUI and API. Attached, you can find the next steps to create a self-signed certificate and a reverse-proxy host configuration for nginx. If needed, self-signed certificates and a DH key will be generated. Other certificates can of course also be used (e.g. Let’s encrypt, etc.). cd /etc/nginx/pki openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout -out openssl dhparam -out dhparam.pem 4096

An example vhost configuration for nginx as a reverse-proxy could look like the following one, serving as
server {
  listen 443 ssl;

  # add Strict-Transport-Security to prevent man in the middle attacks
  add_header Strict-Transport-Security "max-age=31536000" always;

  # SSL
  ssl_certificate /etc/nginx/pki/;
  ssl_certificate_key /etc/nginx/pki/;

  # Recommendations from 
  ssl_dhparam /etc/nginx/dhparam.pem;
  ssl_protocols TLSv1.3;
  ssl_ecdh_curve secp384r1;
  ssl_session_timeout  10m;
  ssl_session_cache shared:SSL:10m;
  ssl_session_tickets off;
  ssl_stapling on;
  ssl_stapling_verify on;
  resolver valid=300s;
  resolver_timeout 5s;

  # required to avoid HTTP 411: see Issue #1486 
  # (
  chunked_transfer_encoding on;

  location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    proxy_buffering off;
    proxy_request_buffering off;

  location /api/ws {
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Origin "";
Semaphore provides a great API for further automation which is described in detail. The details can be found here.

Vagrant: gyptazy/debian12-semaphore-webui-ansible-server-arm64
Docker: semaphoreui/semaphore