--- # ============================================================================ # life-church/playbooks/lc-precheck.yml # Pre-checks + fact gathering for Life Church desktops (thinkcenter, tc1). # READ-ONLY: gathers facts and asserts baseline conditions. Changes nothing. # # become (sudo) password is fetched from Infisical /lc-hosts at runtime on # localhost, then applied per-host via ansible_become_pass. Never hardcoded. # ============================================================================ # --------------------------------------------------------------------------- # Play 1 (localhost): resolve Infisical creds + read per-host sudo passwords # --------------------------------------------------------------------------- - name: "Life Church pre-check — resolve become passwords from Infisical" hosts: localhost gather_facts: false tasks: - name: "[resolve] Infisical creds from env (Semaphore environment)" ansible.builtin.set_fact: infisical_client_id: "{{ lookup('env','INFISICAL_CLIENT_ID') }}" infisical_client_secret: "{{ lookup('env','INFISICAL_CLIENT_SECRET') }}" infisical_project_id: "{{ lookup('env','INFISICAL_PROJECT_ID') }}" infisical_url: "{{ lookup('env','INFISICAL_API_URL') | default('http://192.168.122.41:8080', true) }}" infisical_env_slug: "{{ lookup('env','INFISICAL_ENV_SLUG') | default('prod', true) }}" - name: "[resolve] Assert Infisical creds present" ansible.builtin.assert: that: - infisical_client_id | length > 0 - infisical_client_secret | length > 0 - infisical_project_id | length > 0 fail_msg: "Infisical creds missing from environment — check Semaphore environment 'infisical-dev'." - name: "[infisical] Log in" infisical.vault.login: url: "{{ infisical_url }}" auth_method: universal_auth universal_auth_client_id: "{{ infisical_client_id }}" universal_auth_client_secret: "{{ infisical_client_secret }}" register: infisical_login no_log: true - name: "[infisical] Read /lc-hosts secrets" infisical.vault.read_secrets: login_data: "{{ infisical_login.login_data }}" project_id: "{{ infisical_project_id }}" env_slug: "{{ infisical_env_slug }}" path: "/lc-hosts" as_dict: true register: lc_secrets no_log: true - name: "[set] Stash become passwords keyed by host (localhost hostvars)" ansible.builtin.set_fact: become_pass_map: thinkcenter: "{{ lc_secrets.secrets['THINKCENTER_SUDO_PASS'] }}" tc1: "{{ lc_secrets.secrets['TC1_SUDO_PASS'] }}" no_log: true # --------------------------------------------------------------------------- # Play 2 (the desktops): connectivity, facts, and read-only pre-checks # --------------------------------------------------------------------------- - name: "Life Church pre-check — connectivity + facts + baseline checks" hosts: lifechurch_desktops gather_facts: true become: true vars: # pull this host's sudo pass from the map computed on localhost in Play 1 ansible_become_pass: "{{ hostvars['localhost'].become_pass_map[inventory_hostname] }}" tasks: - name: "[net] Host reachable (SSH connection established)" ansible.builtin.ping: - name: "[sudo] Privilege escalation works" ansible.builtin.command: id -u register: id_check changed_when: false - name: "[sudo] Confirm running as root after become" ansible.builtin.assert: that: id_check.stdout == "0" fail_msg: "become did not escalate to root on {{ inventory_hostname }}" success_msg: "sudo OK on {{ inventory_hostname }}" - name: "[disk] Root filesystem usage" ansible.builtin.set_fact: root_mount: "{{ ansible_mounts | selectattr('mount','equalto','/') | first }}" - name: "[disk] Assert root filesystem has >10% free" ansible.builtin.assert: that: (root_mount.size_available / root_mount.size_total) > 0.10 fail_msg: "LOW DISK on {{ inventory_hostname }}: only {{ (100 * root_mount.size_available / root_mount.size_total) | round(1) }}% free" success_msg: "Disk OK: {{ (100 * root_mount.size_available / root_mount.size_total) | round(1) }}% free" - name: "[mem] Assert at least 200MB RAM free" ansible.builtin.assert: that: ansible_memfree_mb > 200 fail_msg: "LOW MEMORY on {{ inventory_hostname }}: {{ ansible_memfree_mb }}MB free" success_msg: "Memory OK: {{ ansible_memfree_mb }}MB free of {{ ansible_memtotal_mb }}MB" - name: "[time] Check NTP/clock sync status" ansible.builtin.command: timedatectl show -p NTPSynchronized --value register: ntp_sync changed_when: false failed_when: false - name: "[pkg] Count pending apt security updates" ansible.builtin.shell: >- set -o pipefail; apt-get -s -o Debug::NoLocking=true upgrade 2>/dev/null | grep -c '^Inst' || true args: executable: /bin/bash register: pending_updates changed_when: false failed_when: false - name: "[reboot] Reboot-required flag present?" ansible.builtin.stat: path: /var/run/reboot-required register: reboot_required - name: "[report] Host summary" ansible.builtin.debug: msg: - "===== {{ inventory_hostname }} ({{ ansible_host }}) =====" - "OS : {{ ansible_distribution }} {{ ansible_distribution_version }} | kernel {{ ansible_kernel }}" - "CPU / RAM : {{ ansible_processor_vcpus }} vcpus | {{ ansible_memtotal_mb }}MB total, {{ ansible_memfree_mb }}MB free" - "Root disk : {{ (root_mount.size_total / 1073741824) | round(1) }}GB total, {{ (root_mount.size_available / 1073741824) | round(1) }}GB free ({{ (100 * root_mount.size_available / root_mount.size_total) | round(1) }}% free)" - "Uptime : {{ (ansible_uptime_seconds / 3600) | round(1) }} hours" - "Clock synced : {{ 'yes' if ntp_sync.stdout == 'yes' else 'NO — check time sync' }}" - "Pending pkgs : {{ pending_updates.stdout | trim }} upgradable" - "Reboot needed : {{ 'YES' if reboot_required.stat.exists else 'no' }}" - "Default IPv4 : {{ ansible_default_ipv4.address | default('n/a') }} ({{ ansible_default_ipv4.interface | default('n/a') }})" # --------------------------------------------------------------------------- # Play 3 (localhost): overall result # --------------------------------------------------------------------------- - name: "Life Church pre-check — result" hosts: localhost gather_facts: false tasks: - name: "[result] ALL PRE-CHECKS PASSED" ansible.builtin.debug: msg: "Pre-checks passed for all Life Church desktops — hosts reachable, sudo OK, resources healthy."