semaphore/life-church/playbooks/thinkcenter-rustdesk.yml

209 lines
8.4 KiB
YAML

---
# ============================================================================
# life-church/playbooks/thinkcenter-rustdesk.yml
# Install the RustDesk remote-desktop client (1.4.9) on thinkcenter and point
# it at the self-hosted RustDesk server (racknerd2, via NetBird mesh).
# thinkcenter ONLY. Idempotent. become password from Infisical /lc-hosts.
# Server config (id/relay/key) pulled from Infisical /rustdesk at runtime.
#
# - Downloads the official .deb (Flutter build) from GitHub with SHA256 verify.
# - Installs via apt (resolves deps automatically).
# - Writes ~<user>/.config/rustdesk/RustDesk2.toml with the custom rendezvous
# (ID) server, relay server, and public key so the client auto-registers to
# the self-hosted server instead of the public RustDesk network.
#
# UNDO:
# sudo apt remove --purge rustdesk
# rm -rf ~<user>/.config/rustdesk
# ============================================================================
# --- Play 1 (localhost): fetch creds + rustdesk server config from Infisical -
- name: "thinkcenter RustDesk — resolve secrets 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 (sudo pass + user)"
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: "[infisical] Read /rustdesk (server config)"
infisical.vault.read_secrets:
login_data: "{{ infisical_login.login_data }}"
project_id: "{{ infisical_project_id }}"
env_slug: "{{ infisical_env_slug }}"
path: "/rustdesk"
as_dict: true
register: rd_secrets
no_log: true
- name: "[set] Stash sudo pass, user, and rustdesk server config"
ansible.builtin.set_fact:
thinkcenter_become_pass: "{{ lc_secrets.secrets['THINKCENTER_SUDO_PASS'] }}"
thinkcenter_login_user: "{{ lc_secrets.secrets['THINKCENTER_USER'] }}"
rd_id_server: "{{ rd_secrets.secrets['RUSTDESK_ID_SERVER'] }}"
rd_relay_server: "{{ rd_secrets.secrets['RUSTDESK_RELAY_SERVER'] }}"
rd_api_server: "{{ rd_secrets.secrets['RUSTDESK_API_SERVER'] | default('', true) }}"
rd_key: "{{ rd_secrets.secrets['RUSTDESK_KEY'] }}"
no_log: true
# --- Play 2: RustDesk on thinkcenter ONLY ------------------------------------
- name: "Install + configure RustDesk client on thinkcenter"
hosts: thinkcenter
gather_facts: true
become: true
vars:
ansible_become_pass: "{{ hostvars['localhost'].thinkcenter_become_pass }}"
rd_user: "{{ hostvars['localhost'].thinkcenter_login_user }}"
rd_version: "1.4.9"
rd_deb_url: "https://github.com/rustdesk/rustdesk/releases/download/1.4.9/rustdesk-1.4.9-x86_64.deb"
rd_deb_sha256: "7244ba47c40e804172044bfbe659467c54ce46554c98e78c8c0406f1d612fda3"
rd_id_server: "{{ hostvars['localhost'].rd_id_server }}"
rd_relay_server: "{{ hostvars['localhost'].rd_relay_server }}"
rd_api_server: "{{ hostvars['localhost'].rd_api_server }}"
rd_key: "{{ hostvars['localhost'].rd_key }}"
tmp_dir: /tmp/rustdesk-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 rd_user resolved + exists"
block:
- name: "[safety] Non-empty user"
ansible.builtin.assert:
that: rd_user | length > 0
fail_msg: "rd_user empty — THINKCENTER_USER not read from Infisical."
- name: "[facts] getent user"
ansible.builtin.getent:
database: passwd
key: "{{ rd_user }}"
- name: "[facts] Assert user exists"
ansible.builtin.assert:
that: rd_user in ansible_facts.getent_passwd
fail_msg: "User '{{ rd_user }}' does not exist on host."
- name: "[facts] Resolve user home"
ansible.builtin.set_fact:
rd_home: "{{ ansible_facts.getent_passwd[rd_user][4] }}"
- name: "[dl] Create temp dir"
ansible.builtin.file:
path: "{{ tmp_dir }}"
state: directory
mode: "0755"
- name: "[dl] Download RustDesk {{ rd_version }} .deb with SHA256 verify (retry)"
ansible.builtin.get_url:
url: "{{ rd_deb_url }}"
dest: "{{ tmp_dir }}/rustdesk.deb"
checksum: "sha256:{{ rd_deb_sha256 }}"
mode: "0644"
register: rd_dl
until: rd_dl is succeeded
retries: 3
delay: 15
- name: "[apt] Install RustDesk .deb (apt resolves dependencies; retry on lock)"
ansible.builtin.apt:
deb: "{{ tmp_dir }}/rustdesk.deb"
state: present
register: rd_install
until: rd_install is succeeded
retries: 3
delay: 15
- name: "[verify] rustdesk binary present"
ansible.builtin.command: which rustdesk
register: rd_which
changed_when: false
failed_when: false
- name: "[verify] Assert RustDesk installed"
ansible.builtin.assert:
that: rd_which.rc == 0
fail_msg: "RustDesk binary not found after install."
success_msg: "RustDesk installed at {{ rd_which.stdout | trim }}."
# ---- Point the client at the self-hosted server (per-user config) ----
- name: "[config] Ensure rustdesk config dir for {{ rd_user }}"
ansible.builtin.file:
path: "{{ rd_home }}/.config/rustdesk"
state: directory
owner: "{{ rd_user }}"
group: "{{ rd_user }}"
mode: "0700"
- name: "[config] Write RustDesk2.toml (custom ID/relay server + key)"
ansible.builtin.copy:
dest: "{{ rd_home }}/.config/rustdesk/RustDesk2.toml"
owner: "{{ rd_user }}"
group: "{{ rd_user }}"
mode: "0600"
content: |
rendezvous_server = '{{ rd_id_server }}'
nat_type = 1
serial = 0
[options]
custom-rendezvous-server = '{{ rd_id_server }}'
relay-server = '{{ rd_relay_server }}'
{% if rd_api_server | length > 0 %}api-server = '{{ rd_api_server }}'
{% endif %}key = '{{ rd_key }}'
register: rd_config
no_log: true
- name: "[cleanup] Remove temp dir"
ansible.builtin.file:
path: "{{ tmp_dir }}"
state: absent
- name: "[report] RustDesk summary"
ansible.builtin.debug:
msg:
- "===== thinkcenter RustDesk ====="
- "packages changed this run : {{ rd_install.changed }}"
- "rustdesk path : {{ rd_which.stdout | default('n/a') | trim }}"
- "config written for : {{ rd_user }} ({{ rd_home }}/.config/rustdesk/RustDesk2.toml)"
- "ID/relay server : self-hosted (from Infisical /rustdesk)"
- "NOTE: restart RustDesk (or the rustdesk service) for the custom server to take effect. Client shows the server key is applied under Settings -> Network."