292 lines
11 KiB
YAML
292 lines
11 KiB
YAML
---
|
|
# ============================================================================
|
|
# life-church/playbooks/thinkcenter-reaper.yml
|
|
# Install REAPER DAW (7.79) system-wide on thinkcenter, plus the SWS/S&M
|
|
# extension and ReaPack into the login user's UserPlugins folder.
|
|
# thinkcenter ONLY. Idempotent. become password from Infisical /lc-hosts.
|
|
#
|
|
# - REAPER: tarball from reaper.fm -> install-reaper.sh --quiet into /opt.
|
|
# - SWS 2.14.0.4 (stable) + ReaPack 1.2.6: single .so files dropped into
|
|
# ~<user>/.config/REAPER/UserPlugins/ (per-user, owned by the login user).
|
|
# - Audio: ensures pipewire-jack so REAPER's JACK backend maps to PipeWire,
|
|
# and adds the user to the `audio` group for RT scheduling.
|
|
#
|
|
# UNDO:
|
|
# sudo /opt/REAPER/uninstall-reaper.sh (or: sudo rm -rf /opt/REAPER /usr/local/bin/reaper)
|
|
# rm -f ~<user>/.config/REAPER/UserPlugins/reaper_sws-x86_64.so
|
|
# rm -f ~<user>/.config/REAPER/UserPlugins/reaper_reapack-x86_64.so
|
|
# ============================================================================
|
|
|
|
# --- Play 1 (localhost): fetch thinkcenter sudo pass + user from Infisical ---
|
|
- name: "thinkcenter REAPER — 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 + login user"
|
|
ansible.builtin.set_fact:
|
|
thinkcenter_become_pass: "{{ lc_secrets.secrets['THINKCENTER_SUDO_PASS'] }}"
|
|
thinkcenter_login_user: "{{ lc_secrets.secrets['THINKCENTER_USER'] }}"
|
|
no_log: true
|
|
|
|
# --- Play 2: REAPER + SWS + ReaPack on thinkcenter ONLY ----------------------
|
|
- name: "Install REAPER + SWS + ReaPack on thinkcenter"
|
|
hosts: thinkcenter
|
|
gather_facts: true
|
|
become: true
|
|
vars:
|
|
ansible_become_pass: "{{ hostvars['localhost'].thinkcenter_become_pass }}"
|
|
reaper_user: "{{ hostvars['localhost'].thinkcenter_login_user }}"
|
|
reaper_version: "779" # 7.79 (dot removed)
|
|
reaper_url: "https://www.reaper.fm/files/7.x/reaper779_linux_x86_64.tar.xz"
|
|
reaper_install_dir: /opt
|
|
reaper_binary: /opt/REAPER/reaper
|
|
sws_url: "https://www.sws-extension.org/download/pre-release/sws-2.14.0.4-Linux-x86_64-e04d6ff1.tar.xz"
|
|
sws_so_name: reaper_sws-x86_64.so
|
|
reapack_url: "https://github.com/cfillion/reapack/releases/download/v1.2.6/reaper_reapack-x86_64.so"
|
|
reapack_sha256: "35d80f63d8174c964af589c7d87c4728aa18f06899dce873e33f8d552d1bc7e0"
|
|
tmp_dir: /tmp/reaper-install
|
|
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: "[selfheal] Repair any half-configured dpkg/apt state (prevents cascade failures)"
|
|
ansible.builtin.shell: |
|
|
dpkg --configure -a || true
|
|
apt-get -y -f install || true
|
|
register: dpkg_selfheal
|
|
changed_when: "'Setting up' in (dpkg_selfheal.stdout | default(''))"
|
|
failed_when: false
|
|
|
|
- name: "[safety] Assert reaper_user resolved + exists"
|
|
block:
|
|
- name: "[safety] Assert non-empty"
|
|
ansible.builtin.assert:
|
|
that: reaper_user | length > 0
|
|
fail_msg: "reaper_user empty — THINKCENTER_USER not read from Infisical."
|
|
- name: "[facts] getent the user"
|
|
ansible.builtin.getent:
|
|
database: passwd
|
|
key: "{{ reaper_user }}"
|
|
- name: "[facts] Assert user exists"
|
|
ansible.builtin.assert:
|
|
that: reaper_user in ansible_facts.getent_passwd
|
|
fail_msg: "User '{{ reaper_user }}' does not exist on host."
|
|
|
|
- name: "[deps] Ensure runtime deps + PipeWire-JACK bridge (retry)"
|
|
ansible.builtin.apt:
|
|
name:
|
|
- xz-utils
|
|
- libstdc++6
|
|
- libgl1
|
|
- libasound2t64
|
|
- pipewire-jack
|
|
state: present
|
|
update_cache: true
|
|
cache_valid_time: 3600
|
|
register: deps
|
|
until: deps is succeeded
|
|
retries: 3
|
|
delay: 15
|
|
|
|
- name: "[audio] Add {{ reaper_user }} to the audio group (RT scheduling)"
|
|
ansible.builtin.user:
|
|
name: "{{ reaper_user }}"
|
|
groups: audio
|
|
append: true
|
|
|
|
# ---------- REAPER core ----------
|
|
- name: "[reaper] Is REAPER already installed at {{ reaper_binary }}?"
|
|
ansible.builtin.stat:
|
|
path: "{{ reaper_binary }}"
|
|
register: reaper_present
|
|
|
|
- name: "[reaper] Check installed version (if present)"
|
|
ansible.builtin.command: "{{ reaper_binary }} -version"
|
|
register: reaper_installed_ver
|
|
changed_when: false
|
|
failed_when: false
|
|
when: reaper_present.stat.exists
|
|
|
|
- name: "[reaper] Create temp dir"
|
|
ansible.builtin.file:
|
|
path: "{{ tmp_dir }}"
|
|
state: directory
|
|
mode: "0755"
|
|
when: not reaper_present.stat.exists
|
|
|
|
- name: "[reaper] Download REAPER {{ reaper_version }} tarball (retry)"
|
|
ansible.builtin.get_url:
|
|
url: "{{ reaper_url }}"
|
|
dest: "{{ tmp_dir }}/reaper.tar.xz"
|
|
mode: "0644"
|
|
register: reaper_dl
|
|
until: reaper_dl is succeeded
|
|
retries: 3
|
|
delay: 15
|
|
when: not reaper_present.stat.exists
|
|
|
|
- name: "[reaper] Extract tarball"
|
|
ansible.builtin.unarchive:
|
|
src: "{{ tmp_dir }}/reaper.tar.xz"
|
|
dest: "{{ tmp_dir }}"
|
|
remote_src: true
|
|
when: not reaper_present.stat.exists
|
|
|
|
- name: "[reaper] Run installer unattended (--quiet, desktop integration)"
|
|
ansible.builtin.command:
|
|
cmd: "./install-reaper.sh --install {{ reaper_install_dir }} --integrate-desktop --usr-local-bin-symlink --quiet"
|
|
chdir: "{{ tmp_dir }}/reaper_linux_x86_64"
|
|
register: reaper_installer
|
|
when: not reaper_present.stat.exists
|
|
changed_when: reaper_installer.rc == 0
|
|
|
|
- name: "[reaper] Verify binary now exists"
|
|
ansible.builtin.stat:
|
|
path: "{{ reaper_binary }}"
|
|
register: reaper_after
|
|
|
|
- name: "[reaper] Assert REAPER installed"
|
|
ansible.builtin.assert:
|
|
that: reaper_after.stat.exists
|
|
fail_msg: "REAPER binary not found at {{ reaper_binary }} after install."
|
|
success_msg: "REAPER present at {{ reaper_binary }}."
|
|
|
|
# ---------- User plugin dir ----------
|
|
- name: "[plugins] Resolve user home"
|
|
ansible.builtin.set_fact:
|
|
reaper_home: "{{ ansible_facts.getent_passwd[reaper_user][4] }}"
|
|
|
|
- name: "[plugins] Ensure UserPlugins dir exists (owned by {{ reaper_user }})"
|
|
ansible.builtin.file:
|
|
path: "{{ reaper_home }}/.config/REAPER/UserPlugins"
|
|
state: directory
|
|
owner: "{{ reaper_user }}"
|
|
group: "{{ reaper_user }}"
|
|
mode: "0755"
|
|
|
|
# ---------- SWS extension ----------
|
|
- name: "[sws] Download SWS tarball (retry)"
|
|
ansible.builtin.get_url:
|
|
url: "{{ sws_url }}"
|
|
dest: "{{ tmp_dir }}/sws.tar.xz"
|
|
mode: "0644"
|
|
register: sws_dl
|
|
until: sws_dl is succeeded
|
|
retries: 3
|
|
delay: 15
|
|
|
|
- name: "[sws] Create SWS extract dir"
|
|
ansible.builtin.file:
|
|
path: "{{ tmp_dir }}/sws"
|
|
state: directory
|
|
mode: "0755"
|
|
|
|
- name: "[sws] Extract SWS"
|
|
ansible.builtin.unarchive:
|
|
src: "{{ tmp_dir }}/sws.tar.xz"
|
|
dest: "{{ tmp_dir }}/sws"
|
|
remote_src: true
|
|
|
|
- name: "[sws] Locate the SWS .so inside the archive"
|
|
ansible.builtin.find:
|
|
paths: "{{ tmp_dir }}/sws"
|
|
patterns: "reaper_sws*.so"
|
|
recurse: true
|
|
register: sws_found
|
|
|
|
- name: "[sws] Assert SWS .so found"
|
|
ansible.builtin.assert:
|
|
that: sws_found.files | length > 0
|
|
fail_msg: "Could not find reaper_sws*.so in the SWS archive."
|
|
|
|
- name: "[sws] Install SWS .so into UserPlugins"
|
|
ansible.builtin.copy:
|
|
src: "{{ sws_found.files[0].path }}"
|
|
dest: "{{ reaper_home }}/.config/REAPER/UserPlugins/{{ sws_so_name }}"
|
|
owner: "{{ reaper_user }}"
|
|
group: "{{ reaper_user }}"
|
|
mode: "0644"
|
|
remote_src: true
|
|
register: sws_install
|
|
|
|
# ---------- ReaPack ----------
|
|
- name: "[reapack] Download ReaPack .so with checksum verification (retry)"
|
|
ansible.builtin.get_url:
|
|
url: "{{ reapack_url }}"
|
|
dest: "{{ reaper_home }}/.config/REAPER/UserPlugins/reaper_reapack-x86_64.so"
|
|
checksum: "sha256:{{ reapack_sha256 }}"
|
|
owner: "{{ reaper_user }}"
|
|
group: "{{ reaper_user }}"
|
|
mode: "0644"
|
|
register: reapack_install
|
|
until: reapack_install is succeeded
|
|
retries: 3
|
|
delay: 15
|
|
|
|
# ---------- Verify + cleanup ----------
|
|
- name: "[verify] List installed REAPER user plugins"
|
|
ansible.builtin.find:
|
|
paths: "{{ reaper_home }}/.config/REAPER/UserPlugins"
|
|
patterns: "*.so"
|
|
register: installed_plugins
|
|
|
|
- name: "[verify] Assert both extensions present"
|
|
ansible.builtin.assert:
|
|
that:
|
|
- installed_plugins.files | map(attribute='path') | select('search','reaper_sws') | list | length > 0
|
|
- installed_plugins.files | map(attribute='path') | select('search','reaper_reapack') | list | length > 0
|
|
fail_msg: "SWS and/or ReaPack .so missing from UserPlugins."
|
|
success_msg: "SWS + ReaPack installed into UserPlugins."
|
|
|
|
- name: "[cleanup] Remove temp install dir"
|
|
ansible.builtin.file:
|
|
path: "{{ tmp_dir }}"
|
|
state: absent
|
|
|
|
- name: "[report] REAPER stack summary"
|
|
ansible.builtin.debug:
|
|
msg:
|
|
- "===== thinkcenter REAPER stack ====="
|
|
- "REAPER binary : {{ reaper_binary }} ({{ 'newly installed' if not reaper_present.stat.exists else 'already present' }})"
|
|
- "UserPlugins dir : {{ reaper_home }}/.config/REAPER/UserPlugins"
|
|
- "installed .so files : {{ installed_plugins.files | map(attribute='path') | map('basename') | list }}"
|
|
- "audio group : {{ reaper_user }} added (log out/in for RT scheduling to take effect)"
|
|
- "NOTE: launch REAPER, set Preferences->Audio->Device to JACK (PipeWire bridge) or ALSA. Extensions appear under the Extensions menu."
|