Files
homelab/docs/semaphore.md
Hermes Agent service account 6e50461999 docs: add comprehensive Semaphore deployment and setup guide
- Covers deployment, initial setup, DNS/Traefik, GitOps approach, and troubleshooting
2026-05-27 21:57:02 -05:00

3.3 KiB

Semaphore UI

This document describes the deployment, initial setup, and ongoing management of Semaphore UI in mk-labs.

Overview

Semaphore is deployed as a rootless Podman container on figment using a systemd quadlet managed by Ansible. It uses BoltDB for its database and is exposed via Traefik with Cloudflare TLS.

Deployment

The deployment is handled by the semaphore Ansible role:

  • Role location: ansible/roles/semaphore/
  • Playbook: playbooks/deploy_semaphore.yml
  • Container: Managed via quadlet at /etc/systemd/system/container-semaphore.service
  • Image: semaphoreui/semaphore:latest

Key features of the role:

  • Creates dedicated cast user/group
  • Manages data and config directories
  • Generates systemd quadlet with proper rootless volume flags (:Z,U)
  • Creates config.json for non-interactive BoltDB startup
  • Idempotently creates the initial admin user (when semaphore_admin_password is defined in vault)

Initial Setup

1. Deploy the container

ansible-playbook -i inventory.yml playbooks/deploy_semaphore.yml --limit figment

2. Create the initial admin user

The role will attempt to create the admin user defined in the defaults/vault. If this fails or you need to do it manually:

sudo podman exec semaphore semaphore user add --admin \
  --login admin \
  --name "Administrator" \
  --email admin@local.mk-labs.cloud \
  --password 'YourStrongPassword'

3. Access the UI

  • https://semaphore.local.mk-labs.cloud
  • https://imagineering.local.mk-labs.cloud

DNS / Traefik

Traefik dynamic configuration is located at:

  • boilerplates/traefik/dynamic/semaphore.yml

This file defines two hostnames:

  • semaphore.local.mk-labs.cloud
  • imagineering.local.mk-labs.cloud

Both point to figment:3000 and use the cloudflare certificate resolver.

DNS records are managed via playbooks/add_service_route.yml, which now supports multiple hostnames per service config file.

GitOps Approach

The goal is to manage as much of Semaphore as possible through Git and Ansible:

  • Projects, repositories, inventories, and task templates should be defined and synced via the Semaphore API using Ansible.
  • The initial admin user creation is handled idempotently by the role.
  • Future enhancements will include a dedicated playbook/role for syncing Semaphore configuration from the repository.

Variables

Required Vault Variables

Add the following to your vault:

vault_semaphore_admin_password: "your-strong-password"

Role Defaults

See ansible/roles/semaphore/defaults/main.yml for all configurable values (admin user details, container settings, paths, etc.).

Authentik Integration (Planned)

OIDC integration with Authentik is planned. Once enabled, local authentication can be disabled or restricted to an emergency admin account.

Troubleshooting

  • Container fails to start: Check journalctl -u container-semaphore.service
  • Permission issues with BoltDB: Ensure the :U volume flag is present in the quadlet and directories are owned by the cast user.
  • No admin user: Re-run the role or create the user manually via podman exec.

References

  • Semaphore documentation: https://docs.semaphoreui.com/
  • Role source: ansible/roles/semaphore/
  • Traefik config: boilerplates/traefik/dynamic/semaphore.yml