Capture current Ansible control plane state
Commit the accumulated infrastructure work that was living only in the working tree: monitoring stack, emergency access/bot, gyro allocator, grimmory, adguard, backup audit and the OpenCode agent definitions. Also ignore Python bytecode, local archives and Nix/direnv artifacts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GTocXkGUUazHdKKd3r9k71
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
---
|
||||
- name: Guard Gyro VMID before API updates
|
||||
hosts: mini-pc
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Read existing VMID 150 configuration
|
||||
ansible.builtin.command: pct config 150
|
||||
register: gyro_existing_vmid
|
||||
check_mode: false
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Refuse to modify a foreign VMID 150
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- gyro_existing_vmid.rc != 0 or gyro_existing_hostname == 'gyro'
|
||||
fail_msg: VMID 150 already exists and is not the Gyro container.
|
||||
vars:
|
||||
gyro_existing_hostname: >-
|
||||
{{ gyro_existing_vmid.stdout_lines
|
||||
| select('match', '^hostname: ')
|
||||
| map('regex_replace', '^hostname: ', '')
|
||||
| first
|
||||
| default('') }}
|
||||
|
||||
- name: Create Gyro LXC on mini-pc
|
||||
hosts: localhost
|
||||
connection: local
|
||||
become: false
|
||||
gather_facts: false
|
||||
vars:
|
||||
ansible_become: false
|
||||
ansible_python_interpreter: "{{ ansible_playbook_python }}"
|
||||
pve_lxc_vmid: 150
|
||||
pve_lxc_node: mini-pc
|
||||
pve_lxc_hostname: gyro
|
||||
pve_lxc_ip: 192.168.1.35/24
|
||||
pve_lxc_gateway: 192.168.1.1
|
||||
pve_lxc_disk: local-lvm:2
|
||||
pve_lxc_cores: 1
|
||||
pve_lxc_memory: 512
|
||||
pve_lxc_swap: 256
|
||||
pve_lxc_startup: order=80
|
||||
pve_lxc_unprivileged: true
|
||||
pve_lxc_update: false
|
||||
pve_lxc_features: []
|
||||
pve_lxc_ostemplate: local:vztmpl/debian-13-standard_13.1-2_amd64.tar.zst
|
||||
roles:
|
||||
- role: pve_lxc
|
||||
|
||||
- name: Configure Gyro LXC isolation
|
||||
hosts: mini-pc
|
||||
gather_facts: false
|
||||
vars:
|
||||
gyro_vmid: 150
|
||||
tasks:
|
||||
- name: Read Gyro LXC configuration
|
||||
ansible.builtin.command: "pct config {{ gyro_vmid }}"
|
||||
register: gyro_lxc_config
|
||||
changed_when: false
|
||||
|
||||
- name: Require expected Gyro LXC properties
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- "'hostname: gyro' in gyro_lxc_config.stdout"
|
||||
- "'unprivileged: 1' in gyro_lxc_config.stdout"
|
||||
- "'rootfs: local-lvm:' in gyro_lxc_config.stdout"
|
||||
- "'onboot: 1' in gyro_lxc_config.stdout"
|
||||
|
||||
- name: Check for an existing Gyro firewall file
|
||||
ansible.builtin.stat:
|
||||
path: "/etc/pve/firewall/{{ gyro_vmid }}.fw"
|
||||
register: gyro_firewall_file
|
||||
|
||||
- name: Preserve the existing Gyro firewall file
|
||||
ansible.builtin.slurp:
|
||||
src: "/etc/pve/firewall/{{ gyro_vmid }}.fw"
|
||||
register: gyro_previous_firewall
|
||||
when: gyro_firewall_file.stat.exists
|
||||
|
||||
- name: Apply and verify Gyro firewall
|
||||
block:
|
||||
- name: Render Proxmox firewall for Gyro
|
||||
ansible.builtin.copy:
|
||||
dest: "/tmp/gyro-{{ gyro_vmid }}.fw"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
content: |
|
||||
[OPTIONS]
|
||||
enable: 1
|
||||
policy_in: DROP
|
||||
policy_out: ACCEPT
|
||||
|
||||
[RULES]
|
||||
IN ACCEPT -source {{ homelab_lan_cidr }} -p tcp -dport 22 -log nolog
|
||||
IN ACCEPT -source {{ openvpn_network_cidr }} -p tcp -dport 22 -log nolog
|
||||
OUT ACCEPT -dest 192.168.1.27 -p tcp -dport 7890 -log nolog
|
||||
OUT DROP -dest {{ homelab_lan_cidr }} -log nolog
|
||||
register: gyro_rendered_firewall
|
||||
changed_when: false
|
||||
|
||||
- name: Compare rendered and active Gyro firewall
|
||||
ansible.builtin.command: >-
|
||||
cmp -s /tmp/gyro-{{ gyro_vmid }}.fw /etc/pve/firewall/{{ gyro_vmid }}.fw
|
||||
register: gyro_firewall_comparison
|
||||
changed_when: false
|
||||
failed_when: gyro_firewall_comparison.rc not in [0, 1]
|
||||
when: gyro_firewall_file.stat.exists
|
||||
|
||||
- name: Install Proxmox firewall for Gyro
|
||||
ansible.builtin.command: >-
|
||||
cp /tmp/gyro-{{ gyro_vmid }}.fw /etc/pve/firewall/{{ gyro_vmid }}.fw
|
||||
when: not gyro_firewall_file.stat.exists or gyro_firewall_comparison.rc != 0
|
||||
changed_when: true
|
||||
|
||||
- name: Validate Proxmox firewall configuration
|
||||
ansible.builtin.command: pve-firewall compile
|
||||
changed_when: false
|
||||
|
||||
- name: Read cluster firewall options
|
||||
ansible.builtin.command: pvesh get /cluster/firewall/options --output-format json
|
||||
register: gyro_cluster_firewall_options
|
||||
changed_when: false
|
||||
|
||||
- name: Report staged Proxmox firewall state
|
||||
ansible.builtin.debug:
|
||||
msg: >-
|
||||
{{ 'Gyro Proxmox firewall is active.'
|
||||
if (gyro_cluster_firewall_options.stdout | from_json).enable | default(0) | int == 1
|
||||
else 'Gyro Proxmox firewall is staged but inactive because the cluster firewall is disabled; UFW remains the enforced isolation layer.' }}
|
||||
|
||||
- name: Verify SSH remains reachable through the firewall
|
||||
ansible.builtin.wait_for_connection:
|
||||
timeout: 180
|
||||
delegate_to: gyro
|
||||
vars:
|
||||
ansible_become: false
|
||||
rescue:
|
||||
- name: Restore the previous Gyro firewall file
|
||||
ansible.builtin.copy:
|
||||
dest: "/tmp/gyro-{{ gyro_vmid }}-previous.fw"
|
||||
content: "{{ gyro_previous_firewall.content | b64decode }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0640"
|
||||
when: gyro_firewall_file.stat.exists
|
||||
|
||||
- name: Reinstall the previous Gyro firewall file
|
||||
ansible.builtin.command: >-
|
||||
cp /tmp/gyro-{{ gyro_vmid }}-previous.fw /etc/pve/firewall/{{ gyro_vmid }}.fw
|
||||
when: gyro_firewall_file.stat.exists
|
||||
changed_when: true
|
||||
|
||||
- name: Remove the failed new Gyro firewall file
|
||||
ansible.builtin.file:
|
||||
path: "/etc/pve/firewall/{{ gyro_vmid }}.fw"
|
||||
state: absent
|
||||
when: not gyro_firewall_file.stat.exists
|
||||
|
||||
- name: Recompile restored Proxmox firewall configuration
|
||||
ansible.builtin.command: pve-firewall compile
|
||||
changed_when: false
|
||||
|
||||
- name: Remove temporary Gyro firewall files after rollback
|
||||
ansible.builtin.file:
|
||||
path: "{{ item }}"
|
||||
state: absent
|
||||
loop:
|
||||
- "/tmp/gyro-{{ gyro_vmid }}.fw"
|
||||
- "/tmp/gyro-{{ gyro_vmid }}-previous.fw"
|
||||
|
||||
- name: Stop after rolling back the Gyro firewall
|
||||
ansible.builtin.fail:
|
||||
msg: Gyro firewall validation or SSH reachability failed; the previous firewall state was restored.
|
||||
|
||||
- name: Remove temporary Gyro firewall file
|
||||
ansible.builtin.file:
|
||||
path: "/tmp/gyro-{{ gyro_vmid }}.fw"
|
||||
state: absent
|
||||
changed_when: false
|
||||
|
||||
- name: Wait for Gyro SSH
|
||||
hosts: gyro
|
||||
gather_facts: false
|
||||
tasks:
|
||||
- name: Wait for Gyro to accept SSH connections
|
||||
ansible.builtin.wait_for_connection:
|
||||
timeout: 180
|
||||
Reference in New Issue
Block a user