--- - name: Verify hosts: all become: true gather_facts: false tasks: - name: Read the rendered ruleset ansible.builtin.slurp: src: /etc/nftables.conf register: ruleset - name: Decode it ansible.builtin.set_fact: nft: "{{ ruleset.content | b64decode }}" - name: Assert default-deny input policy and management plane ansible.builtin.assert: that: - "'type filter hook input priority 0; policy drop;' in nft" - "'ct state established,related accept' in nft" - "'iifname \"wt0\" tcp dport 22 accept' in nft" - "'ip saddr 10.10.0.99 tcp dport 22 accept' in nft" fail_msg: >- input chain is missing default-deny, the wt0 SSH allow, or the ssh-from-control management-plane rule - name: Assert the lan->reverse_proxy:443 ingress rule (zone source) ansible.builtin.assert: that: - "'10.30.0.0/24' in nft" - "'tcp dport 443 accept' in nft" fail_msg: "missing lan->443 rule for reverse_proxy" - name: Assert the srv->photoprism:2342 ingress rule (zone source) ansible.builtin.assert: that: - "'10.20.0.0/24' in nft" - "'tcp dport 2342 accept' in nft" fail_msg: "missing srv->2342 rule for photoprism" - name: Assert the docker_host extension hook is present ansible.builtin.assert: that: - "'include \"/etc/nftables.d/*.nft\"' in nft" fail_msg: "missing drop-in include hook" - name: Syntax-check the rendered ruleset (no apply) ansible.builtin.command: nft -c -f /etc/nftables.conf changed_when: false