--- - name: Install required packages ansible.builtin.apt: name: ethtool state: present update_cache: yes # ------------------------------------------------------------ # Map vmbr0 → backing physical NIC # ------------------------------------------------------------ - name: Get bridge link information ansible.builtin.command: "bridge link show" register: bridge_links changed_when: false failed_when: false - name: Show bridge_links.stdout_lines ansible.builtin.debug: msg: "{{ bridge_links.stdout_lines }}" - name: "Detect physical NIC backing {{ wol_bridge }}" ansible.builtin.set_fact: wol_detected_phy_candidates: >- {{ bridge_links.stdout_lines | select('search', 'master ' ~ wol_bridge) | map('regex_replace', '^\\d+: ([^:@]+).*', '\\1') | reject('search', '^(veth|tap|fw)') | list }} - name: Select first physical NIC candidate ansible.builtin.set_fact: wol_detected_phy: "{{ wol_detected_phy_candidates[0] | default('') }}" - name: Fail if vmbr0 backing NIC could not be detected ansible.builtin.fail: msg: > Unable to detect physical NIC backing {{ wol_bridge }}. Please set wol_interface explicitly. Bridge output: {{ bridge_links.stdout_lines }} when: wol_detected_phy | default('') | length == 0 # ------------------------------------------------------------ # Validate WOL capability # ------------------------------------------------------------ - name: Check WOL capability on detected NIC ansible.builtin.command: "ethtool {{ wol_detected_phy }}" register: wol_capabilities changed_when: false - name: Fail if NIC does not support Wake-on-LAN ansible.builtin.fail: msg: "Interface {{ wol_detected_phy }} does not support Wake-on-LAN." when: "'Supports Wake-on: g' not in wol_capabilities.stdout" # ------------------------------------------------------------ # Enable WOL immediately # ------------------------------------------------------------ - name: Enable Wake-on-LAN immediately ansible.builtin.command: > ethtool -s {{ wol_detected_phy }} wol {{ wol_mode }} changed_when: false # ------------------------------------------------------------ # Persist WOL via udev (correct + recommended) # ------------------------------------------------------------ - name: Create udev rule to persist Wake-on-LAN ansible.builtin.copy: dest: /etc/udev/rules.d/90-wol.rules owner: root group: root mode: '0644' content: | ACTION=="add", SUBSYSTEM=="net", KERNEL=="{{ wol_detected_phy }}", RUN+="/sbin/ethtool -s {{ wol_detected_phy }} wol {{ wol_mode }}" - name: Reload udev rules ansible.builtin.command: udevadm control --reload changed_when: false - name: Trigger udev for network interfaces ansible.builtin.command: udevadm trigger --subsystem-match=net changed_when: false # ------------------------------------------------------------ # Verification & Reporting # ------------------------------------------------------------ - name: Verify Wake-on-LAN status ansible.builtin.command: "ethtool {{ wol_detected_phy }}" register: wol_status changed_when: false when: wol_verify - name: Get MAC address ansible.builtin.set_fact: wol_mac_address: "{{ ansible_facts.interfaces[wol_detected_phy].macaddress | default('') }}" - name: Fail if MAC address could not be detected ansible.builtin.fail: msg: "Unable to determine MAC address for interface {{ wol_detected_phy }}" when: - wol_report_mac - wol_mac_address | length == 0 - name: Show WOL status ansible.builtin.debug: msg: "{{ wol_status.stdout_lines }}" when: wol_verify - name: Report Wake-on-LAN sender details ansible.builtin.debug: msg: - "Wake-on-LAN enabled successfully" - "Bridge: {{ wol_bridge }}" - "Physical NIC: {{ wol_detected_phy }}" - "MAC address: {{ wol_mac_address }}" - "Example commands:" - " wakeonlan {{ wol_mac_address }}" - " etherwake {{ wol_mac_address }}" - "Home Assistant:" - " mac: {{ wol_mac_address }}" when: wol_report_mac