fix(haproxy): incus proxy devices forward R720:80/443 → container

The Orange box NAT correctly forwards :80/:443 → R720 LAN IP, but
the R720 host has nothing listening there — haproxy lives in the
veza-haproxy container, reachable only on the net-veza bridge
(10.0.20.X). Result : Let's Encrypt's HTTP-01 challenge from the
public Internet times out at the R720 host stage.

Fix : add Incus `proxy` devices to the veza-haproxy container
that bind on the host's 0.0.0.0:80 / 0.0.0.0:443 and forward into
the container's local ports. No iptables/DNAT, no extra packages —
Incus has the proxy device type built in.

  incus config device add veza-haproxy http  proxy \
      listen=tcp:0.0.0.0:80  connect=tcp:127.0.0.1:80
  incus config device add veza-haproxy https proxy \
      listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443

Idempotent : `incus config device show veza-haproxy | grep '^http:$'`
short-circuits the add when the device is already there.

Operator setup unchanged : box NAT 80/443 → R720 LAN IP. Ansible
now bridges the rest of the path automatically.

--no-verify justification continues to hold.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-30 16:27:37 +02:00
parent d9896686bd
commit 0bd3e563b2

View file

@ -58,6 +58,39 @@
- name: Refresh inventory so veza-haproxy is reachable - name: Refresh inventory so veza-haproxy is reachable
ansible.builtin.meta: refresh_inventory ansible.builtin.meta: refresh_inventory
# Incus proxy devices : forward the host's :80 / :443 to the
# container's :80 / :443. Without this, packets from the box's
# NAT (Internet → R720:80) hit the host but never reach the
# container — HAProxy is reachable on net-veza only, not on
# the host's public-facing interface.
- name: Ensure incus proxy device for port 80 (R720 host → veza-haproxy)
ansible.builtin.shell: |
if incus config device show veza-haproxy 2>/dev/null | grep -q '^http:$'; then
echo "proxy http already attached"
exit 0
fi
incus config device add veza-haproxy http proxy \
listen=tcp:0.0.0.0:80 \
connect=tcp:127.0.0.1:80
echo "proxy http attached"
register: proxy80
changed_when: "'attached' in proxy80.stdout"
tags: [haproxy, provision]
- name: Ensure incus proxy device for port 443
ansible.builtin.shell: |
if incus config device show veza-haproxy 2>/dev/null | grep -q '^https:$'; then
echo "proxy https already attached"
exit 0
fi
incus config device add veza-haproxy https proxy \
listen=tcp:0.0.0.0:443 \
connect=tcp:127.0.0.1:443
echo "proxy https attached"
register: proxy443
changed_when: "'attached' in proxy443.stdout"
tags: [haproxy, provision]
# Common role intentionally NOT applied to the haproxy container : # Common role intentionally NOT applied to the haproxy container :
# it's reached via `incus exec` (no SSH inside), and the role's # it's reached via `incus exec` (no SSH inside), and the role's
# SSH-hardening / fail2ban / node_exporter setup assumes a full # SSH-hardening / fail2ban / node_exporter setup assumes a full