diff --git a/docs/semaphore.md b/docs/semaphore.md new file mode 100644 index 0000000..5191579 --- /dev/null +++ b/docs/semaphore.md @@ -0,0 +1,100 @@ +# Semaphore UI + +This document describes the deployment, initial setup, and ongoing management of [Semaphore UI](https://semaphoreui.com/) 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 + +```bash +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: + +```bash +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: + +```yaml +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`