gyptazy

DevOps

Developer

IT Consultant

gyptazy

DevOps

Developer

IT Consultant

Blog Post

Install Ansible Semaphore UI on Debian 12 (Bookworm)

Install Ansible Semaphore UI on Debian 12 (Bookworm)

General

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.

Features:

  • 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
wget https://github.com/ansible-semaphore/semaphore/releases/\
download/v2.8.75/semaphore_2.8.75_linux_arm64.deb
​
# Debian/Ubuntu AMD64
wget https://github.com/ansible-semaphore/semaphore/releases/\
download/v2.8.75/semaphore_2.8.75_linux_amd64.deb
​
# CentOS/RedHat ARM64
wget https://github.com/ansible-semaphore/semaphore/releases/\
download/v2.8.75/semaphore_2.8.75_linux_arm64.rpm

# CentOS/RedHat AMD64
wget https://github.com/ansible-semaphore/semaphore/releases/\
download/v2.8.75/semaphore_2.8.75_linux_amd64.rpm

Installation

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:

ansible
netaddr
jmespath
pywinrm
passlib
requests
docker

A requirements.yaml file for additional Ansible modules will be created in /home/semaphore/requirements.yaml containing the following modules:

---
collections:
  - '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:

[Unit]
Description=Ansible Semaphore
Documentation=https://docs.ansible-semaphore.com/
Wants=network-online.target
After=network-online.target
ConditionPathExists=/usr/bin/semaphore
ConditionPathExists=/etc/semaphore/config.json
​
[Service]
User=semaphore
Group=semaphore
ExecStart=/usr/bin/semaphore service --config /etc/semaphore/config.json
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10s
Environment=LANG="en_US.UTF-8"
Environment=LC_ALL="en_US.UTF-8"
​
[Install]
WantedBy=multi-user.target

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
       Docs: https://docs.ansible-semaphore.com/
   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@127.0.0.1:3306 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.

Security

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 semaphore.example.com.crt.key -out semaphore.example.com.crt
openssl dhparam -out dhparam.pem 4096

An example vhost configuration for nginx as a reverse-proxy could look like the following one, serving as semaphore.example.com:

server {
  listen 443 ssl;
  server_name  semaphore.example.com;

  # 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/semaphore.example.com.crt;
  ssl_certificate_key /etc/nginx/pki/semaphore.example.com.key;

  # Recommendations from 
  # https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
  ssl_dhparam /etc/nginx/dhparam.pem;
  ssl_protocols TLSv1.3;
  ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
  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 8.8.8.8 8.8.4.4 valid=300s;
  resolver_timeout 5s;

  # required to avoid HTTP 411: see Issue #1486 
  # (https://github.com/docker/docker/issues/1486)
  chunked_transfer_encoding on;

  location / {
    proxy_pass http://127.0.0.1:3000;
    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_pass http://127.0.0.1:3000/api/ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Origin "";
  }
}

API

Semaphore provides a great API for further automation which is described in detail. The details can be found here.

Ready to Use Images

Of course, there are also ready to use Docker images, Vagrant boxes and Snap packages available. You can find them below:

Vagrant: https://app.vagrantup.com/gyptazy/boxes/debian12-semaphore-webui-ansible-server-arm64
(ARM64 box: 994MB) (full overview: here)

Docker: https://hub.docker.com/r/semaphoreui/semaphore

Snap: https://snapcraft.io/semaphore

Taggs: