--- - name: Configure static IP using Netplan (only if needed) become: true when: - ansible_distribution == "Ubuntu" - ansible_oldip is defined - ansible_oldip != ansible_newip block: - name: Detect primary network interface set_fact: netplan_interface: "{{ ansible_default_ipv4.interface }}" - name: Derive CIDR prefix from netmask (fallback to 24) set_fact: netmask_bits: "{{ ansible_default_ipv4.netmask | ansible.utils.ipaddr('prefix') | default('24', true) }}" - name: Capture system DNS servers (fallback to 8.8.8.8) set_fact: current_dns_servers: "{{ ansible_dns.nameservers | default(['8.8.8.8']) }}" - name: Generate Netplan config with static IP ansible.builtin.copy: dest: /etc/netplan/01-netcfg.yaml mode: '0600' content: | network: version: 2 renderer: networkd ethernets: {{ netplan_interface }}: dhcp4: no addresses: [{{ ansible_newip }}/{{ netmask_bits }}] routes: - to: default via: {{ ansible_default_ipv4.gateway }} nameservers: addresses: {{ current_dns_servers }} - name: Remove default cloud-init netplan config ansible.builtin.file: path: /etc/netplan/50-cloud-init.yaml state: absent notify: Apply netplan - name: Wait for network change to apply ansible.builtin.pause: seconds: 10 - name: Wait for host to become reachable on new IP ansible.builtin.wait_for: host: "{{ ansible_newip }}" port: 22 delay: 5 timeout: 120 state: started - name: Reassign ansible_host to the new static IP set_fact: ansible_host: "{{ ansible_newip }}"