--- # ============================================================================ # life-church/playbooks/thinkcenter-obs.yml # Install OBS Studio on thinkcenter via the official OBS PPA (latest stable), # plus v4l2loopback (virtual camera) + ffmpeg. thinkcenter ONLY. Idempotent. # Native packages only (no flatpak/snap — matches the homelab audio rule). # become password from Infisical /lc-hosts at runtime. # # Mint gotcha handled: `add-apt-repository` mis-detects Mint's codename ("zena") # instead of the Ubuntu base ("noble"). We add the PPA source explicitly pinned # to the Ubuntu base codename so apt can resolve it. # # UNDO: # sudo apt remove --purge obs-studio v4l2loopback-dkms # sudo add-apt-repository --remove ppa:obsproject/obs-studio # (or delete /etc/apt/sources.list.d/obsproject-*.list + key) # ============================================================================ # --- Play 1 (localhost): fetch thinkcenter sudo pass from Infisical ---------- - name: "thinkcenter OBS — resolve become password from Infisical" hosts: localhost gather_facts: false tasks: - name: "[resolve] Infisical creds from env" 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 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" 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 thinkcenter sudo pass" ansible.builtin.set_fact: thinkcenter_become_pass: "{{ lc_secrets.secrets['THINKCENTER_SUDO_PASS'] }}" no_log: true # --- Play 2: OBS on thinkcenter ONLY ----------------------------------------- - name: "Install OBS Studio on thinkcenter" hosts: thinkcenter gather_facts: true become: true vars: ansible_become_pass: "{{ hostvars['localhost'].thinkcenter_become_pass }}" obs_ppa_codename: noble # Ubuntu base for Mint 22.3 (NOT 'zena') tasks: - name: "[safety] Confirm we are on thinkcenter" ansible.builtin.assert: that: inventory_hostname == 'thinkcenter' fail_msg: "Refusing to run — this play is scoped to thinkcenter only." - name: "[safety] Confirm Ubuntu-family host (apt/PPA path)" ansible.builtin.assert: that: ansible_facts.os_family == 'Debian' fail_msg: "This playbook targets Debian/Ubuntu (Mint). Host is {{ ansible_facts.os_family }}." - name: "[repo] Ensure keyrings dir exists" ansible.builtin.file: path: /etc/apt/keyrings state: directory mode: "0755" - name: "[repo] Fetch OBS PPA signing key into keyring (modern signed-by method)" ansible.builtin.get_url: url: "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xBC7345F522079769F5BBE987EFC71127F425E228" dest: /etc/apt/keyrings/obsproject-obs-studio.asc mode: "0644" force: false register: obs_key until: obs_key is succeeded retries: 3 delay: 10 - name: "[repo] Add OBS PPA source pinned to Ubuntu base codename (avoids Mint 'zena' bug)" ansible.builtin.apt_repository: repo: "deb [signed-by=/etc/apt/keyrings/obsproject-obs-studio.asc] https://ppa.launchpadcontent.net/obsproject/obs-studio/ubuntu {{ obs_ppa_codename }} main" filename: obsproject-obs-studio state: present update_cache: false register: obs_repo - name: "[repo] Update apt cache (retry on transient failure)" ansible.builtin.apt: update_cache: true register: apt_cache until: apt_cache is succeeded retries: 3 delay: 15 - name: "[apt] Install OBS Studio + virtual-cam + ffmpeg (retry on dpkg lock)" ansible.builtin.apt: name: - obs-studio - v4l2loopback-dkms - v4l2loopback-utils - ffmpeg state: present register: obs_install until: obs_install is succeeded retries: 3 delay: 15 - name: "[vcam] Configure v4l2loopback module for the OBS virtual camera" ansible.builtin.copy: dest: /etc/modprobe.d/obs-v4l2loopback.conf mode: "0644" content: | options v4l2loopback devices=1 video_nr=10 card_label="OBS Virtual Camera" exclusive_caps=1 register: vcam_conf - name: "[vcam] Load v4l2loopback now (non-fatal if module build pending a reboot)" community.general.modprobe: name: v4l2loopback state: present register: vcam_load failed_when: false - name: "[verify] Query obs-studio package status (dpkg, not the GUI binary)" ansible.builtin.command: dpkg-query -W -f='${Status} ${Version}' obs-studio register: obs_pkg changed_when: false failed_when: false - name: "[verify] obs binary present on PATH" ansible.builtin.command: which obs register: obs_bin changed_when: false failed_when: false - name: "[verify] Assert OBS installed" ansible.builtin.assert: that: - "'install ok installed' in (obs_pkg.stdout | default(''))" - obs_bin.rc == 0 fail_msg: "OBS Studio not installed. pkg='{{ obs_pkg.stdout | default('') }}', bin rc={{ obs_bin.rc }}" success_msg: "OBS Studio installed." - name: "[report] OBS summary" ansible.builtin.debug: msg: - "===== thinkcenter OBS Studio =====" - "packages changed this run : {{ obs_install.changed }}" - "OBS package : {{ obs_pkg.stdout | default('n/a') | trim }}" - "v4l2loopback module loaded: {{ 'yes' if vcam_load.rc | default(1) == 0 else 'not yet (loads on Start Virtual Camera / reboot)' }}" - "NOTE: on Mint X11 use XSHM/XComposite capture sources; PipeWire capture is for Wayland."