semaphore/playbooks/preflight-homarr.yml

140 lines
5.3 KiB
YAML

---
# ============================================================================
# preflight-homarr.yml — reachability pre-flight for Homarr (NO host changes)
# ============================================================================
# Read-only gate. Confirms, in order:
# 1. Infisical auth + deploy SSH key retrievable (runner).
# 2. Target host reachable over SSH as the `ansible` user.
# 3. Rootless docker is usable (docker version).
# 4. The `homarr` container exists and is running.
# 5. Homarr answers HTTP on its port.
# Fails with a clear reason at the first broken link. Changes nothing on the host.
#
# Run this before update-homarr-checked.yml, or any time to confirm Homarr health.
#
# Connects AS the `ansible` user via the Infisical-injected deploy key (same
# pattern as deploy-homarr.yml / update-homarr.yml).
#
# Usage: playbook playbooks/preflight-homarr.yml, extra vars: target=racknerd1
# ============================================================================
- name: "PRECHECK — fetch deploy SSH key from Infisical"
hosts: localhost
gather_facts: false
vars:
infisical_url: "{{ lookup('env','INFISICAL_URL') | default('http://192.168.122.41:8080', true) }}"
infisical_env_slug: "{{ lookup('env','INFISICAL_ENV_SLUG') | default('dev', true) }}"
tasks:
- name: "[precheck] Infisical auth vars present?"
ansible.builtin.assert:
that:
- lookup('env','INFISICAL_CLIENT_ID') | length > 0
- lookup('env','INFISICAL_CLIENT_SECRET') | length > 0
- lookup('env','INFISICAL_PROJECT_ID') | length > 0
fail_msg: "Missing INFISICAL_CLIENT_ID / _SECRET / _PROJECT_ID in Semaphore Environment."
- name: "[precheck] Login to Infisical"
infisical.vault.login:
url: "{{ infisical_url }}"
auth_method: universal_auth
universal_auth_client_id: "{{ lookup('env','INFISICAL_CLIENT_ID') }}"
universal_auth_client_secret: "{{ lookup('env','INFISICAL_CLIENT_SECRET') }}"
register: infisical_login
- name: "[precheck] Read secrets"
infisical.vault.read_secrets:
login_data: "{{ infisical_login.login_data }}"
project_id: "{{ lookup('env','INFISICAL_PROJECT_ID') }}"
env_slug: "{{ infisical_env_slug }}"
path: "/"
as_dict: true
register: infisical_secrets
- name: "[precheck] stash SSH key for preflight play"
ansible.builtin.set_fact:
pc_ssh_privkey: "{{ infisical_secrets.secrets.SSH_PRIVATE_KEY }}"
no_log: true
- name: "[precheck] write deploy private key to runner temp (0600)"
ansible.builtin.copy:
dest: "/tmp/homarr_deploy_key"
content: "{{ pc_ssh_privkey }}\n"
mode: "0600"
no_log: true
- name: "PRE-FLIGHT — reachability + Homarr health (read-only)"
hosts: "{{ target | default('racknerd1') }}"
gather_facts: false
vars:
deploy_user: ansible
homarr_dir: "/home/{{ deploy_user }}/docker/homarr"
homarr_port: 7575
ansible_user: ansible
ansible_ssh_private_key_file: "/tmp/homarr_deploy_key"
ansible_ssh_common_args: "-o StrictHostKeyChecking=accept-new -o IdentitiesOnly=yes"
tasks:
- name: "[1/5] SSH reachable as ansible user?"
ansible.builtin.ping:
- name: Reset connection so docker group membership is active in this session
ansible.builtin.meta: reset_connection
- name: "[2/5] Rootless docker usable?"
ansible.builtin.command: docker version
register: dv
changed_when: false
failed_when: dv.rc != 0
- name: "[3/5] Homarr container present + running?"
ansible.builtin.command:
cmd: docker inspect --format '{{ '{{' }}.State.Running{{ '}}' }}' homarr
register: homarr_state
changed_when: false
failed_when: false
- name: "Assert homarr container is running"
ansible.builtin.assert:
that:
- homarr_state.rc == 0
- homarr_state.stdout | trim == 'true'
fail_msg: >-
Homarr container is not running on {{ inventory_hostname }}
(docker inspect rc={{ homarr_state.rc }}, state='{{ homarr_state.stdout | trim }}').
Run deploy-homarr.yml.
- name: "[4/5] Compose stack file present?"
ansible.builtin.stat:
path: "{{ homarr_dir }}/docker-compose.yml"
register: compose_file
- name: "Warn if compose file missing (container running without repo compose)"
ansible.builtin.debug:
msg: >-
NOTE: no docker-compose.yml at {{ homarr_dir }} — container is running but
update-homarr-checked.yml expects the compose stack. Deploy first if updating.
when: not compose_file.stat.exists
- name: "[5/5] Homarr answers HTTP?"
ansible.builtin.uri:
url: "http://127.0.0.1:{{ homarr_port }}/"
status_code: [200, 302, 307]
register: health
retries: 6
delay: 5
until: health.status is defined and health.status in [200, 302, 307]
- name: "PRE-FLIGHT PASSED"
ansible.builtin.debug:
msg: >-
Homarr reachable on {{ inventory_hostname }}:{{ homarr_port }}
(HTTP {{ health.status }}) — safe to update.
- name: "Cleanup runner temp key"
hosts: localhost
gather_facts: false
tasks:
- name: "remove temp deploy key from runner"
ansible.builtin.file:
path: /tmp/homarr_deploy_key
state: absent