mirror of
https://github.com/fscotto/infra.git
synced 2026-09-27 11:02:47 +00:00
* Add Atlas media and storage services * Document Atlas backend phase one and WireGuard deployment * Enable Atlas NAS management and document bootstrap workflow * Harden Atlas network, SSH, firewall, and sharing * Rotate Ansible Vault secrets * Allow configurable Aegis SSH users and authorized keys * Manage Aegis SSH authorized key fragments * Manage SSH authorized key fragments for infrastructure hosts * Harden Rocky storage and sharing configuration * Verify WireGuard handshakes and restore Podman networking
193 lines
6.3 KiB
YAML
193 lines
6.3 KiB
YAML
---
|
|
- name: Configure WireGuard overlay
|
|
tags: [wireguard, services]
|
|
when: wireguard_overlay_enabled | bool
|
|
block:
|
|
- name: Validate WireGuard host configuration
|
|
ansible.builtin.assert:
|
|
that:
|
|
- wireguard_address != 'CHANGEME_WIREGUARD_ADDRESS'
|
|
- wireguard_address is match('^[0-9]{1,3}(\.[0-9]{1,3}){3}/[0-9]{1,2}$')
|
|
- wireguard_peers | length > 0
|
|
- wireguard_peers | map(attribute='host') | difference(ansible_play_hosts_all) | length == 0
|
|
fail_msg: >-
|
|
Configure this host's WireGuard address and peers, and run the first
|
|
key bootstrap against every peer in the same play.
|
|
|
|
- name: Install WireGuard userspace tools
|
|
ansible.builtin.dnf:
|
|
name: "{{ wireguard_packages }}"
|
|
state: present
|
|
|
|
- name: Create private WireGuard configuration directory
|
|
ansible.builtin.file:
|
|
path: "{{ wireguard_config_dir }}"
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0700"
|
|
|
|
- name: Check for an existing WireGuard private key
|
|
ansible.builtin.stat:
|
|
path: "{{ wireguard_private_key_path }}"
|
|
register: wireguard_private_key_stat
|
|
|
|
- name: Generate a missing WireGuard private key
|
|
ansible.builtin.command:
|
|
argv:
|
|
- wg
|
|
- genkey
|
|
register: wireguard_generated_private_key
|
|
changed_when: true
|
|
no_log: true
|
|
when:
|
|
- not wireguard_private_key_stat.stat.exists
|
|
- not ansible_check_mode
|
|
|
|
- name: Persist the generated WireGuard private key
|
|
ansible.builtin.copy:
|
|
content: "{{ wireguard_generated_private_key.stdout }}\n"
|
|
dest: "{{ wireguard_private_key_path }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0600"
|
|
no_log: true
|
|
when:
|
|
- not wireguard_private_key_stat.stat.exists
|
|
- not ansible_check_mode
|
|
|
|
- name: Require a private key during check mode
|
|
ansible.builtin.assert:
|
|
that:
|
|
- wireguard_private_key_stat.stat.exists
|
|
fail_msg: >-
|
|
The initial WireGuard key generation cannot be simulated safely in
|
|
check mode. Run the gated WireGuard play once without --check.
|
|
when: ansible_check_mode
|
|
|
|
- name: Read the persisted WireGuard private key
|
|
ansible.builtin.slurp:
|
|
src: "{{ wireguard_private_key_path }}"
|
|
register: wireguard_private_key_material
|
|
no_log: true
|
|
|
|
- name: Derive this host's WireGuard public key
|
|
ansible.builtin.command:
|
|
argv:
|
|
- wg
|
|
- pubkey
|
|
stdin: "{{ wireguard_private_key_material.content | b64decode | trim }}"
|
|
register: wireguard_derived_public_key
|
|
changed_when: false
|
|
no_log: true
|
|
|
|
- name: Publish this host's WireGuard public key
|
|
ansible.builtin.set_fact:
|
|
wireguard_public_key: "{{ wireguard_derived_public_key.stdout }}"
|
|
|
|
- name: Require every peer's generated public key
|
|
ansible.builtin.assert:
|
|
that:
|
|
- hostvars[item.host].wireguard_public_key is defined
|
|
- hostvars[item.host].wireguard_public_key | length > 0
|
|
fail_msg: >-
|
|
The public key for {{ item.host }} is unavailable. The first
|
|
WireGuard run must include every overlay host.
|
|
loop: "{{ wireguard_peers }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
|
|
- name: Render the private WireGuard interface configuration
|
|
ansible.builtin.template:
|
|
src: wg.conf.j2
|
|
dest: "{{ wireguard_config_path }}"
|
|
owner: root
|
|
group: root
|
|
mode: "0600"
|
|
diff: false
|
|
no_log: true
|
|
notify: Restart WireGuard interface
|
|
|
|
- name: Enable IPv4 forwarding for the ingress host
|
|
ansible.posix.sysctl:
|
|
name: net.ipv4.ip_forward
|
|
value: "1"
|
|
state: present
|
|
sysctl_set: true
|
|
reload: true
|
|
when: wireguard_enable_ipv4_forwarding | bool
|
|
|
|
- name: Create the WireGuard firewalld zone
|
|
ansible.posix.firewalld:
|
|
zone: "{{ wireguard_firewalld_zone }}"
|
|
state: present
|
|
permanent: true
|
|
register: wireguard_firewalld_zone_result
|
|
|
|
- name: Reload firewalld after creating the WireGuard zone
|
|
ansible.builtin.systemd:
|
|
name: firewalld.service
|
|
state: reloaded
|
|
when:
|
|
- wireguard_firewalld_zone_result is changed
|
|
- not ansible_check_mode
|
|
|
|
- name: Restore rootful Podman networking after firewalld reload
|
|
ansible.builtin.command:
|
|
argv:
|
|
- podman
|
|
- network
|
|
- reload
|
|
- --all
|
|
register: wireguard_podman_network_reload
|
|
changed_when: wireguard_podman_network_reload.stdout_lines | length > 0
|
|
when:
|
|
- wireguard_firewalld_zone_result is changed
|
|
- wireguard_reload_rootful_podman_networks | bool
|
|
- not ansible_check_mode
|
|
|
|
- name: Assign the WireGuard interface to its firewalld zone
|
|
ansible.posix.firewalld:
|
|
interface: "{{ wireguard_interface }}"
|
|
zone: "{{ wireguard_firewalld_zone }}"
|
|
state: enabled
|
|
permanent: true
|
|
immediate: true
|
|
|
|
- name: Permit this host's public WireGuard listener
|
|
ansible.posix.firewalld:
|
|
port: "{{ wireguard_listen_port }}/udp"
|
|
zone: "{{ wireguard_public_firewalld_zone }}"
|
|
state: enabled
|
|
permanent: true
|
|
immediate: true
|
|
when: wireguard_listen_port | int > 0
|
|
|
|
- name: Enable the WireGuard interface
|
|
ansible.builtin.systemd:
|
|
name: "wg-quick@{{ wireguard_interface }}.service"
|
|
enabled: true
|
|
state: started
|
|
daemon_reload: true
|
|
when: not ansible_check_mode
|
|
|
|
- name: Apply pending WireGuard handlers before verification
|
|
ansible.builtin.meta: flush_handlers
|
|
when: not ansible_check_mode
|
|
|
|
- name: Wait for every WireGuard peer handshake
|
|
ansible.builtin.command:
|
|
argv:
|
|
- wg
|
|
- show
|
|
- "{{ wireguard_interface }}"
|
|
- latest-handshakes
|
|
register: wireguard_latest_handshakes
|
|
changed_when: false
|
|
retries: "{{ wireguard_handshake_retries }}"
|
|
delay: "{{ wireguard_handshake_delay }}"
|
|
until:
|
|
- wireguard_latest_handshakes.stdout_lines | length == wireguard_peers | length
|
|
- wireguard_latest_handshakes.stdout_lines | select('search', '\t0$') | list | length == 0
|
|
when: not ansible_check_mode
|