/
/
/
Ansible role that deploys a supervised home assistant installation on my homeassistant device.
1---
2# Semaphore UI Deployment
3#
4# Secrets are written as raw files and passed through the image's *_FILE
5# variables. That keeps them out of the compose file, and avoids compose
6# interpolating a '$' inside a password. Compose cannot see file contents,
7# so the start task forces a recreate when a secret or requirements.txt
8# changed - and only then, so the container starts exactly once per run.
9
10- name: Create Semaphore project directory
11 ansible.builtin.file:
12 path: "{{ homeassistant_semaphore_dir }}"
13 state: directory
14 owner: "{{ homeassistant_docker_owner }}"
15 group: "{{ homeassistant_docker_group }}"
16 mode: '2775'
17 become: true
18
19- name: Create Semaphore state directories (owned by the container user)
20 ansible.builtin.file:
21 path: "{{ item }}"
22 state: directory
23 owner: "{{ homeassistant_semaphore_uid }}"
24 group: "{{ homeassistant_semaphore_gid }}"
25 mode: '0750'
26 become: true
27 loop:
28 - "{{ homeassistant_semaphore_config_dir }}"
29 - "{{ homeassistant_semaphore_data_dir }}"
30
31- name: Create Semaphore secrets directory
32 ansible.builtin.file:
33 path: "{{ homeassistant_semaphore_secrets_dir }}"
34 state: directory
35 owner: "{{ homeassistant_semaphore_uid }}"
36 group: "{{ homeassistant_semaphore_gid }}"
37 mode: '0700'
38 become: true
39
40- name: Deploy Semaphore secret files
41 ansible.builtin.copy:
42 content: "{{ item.value }}"
43 dest: "{{ homeassistant_semaphore_secrets_dir }}/{{ item.name }}"
44 owner: "{{ homeassistant_semaphore_uid }}"
45 group: "{{ homeassistant_semaphore_gid }}"
46 mode: '0400'
47 become: true
48 loop:
49 - { name: admin_password, value: "{{ homeassistant_semaphore_admin_password }}" }
50 - { name: access_key_encryption, value: "{{ homeassistant_semaphore_access_key_encryption }}" }
51 loop_control:
52 label: "{{ item.name }}"
53 register: semaphore_secrets
54 no_log: true
55
56# The image's wrapper pip-installs /etc/semaphore/requirements.txt on start
57- name: Deploy Semaphore Python requirements
58 ansible.builtin.template:
59 src: semaphore-requirements.txt.j2
60 dest: "{{ homeassistant_semaphore_config_dir }}/requirements.txt"
61 owner: "{{ homeassistant_semaphore_uid }}"
62 group: "{{ homeassistant_semaphore_gid }}"
63 mode: '0644'
64 become: true
65 register: semaphore_requirements_deployed
66 when: homeassistant_semaphore_python_requirements | length > 0
67
68- name: Remove Semaphore Python requirements when none are configured
69 ansible.builtin.file:
70 path: "{{ homeassistant_semaphore_config_dir }}/requirements.txt"
71 state: absent
72 become: true
73 register: semaphore_requirements_removed
74 when: homeassistant_semaphore_python_requirements | length == 0
75
76- name: Deploy Semaphore Docker Compose file
77 ansible.builtin.template:
78 src: semaphore-compose.yml.j2
79 dest: "{{ homeassistant_semaphore_dir }}/docker-compose.yaml"
80 owner: "{{ homeassistant_docker_owner }}"
81 group: "{{ homeassistant_docker_group }}"
82 mode: '0664'
83 become: true
84
85- name: Start Semaphore service
86 community.docker.docker_compose_v2:
87 project_src: "{{ homeassistant_semaphore_dir }}"
88 state: present
89 recreate: "{{ 'always' if (semaphore_secrets is changed or semaphore_requirements_deployed is changed or semaphore_requirements_removed is changed) else 'auto' }}"
90 register: semaphore_start_result
91 check_mode: false
92 when: not ansible_check_mode
93
94# First start runs the setup and a pip install before the API answers
95- name: Wait for Semaphore API to respond
96 ansible.builtin.uri:
97 url: "http://localhost:{{ homeassistant_semaphore_host_port }}/api/ping"
98 method: GET
99 status_code: [200]
100 register: semaphore_health
101 until: semaphore_health.status == 200
102 retries: 24
103 delay: 5
104 check_mode: false
105 when:
106 - not ansible_check_mode
107 - semaphore_start_result is changed
108
109- name: Display Semaphore deployment summary
110 ansible.builtin.debug:
111 msg: |
112 Semaphore UI Deployment:
113 - Status: {{ 'Check mode - not started' if ansible_check_mode else ('Started' if semaphore_start_result is changed else 'Already running') }}
114 - Web UI: http://{{ ansible_default_ipv4.address }}:{{ homeassistant_semaphore_host_port }}
115 - Admin user: {{ homeassistant_semaphore_admin_user }} (password from vault, applied on first start only)
116 - Database: SQLite in {{ homeassistant_semaphore_data_dir }}
117 - Config: {{ homeassistant_semaphore_config_dir }}
118 - Extra Python packages: {{ homeassistant_semaphore_python_requirements | join(', ') if homeassistant_semaphore_python_requirements | length > 0 else 'none' }}
119