Skip to content

Commit

Permalink
changes form forked role:
Browse files Browse the repository at this point in the history
renamed var:

  semaphore_port -> semaphore_listenport

introduced vars:

  semaphore_listenip
  semaphore_default_user_make_admin: true|false

added vars for nginx reverse config (new vars) including dist-specfic vars:

  semaphore_nginx_deploy_reverseconfig
  semaphore_nginx_template
  semaphore_nginx_remove_default_config
  semaphore_nginx_config_filename
  semaphore_nginx_use_nginx_common_snippet
  semaphore_nginx_snippet_directory
  semaphore_nginx_tls_hardening_snippet

  semaphore_tls_hsts_enable: true|false
  semaphore_tls_hsts_time: integer
  semaphore_nginx_ssl_certificate
  semaphore_nginx_ssl_certificate_key

  semaphore_nginx_default_config
  semaphore_nginx_config_src_dir
  semaphore_nginx_config_dst_dir

improved query if default user already exists (query specifically the semaphore_default_user not if any user exists)

option to make default user admin (var: semaphore_default_user_make_admin)

changed default config to builtin-default of semaphore (you can omit --config on commands this way):
  semaphore_config_path: "/etc/semaphore/semaphore.json" -> "/etc/semaphore/config.json"
  • Loading branch information
Stefan Schwarz committed Apr 28, 2023
1 parent 201d743 commit f1720b0
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 12 deletions.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Ansible role to install and configure the [Ansible UI Semaphore](https://github.

## Requirements

None. But for a production environment you should install a webserver as proxy for ssl termination.
None. But for a production environment you should install a webserver as proxy for ssl termination (role is prepared for nginx).

## Example playbook

Expand All @@ -31,22 +31,30 @@ None of the variables below are required.

| Variable | Default | Comment |
| :--- | :--- | :--- |
| `semaphore_version` | `v2.8.77` | the version to download, also see `semaphore_download_url` and `semaphore_download_checksum` |
| `semaphore_version` | latest available version | the version to download (example: 2.8.77), also see `semaphore_download_url` and `semaphore_download_checksum` |
| `semaphore_mysql_install` | `true` | whether to install mysql on the host, installs with the password `mysql_root_password` |
| `semaphore_mysql_create_db` | `true` | whether to create the mysql db and user |
| `semaphore_mysql_host`:`semaphore_mysql_port` | `127.0.0.1`:`3306` | the mysql host |
| `semaphore_mysql_db` | semaphore | the mysql database |
| `semaphore_mysql_user` | semaphore | the mysql user |
| `semaphore_mysql_password` | semaphore | the mysql user password |
| `semaphore_user` | semaphore | the user and systemd identifier semaphore runs as |
| `semaphore_port` | `3000` | the port semaphore binds to |
| `semaphore_listenip` | `127.0.0.1` | the IP semaphore binds to |
| `semaphore_listenport` | `3000` | the port semaphore binds to |
| `semaphore_path` | /opt/semaphore | destination for the binary |
| `semaphore_addn_config` | `{}` | for all options see the [source](https://github.com/ansible-semaphore/semaphore/blob/master/util/config.go#L36-L72) |
| `semaphore_config_path` | /etc/semaphore/semaphore.json | config file |
| `semaphore_default_user` | admin | login name of the default user |
| `semaphore_default_user_make_admin` | true | make default user admin |
| `semaphore_default_user_name` | `semaphore_default_user` | his human readable name |
| `semaphore_default_user_password` | admin | the password |
| `semaphore_default_user_mail` | admin@example.com | and mail adress |
| `semaphore_default_user_password` | `admin` | change to a secure value! |
| :--- | :--- | :--- |
| `semaphore_nginx_deploy_reverseconfig` | false | set to true to enable nginx |
| `semaphore_nginx_config_filename` | `semaphore` | filename of nginx vhost-config |
| `semaphore_nginx_ssl_certificate` | `/etc/letsencrypt/live/{{ semaphore_hostname }}/fullchain.pem` | path to tls certificate |
| `semaphore_nginx_ssl_certificate_key` | `/etc/letsencrypt/live/{{ semaphore_hostname }}/privkey.pem` | path to tls key |

For all options see [defaults/main.yml](defaults/main.yml)

Expand All @@ -61,3 +69,5 @@ Molecule is used for testing, the webinterface of the centos machine will be exp
## License

MIT

Role forked from https://github.com/morbidick/ansible-role-semaphore
36 changes: 31 additions & 5 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,25 @@ semaphore_mysql_allowed_host: "localhost"

# the default user that should be created
semaphore_default_user: "admin"
# create default user with admin priviledges
# (otherwise you need to execute "/opt/semaphore/semaphore "):
semaphore_default_user_make_admin: true
semaphore_default_user_name: "{{ semaphore_default_user }}"
semaphore_default_user_password: "admin"
semaphore_default_user_mail: "admin@example.com"

# sempahore binary source
semaphore_version: "2.8.77"
# if not set anywhere, defaults to latest version:
# semaphore_version: "2.8.77"

semaphore_download_url: "https://github.com/ansible-semaphore/semaphore/releases/download/v{{ semaphore_version }}/semaphore_{{ semaphore_version }}_linux_amd64.tar.gz"
semaphore_download_checksum: "sha256:a67a6ef4a49bf7613e87628bf35db7d239050a99d7123a278c6cc85b2bff7997"
# if not set dynamically determined:
# semaphore_download_checksum: "sha256:a67a6ef4a49bf7613e87628bf35db7d239050a99d7123a278c6cc85b2bff7997"

# binary paths and service identifiers
semaphore_user: "semaphore"
semaphore_path: "/opt/semaphore"
semaphore_config_path: "/etc/semaphore/semaphore.json"
semaphore_config_path: "/etc/semaphore/config.json"
semaphore_tmp_path: "{{ semaphore_path }}/tmp"
semaphore_executable: "{{ semaphore_path }}/semaphore"
semaphore_command: "{{ semaphore_executable }} --config {{ semaphore_config_path | quote }}"
Expand All @@ -37,7 +43,8 @@ semaphore_identifier: "{{ semaphore_user }}"
semaphore_systemd_unit_path: "/etc/systemd/system/{{ semaphore_identifier }}.service"

# semaphore config options
semaphore_port: 3000
semaphore_listenip: "127.0.0.1"
semaphore_listenport: 3000
semaphore_addn_config: {}

# mysql command lines to create default user
Expand All @@ -60,5 +67,24 @@ semaphore_config_object:
user: "{{ semaphore_mysql_user }}"
pass: "{{ semaphore_mysql_password }}"
name: "{{ semaphore_mysql_db }}"
port: ":{{ semaphore_port }}"
port: ":{{ semaphore_listenport }}"
tmp_path: "{{ semaphore_tmp_path }}"

# use nginx to make a ssl reverse-proxy-config:
semaphore_nginx_deploy_reverseconfig: true
semaphore_nginx_template: "nginx-semaphore.j2"
semaphore_nginx_remove_default_config: false
semaphore_nginx_config_filename: semaphore

# if you use https://github.com/selfhostx/ansible/tree/main/roles/nginx_common than set to "true" here:
semaphore_nginx_use_nginx_common_snippet: false
semaphore_nginx_snippet_directory: "{{ nginx_snippet_directory | default('/etc/nginx/snippets') }}"
semaphore_nginx_tls_hardening_snippet: "{{ semaphore_nginx_snippet_directory }}/tls-hardening.conf"

# enable HSTS (not used when semaphore_nginx_use_nginx_common_snippet: true):
semaphore_tls_hsts_enable: true
semaphore_tls_hsts_time: 31536000

# path to ssl certificates, defaults to letsencrypt paths:
semaphore_nginx_ssl_certificate: "/etc/letsencrypt/live/{{ semaphore_hostname }}/fullchain.pem"
semaphore_nginx_ssl_certificate_key: "/etc/letsencrypt/live/{{ semaphore_hostname }}/privkey.pem"
5 changes: 5 additions & 0 deletions handlers/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@
name: "{{ semaphore_identifier }}"
daemon_reload: true
state: restarted

- name: Restart nginx
ansible.builtin.service:
name: nginx
state: restarted
41 changes: 37 additions & 4 deletions tasks/main.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
---
- name: Include OS-specific variables
ansible.builtin.include_vars: "vars-{{ ansible_os_family }}.yml"
tags:
- always

- name: Ensure MySQL Server
ansible.builtin.import_tasks: setup-mysql.yml
when: semaphore_mysql_install or semaphore_mysql_create_db

- name: Nginx Config
ansible.builtin.import_tasks: nginx.yml
when: semaphore_nginx_deploy_reverseconfig

- name: Install dependencies
ansible.builtin.package:
name: "{{ item }}"
Expand All @@ -22,6 +31,27 @@
name: "{{ semaphore_user }}"
createhome: false

- name: Get Semaphore Release Info
ansible.builtin.uri:
url: 'https://api.github.com/repos/ansible-semaphore/semaphore/releases/latest'
return_content: true
register: 'semaphore_version_github'

- name: Determine current Semaphore version
ansible.builtin.set_fact:
semaphore_version: "{{ semaphore_version_github['json']['tag_name'][1:] }}"

# FIXME implement lookup of checksum from semaphore_checksums_github.content
#- name: Get checksum file of current Semaphore version
# ansible.builtin.uri:
# url: "https://github.com/ansible-semaphore/semaphore/releases/download/v{{ semaphore_version }}/semaphore_{{ semaphore_version }}_checksums.txt"
# return_content: true
# register: 'semaphore_checksums_github'

#- name: Set checksum from file
# ansible.builtin.set_fact:
# semaphore_download_checksum: "{{ semaphore_checksums_github['json']['tag_name'][2:] }}"

- name: Create application directories
ansible.builtin.file:
path: "{{ item }}"
Expand Down Expand Up @@ -94,15 +124,18 @@
notify:
- Semaphore restart

- name: Check users
ansible.builtin.command: "{{ semaphore_command }} user list"
- name: Check if default user already exists (fails if not)
ansible.builtin.command: "{{ semaphore_command }} user get --login {{ semaphore_default_user | quote }}"
register: semaphore_users
ignore_errors: true
changed_when: false

- name: Create default user
ansible.builtin.command: "{{ semaphore_command }} user add --name {{ semaphore_default_user_name | quote }} --login {{ semaphore_default_user | quote }} --email {{ semaphore_default_user_mail | quote }} --password {{ semaphore_default_user_password | quote }}"
when: semaphore_users.stdout == ""
ansible.builtin.command: "{{ semaphore_command }} user add {% if semaphore_default_user_make_admin %}--admin{% endif %} --name {{ semaphore_default_user_name | quote }} --login {{ semaphore_default_user | quote }} --email {{ semaphore_default_user_mail | quote }} --password {{ semaphore_default_user_password | quote }}"
# when: semaphore_users.stdout == ""
when: semaphore_users.rc != 0
changed_when: true
no_log: true

- name: Deploy systemd service file
ansible.builtin.template:
Expand Down
21 changes: 21 additions & 0 deletions tasks/nginx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
- name: Remove default config (when enabled)
ansible.builtin.file:
path: "{{ semaphore_nginx_default_config }}"
state: absent
notify: Restart nginx
when: semaphore_nginx_remove_default_config

- name: Ensure nginx config is present
ansible.builtin.template:
dest: "{{ semaphore_nginx_config_src_dir }}/{{ semaphore_nginx_config_filename }}"
mode: "0644"
src: "{{ semaphore_nginx_template }}"
notify: Restart nginx

- name: Enable nginx config via symbolic link
ansible.builtin.file:
src: "{{ semaphore_nginx_config_src_dir }}/{{ semaphore_nginx_config_filename }}"
dest: "{{ semaphore_nginx_config_dst_dir }}/{{ semaphore_nginx_config_filename }}"
state: link
notify: Restart nginx
57 changes: 57 additions & 0 deletions templates/nginx-semaphore.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
server {
listen 80 {% if semaphore_nginx_remove_default_config %}default_server{% endif %};
listen [::]:80 {% if semaphore_nginx_remove_default_config %}default_server{% endif %};
server_name {{ semaphore_hostname }};

location / {
# remember: 301 = moved permanently (search engines will react), 302 = moved temporarily (search engines will hold back)
return 301 https://$server_name$request_uri;
}
}

server {
listen 443 ssl http2 {% if semaphore_nginx_remove_default_config %}default_server{% endif %};
listen [::]:443 ssl http2 {% if semaphore_nginx_remove_default_config %}default_server{% endif %};
server_name {{ semaphore_hostname }};

client_max_body_size 0;
chunked_transfer_encoding on;

{% if semaphore_nginx_use_nginx_common_snippet %}
include {{ semaphore_nginx_tls_hardening_snippet }};
{% else %}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers CHACHA20:-AES:AESGCM:AESCCM:!kRSA:!PSK:!aECDSA:!aDSS:!aNULL:!eNULL:!SHA1:!MD5;
ssl_ecdh_curve X25519:secp521r1:secp384r1;
{% if semaphore_tls_hsts_enable %}
add_header Strict-Transport-Security "max-age={{ semaphore_tls_hsts_time }}";
{% endif %}
{% endif %}

ssl_certificate {{ semaphore_nginx_ssl_certificate }};
ssl_certificate_key {{ semaphore_nginx_ssl_certificate_key }};

location / {
proxy_set_header Host $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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://{{ semaphore_listenip }}:{{ semaphore_listenport }};
proxy_read_timeout 30;

proxy_buffering off;
proxy_request_buffering off;
}

location /api/ws {
proxy_pass http://{{ semaphore_listenip }}:{{ semaphore_listenport }}/api/ws;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Origin "";
}
}
5 changes: 5 additions & 0 deletions vars/vars-Debian.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
# vars specific for Debian systems
semaphore_nginx_default_config: "/etc/nginx/sites-enabled/default"
semaphore_nginx_config_src_dir: "/etc/nginx/sites-available"
semaphore_nginx_config_dst_dir: "/etc/nginx/sites-enabled"
5 changes: 5 additions & 0 deletions vars/vars-RedHat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
# vars specific for RedHat systems
semaphore_nginx_default_config: "/etc/nginx/conf.d/default.conf"
# semaphore_nginx_config_src_dir: ""
semaphore_nginx_config_dst_dir: "/etc/nginx/conf.d"

0 comments on commit f1720b0

Please sign in to comment.