mirror of
https://github.com/fscotto/infra.git
synced 2026-09-27 11:02:47 +00:00
256 lines
8.6 KiB
YAML
256 lines
8.6 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: Validate WireGuard forwarding policies
|
|
ansible.builtin.assert:
|
|
that:
|
|
- item.name is defined
|
|
- item.ingress_zone is defined
|
|
- item.egress_zone is defined
|
|
- item.source is defined
|
|
- item.destination is defined
|
|
fail_msg: >-
|
|
Every WireGuard forwarding policy requires name, ingress_zone,
|
|
egress_zone, source, and destination.
|
|
loop: "{{ wireguard_forwarding_policies }}"
|
|
loop_control:
|
|
label: "{{ item.name | default('unnamed policy') }}"
|
|
|
|
- name: Install WireGuard userspace tools on mutable hosts
|
|
ansible.builtin.dnf:
|
|
name: "{{ wireguard_packages }}"
|
|
state: present
|
|
when: "'platform_fedora_iot' not in group_names"
|
|
|
|
- name: Require WireGuard userspace tools in the booted deployment
|
|
ansible.builtin.command:
|
|
argv:
|
|
- wg
|
|
- --version
|
|
changed_when: false
|
|
failed_when: false
|
|
register: wireguard_userspace_tools
|
|
|
|
- name: Require active WireGuard userspace tools
|
|
ansible.builtin.assert:
|
|
that:
|
|
- wireguard_userspace_tools.rc == 0
|
|
fail_msg: >-
|
|
WireGuard userspace tools are not present in the booted deployment.
|
|
On Fedora IoT, reboot after rpm-ostree layers wireguard-tools, then
|
|
rerun the WireGuard play.
|
|
|
|
- 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: Create the firewalld policy directory
|
|
ansible.builtin.file:
|
|
path: /etc/firewalld/policies
|
|
state: directory
|
|
owner: root
|
|
group: root
|
|
mode: "0755"
|
|
when: wireguard_forwarding_policies | length > 0
|
|
|
|
- name: Render WireGuard forwarding policies
|
|
ansible.builtin.template:
|
|
src: wireguard-forwarding-policy.xml.j2
|
|
dest: "/etc/firewalld/policies/{{ item.name }}.xml"
|
|
owner: root
|
|
group: root
|
|
mode: "0644"
|
|
loop: "{{ wireguard_forwarding_policies }}"
|
|
loop_control:
|
|
label: "{{ item.name }}"
|
|
register: wireguard_forwarding_policy_result
|
|
|
|
- name: Reload firewalld after WireGuard firewall changes
|
|
ansible.builtin.systemd:
|
|
name: firewalld.service
|
|
state: reloaded
|
|
when:
|
|
- wireguard_firewalld_zone_result is changed or (wireguard_forwarding_policy_result | default({})) 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 or (wireguard_forwarding_policy_result | default({})) 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: Manage legacy WireGuard zone masquerading
|
|
ansible.posix.firewalld:
|
|
zone: "{{ wireguard_firewalld_zone }}"
|
|
masquerade: true
|
|
state: "{{ 'enabled' if wireguard_enable_masquerade | bool else 'disabled' }}"
|
|
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
|