Для своего времени Semaphore был неплох.
Однако, Semaphore больше не поддерживается и сейчас стал бесплатным upstream Ansible Tower - AWX. Установить его можно вот так: Установка AWX на Ubuntu или в кластер Kubernetes
По сути Semaphore - бледное подобие Ansible Tower.
Установка Semaphore на Ubuntu/Debian
https://github.com/ansible-semaphore/semaphore/wiki/Installation
sudo apt-get update && sudo apt-get -y upgrade sudo apt-get install -y software-properties-common sudo apt-add-repository -y universe sudo add-apt-repository -y ppa:ansible/ansible sudo apt-get install -y git ansible mysql-server nginx wget https://github.com/ansible-semaphore/semaphore/releases/download/v2.5.1/semaphore_2.5.1_linux_amd64.deb sudo dpkg -i ./semaphore_2.5.1_linux_amd64.deb
Создаем базу данных:
sudo mysql mysql> CREATE DATABASE semaphore; Query OK, 1 row affected (0.04 sec) mysql> CREATE USER 'semaphore'@'localhost' IDENTIFIED BY 'superpassword'; Query OK, 0 rows affected (0.06 sec) mysql> GRANT ALL PRIVILEGES ON semaphore.* TO 'semaphore'@'localhost'; Query OK, 0 rows affected (0.01 sec) mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.03 sec) mysql> exit
Создаем файл конфигурации:
sudo semaphore -setup
При первичной настройке не стоит включать LDAP-аутентификацию, потому что при ее включении скрипт не предлагает добавить локального пользователя.
Включить LDAP можно и в дальнейшем, просто добавив нужные параметры в файл конфигурации.
Semaphore AD Authentication
Для аутентификации пользователей из AD нужно включить LDAP. Эта часть конфига должна выглядеть так:
"ldap_binddn": "semaphore", "ldap_bindpassword": "semaphore_password", "ldap_server": "dc.local:389", "ldap_searchdn": "OU=Users,DC=domain,DC=local", "ldap_searchfilter": "(sAMAccountName=%s)", "ldap_mappings": { "dn": "dn", "mail": "mail", "uid": "sAMAccountName", "cn": "cn" }, "ldap_enable": true, "ldap_needtls": false
С начала я пытался сконфигурировать параметр “ldap_binddn” в виде CN=semaphore,OU=Users,DC=domain,DC=local, однако это приводило к ошибкам вида:
time="2018-09-26T08:48:22Z" level=info msg="LDAP Result Code 49 "Invalid Credentials": 80090308: LdapErr: DSID-0C09042A, comment: AcceptSecurityContext error, data 52e, v3839"
в таком случае, стоит попробывать в качестве “ldap_binddn” использовать просто логин (sAMAccountname или UserPrincipalName а не distinguished name) пользователя, который будет обращаться к LDAP.
Также, вместо uid нужно использовать sAMAccountName. В противном случае можно увидеть такую ошибку:
time="2018-09-26T13:45:35Z" level=info msg="User does not exist or too many entries returned"
Запуск semaphore в виде сервиса
Копируем конфиг semaphore в /etc/ansible/:
cp ./config.json /etc/ansible/semaphore_config.json
И конфигурируем сервис: /etc/systemd/system/semaphore.service
[Unit] Description=Ansible Semaphore After=syslog.service Before=nginx.service Requires=network.target [Service] Type=forking EnvironmentFile=-/etc/default/ansible-semaphore ExecStart=/bin/sh -c "/usr/bin/semaphore -config ${SEMAPHORE_CONFIG} >> ${SEMAPHORE_LOGS} 2>&1 &" Restart=always RestartSec=10s [Install] WantedBy=multi-user.target
/etc/default/ansible-semaphore
#Ansible Semaphore Defaults SEMAPHORE_CONFIG=/etc/ansible/semaphore_config.json SEMAPHORE_LOGS=/var/log/semaphore.log
Включаем и запускаем сервис:
systemctl enable semaphore.service service semaphore start
SSL посредством nginx
/etc/nginx/nginx.conf
user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 1024; use epoll; multi_accept on; } http { tcp_nodelay on; keepalive_timeout 600; types_hash_max_size 2048; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; gzip on; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; }
/etc/nginx/sites-enabled/default
server {
listen 80;
root /var/www/;
#Enable access to acme files
location ~ /\.well-known/acme-challenge/ {
allow all;
access_log off;
log_not_found off;
}
return 301 https://$host$request_uri;
}
upstream semaphore {
server 127.0.0.1:3000;
}
server {
listen 443 ssl http2;
server_name server.domain.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/letsencrypt/live/server.domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/server.domain.com/privkey.pem;
# Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
ssl_protocols TLSv1.1 TLSv1.2;
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# disable any limits to avoid HTTP 413 for large image uploads
client_max_body_size 0;
# required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
chunked_transfer_encoding on;
location / {
proxy_pass http://semaphore/;
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://semaphore/api/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Origin "";
}
}
Discussion