/
/
/
Ansible role that deployes services on my runner machine
1---
2# Runner Role - Vault Variable Validation
3# Fail fast if critical vault secrets are missing or empty
4
5# Only when the remote chronicler is selected. A missing key would otherwise
6# surface as an auth error on the first chapter of an evening -- after
7# transcription and diarization have already run.
8- name: Assert the remote chronicler has an API key
9 ansible.builtin.assert:
10 that: (vault_runner.deepseek_api_key | default('')) | length > 0
11 fail_msg: >-
12 dnd_chronicle_backend is 'remote' but vault_runner.deepseek_api_key is
13 unset. Add it to group_vars/all/vault.yml, or set
14 dnd_chronicle_backend: local to keep the chapter in the house.
15 success_msg: "The remote chronicler has a key"
16 when:
17 - dnd_enabled | bool
18 - dnd_chronicle_backend == 'remote'
19 tags: [dnd, vault]
20
21- name: Validate PostgreSQL vault variables (Immich)
22 ansible.builtin.assert:
23 that:
24 - postgres_password | default('') | length > 0
25 - postgres_db | default('') | length > 0
26 - postgres_user | default('') | length > 0
27 fail_msg: |
28 Missing PostgreSQL vault variables required by Immich.
29 Ensure vault_runner contains: postgres_password, postgres_db, postgres_user
30 success_msg: "PostgreSQL vault variables validated"
31 when: immich_enabled
32 tags: [always, validation]
33
34- name: Validate Immich JWT secret
35 ansible.builtin.assert:
36 that:
37 - immich_jwt_secret | default('') | length > 0
38 fail_msg: |
39 Missing Immich JWT secret.
40 Ensure vault_runner contains: immich_jwt_secret
41 success_msg: "Immich JWT secret validated"
42 when: immich_enabled
43 tags: [always, validation]
44
45- name: Validate MySQL vault variables (Ghost)
46 ansible.builtin.assert:
47 that:
48 - mysql_password | default('') | length > 0
49 - mysql_root_password | default('') | length > 0
50 fail_msg: |
51 Missing MySQL vault variables required by Ghost CMS.
52 Ensure vault_runner contains: mysql_password, mysql_root_password
53 success_msg: "MySQL vault variables validated"
54 when: ghost_enabled
55 tags: [always, validation]
56
57- name: Validate Tandoor secret key
58 ansible.builtin.assert:
59 that:
60 - tandoor_secret_key | default('') | length > 0
61 fail_msg: |
62 Missing Tandoor secret key.
63 Ensure vault_runner contains: tandoor_secret_key
64 success_msg: "Tandoor secret key validated"
65 when: tandoor_enabled
66 tags: [always, validation]
67
68- name: Validate LiveKit API credentials
69 ansible.builtin.assert:
70 that:
71 - livekit_api_key | default('') | length > 0
72 - livekit_api_secret | default('') | length >= 32
73 fail_msg: |
74 Missing or weak LiveKit API credentials.
75 Ensure vault_runner contains: livekit_api_key, livekit_api_secret
76 The secret must be at least 32 characters. Generate a pair with:
77 docker run --rm livekit/livekit-server generate-keys
78 success_msg: "LiveKit API credentials validated"
79 when: livekit_enabled
80 tags: [always, validation]
81
82- name: Validate LiteLLM secrets
83 ansible.builtin.assert:
84 that:
85 - vault_runner.lite_llm_master_key | default('') | length > 0
86 - vault_runner.lite_llm_salt_key | default('') | length > 0
87 - vault_runner.lite_llm_db_password | default('') | length > 0
88 fail_msg: |
89 Missing LiteLLM secrets.
90 Ensure vault_runner contains: lite_llm_master_key, lite_llm_salt_key, lite_llm_db_password
91
92 lite_llm_salt_key encrypts model credentials at rest and must NEVER be
93 changed once models have been stored in the database - rotating it makes
94 previously stored credentials unrecoverable.
95 success_msg: "LiteLLM secrets validated"
96 when: llm_stack_enabled
97 tags: [always, validation]
98
99- name: Validate D&D agent secrets
100 ansible.builtin.assert:
101 that:
102 - vault_runner.homeassistant_token | default('') | length > 0
103 - vault_runner.homeassistant_url | default('') | length > 0
104 - vault_runner.huggingface_token | default('') | length > 0
105 fail_msg: |
106 Missing D&D session agent secrets.
107 Ensure vault_runner contains: homeassistant_token, homeassistant_url,
108 huggingface_token
109
110 The Home Assistant token drives lighting scenes; create one under
111 Profile -> Security -> Long-lived access tokens.
112
113 The HuggingFace token only downloads gated pyannote weights once -
114 diarization itself runs locally. It requires accepting the terms on
115 pyannote/segmentation-3.0, pyannote/speaker-diarization-3.1 and
116 pyannote/speaker-diarization-community-1.
117 success_msg: "D&D agent secrets validated"
118 when: dnd_enabled
119 tags: [always, validation]
120
121# The Chamberlain needs no secrets of its own: it reuses the LiveKit keys
122# asserted above and the MQTT credentials asserted below. Email is deliberately
123# optional -- with no SMTP host it hides the mail buttons and says what is
124# missing, so an unset vault entry is a supported state rather than a failure.
125- name: Warn when Chamberlain email is unconfigured
126 ansible.builtin.debug:
127 msg: >-
128 Chamberlain email is not configured (vault_runner.dnd_smtp_host is unset),
129 so the recap and invitation buttons will be hidden. Set dnd_smtp_host,
130 dnd_mail_from and dnd_mail_to under vault_runner to enable them.
131 when: dnd_enabled and not chamberlain_smtp_host
132 tags: [always, validation]
133
134- name: Validate MQTT credentials
135 ansible.builtin.assert:
136 that:
137 - mqtt_username | default('') | length > 0
138 - mqtt_password | default('') | length > 0
139 fail_msg: |
140 Missing MQTT credentials.
141 Ensure the vault contains top-level: mqtt_username, mqtt_password
142 success_msg: "MQTT credentials validated"
143 when: frigate_enabled and frigate_mqtt_enabled
144 tags: [always, validation]
145
146- name: Validate at least one camera has a non-empty host
147 ansible.builtin.assert:
148 that:
149 - frigate_cameras | selectattr('enabled', 'equalto', true) | selectattr('host', 'ne', '') | list | length > 0
150 fail_msg: |
151 No enabled Frigate cameras have a configured host.
152 Ensure at least one camera in frigate_cameras has a non-empty host from vault.
153 success_msg: "Frigate camera configuration validated"
154 when: frigate_enabled
155 tags: [always, validation]
156
157- name: Validate Macro Checker vault variables
158 ansible.builtin.assert:
159 that:
160 - macros_password | length > 0
161 - macros_secret_key | length >= 32
162 - macros_postgres_password | length > 0
163 - macros_searxng_secret | length > 0
164 fail_msg: |
165 Missing Macro Checker secrets.
166 Ensure the vault contains a vault_macros block with: password,
167 secret_key (32+ chars), postgres_password, searxng_secret.
168 Generate values with: openssl rand -hex 32
169 success_msg: "Macro Checker vault variables validated"
170 when: macros_enabled
171 tags: [always, validation]
172
173- name: Validate Mealie vault variables
174 ansible.builtin.assert:
175 that:
176 - mealie_admin_email | length > 0
177 - mealie_admin_password | length >= 12
178 - mealie_admin_password != 'MyPassword'
179 - mealie_postgres_password | length > 0
180 fail_msg: |
181 Missing Mealie secrets.
182 Ensure the vault contains a vault_mealie block with: admin_email,
183 admin_password (12+ characters, not the default), postgres_password.
184 Optional: admin_username, admin_full_name, llm_api_key.
185 success_msg: "Mealie vault variables validated"
186 when: mealie_enabled
187 tags: [always, validation]
188