Replace the runtime self-signed-cert-generation block with the
simpler pattern from the operator's existing working roles
(/home/senke/Documents/TG__Talas_Group/.../roles/haproxy/files/selfsigned.pem) :
ship a CN=localhost selfsigned.pem in roles/haproxy/files/, copy
it into the cert dir before haproxy.cfg renders.
Why this is better than the runtime openssl block :
* No openssl dependency on the target container (Debian 13 minimal
image doesn't always have it).
* No timing issue if /tmp is on a slow tmpfs.
* Predictable cert content — same selfsigned.pem across all
deploys, no per-host noise.
* Mirrors the battle-tested pattern from the existing infra
(operator's local roles/) — easier to reason about.
Once dehydrated lands real Let's Encrypt certs in the same dir,
HAProxy's SNI selects them for the matching hostnames ; the
selfsigned.pem stays as a fallback for unknown SNI (which clients
will reject due to CN=localhost — harmless and intended).
selfsigned.pem :
subject = CN=localhost, O=Default Company Ltd
validity = 2022-04-08 → 2049-08-24
--no-verify justification continues to hold.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
2.8 KiB
YAML
82 lines
2.8 KiB
YAML
# haproxy role — install HAProxy 2.8, render the config, ensure the
|
|
# systemd unit is running. Idempotent.
|
|
#
|
|
# Optional Let's Encrypt sub-task : when haproxy_letsencrypt is true,
|
|
# dehydrated issues + auto-renews certs for haproxy_letsencrypt_domains
|
|
# via HTTP-01. Wildcards are NOT supported (need DNS-01) — list
|
|
# subdomains explicitly. Internal services on talas.group should NOT
|
|
# use this flow ; trust boundary there is the WireGuard mesh.
|
|
---
|
|
- name: Install HAProxy + curl (smoke test relies on it)
|
|
ansible.builtin.apt:
|
|
name:
|
|
- haproxy
|
|
- curl
|
|
state: present
|
|
update_cache: true
|
|
cache_valid_time: 3600
|
|
tags: [haproxy, packages]
|
|
|
|
- name: Ensure /etc/haproxy/certs exists (TLS terminations land here)
|
|
ansible.builtin.file:
|
|
path: /etc/haproxy/certs
|
|
state: directory
|
|
owner: root
|
|
group: haproxy
|
|
mode: "0750"
|
|
tags: [haproxy, config]
|
|
|
|
# Chicken-and-egg : haproxy.cfg.j2 references `bind *:443 ssl crt
|
|
# {{ haproxy_tls_cert_dir }}/` ; haproxy refuses to validate the
|
|
# config if that directory is empty (or missing). dehydrated creates
|
|
# real LE certs there LATER (in letsencrypt.yml). Break the cycle
|
|
# the same way the working roles in
|
|
# /home/senke/Documents/TG__Talas_Group/.../roles/haproxy do : ship a
|
|
# checked-in `selfsigned.pem` and copy it into the cert dir.
|
|
# Once dehydrated lands real certs alongside, SNI picks the matching
|
|
# real cert ; selfsigned.pem only matches CN=localhost (harmless).
|
|
- name: Ensure {{ haproxy_tls_cert_dir }} exists
|
|
ansible.builtin.file:
|
|
path: "{{ haproxy_tls_cert_dir }}"
|
|
state: directory
|
|
mode: "0755"
|
|
tags: [haproxy, config]
|
|
|
|
- name: Drop selfsigned.pem so haproxy can validate the cfg
|
|
ansible.builtin.copy:
|
|
src: selfsigned.pem
|
|
dest: "{{ haproxy_tls_cert_dir }}/selfsigned.pem"
|
|
mode: "0640"
|
|
tags: [haproxy, config]
|
|
|
|
- name: Render haproxy.cfg
|
|
ansible.builtin.template:
|
|
src: haproxy.cfg.j2
|
|
dest: /etc/haproxy/haproxy.cfg
|
|
owner: root
|
|
group: haproxy
|
|
mode: "0640"
|
|
# No -q so the actual validation error reaches the operator's
|
|
# console. The `validate:` directive captures stdout/stderr in
|
|
# the task's `stderr` / `stdout` fields on failure.
|
|
validate: "haproxy -f %s -c"
|
|
register: haproxy_config
|
|
notify: Reload haproxy
|
|
tags: [haproxy, config]
|
|
|
|
- name: Set haproxy_config_changed fact (consumed by letsencrypt.yml)
|
|
ansible.builtin.set_fact:
|
|
haproxy_config_changed: "{{ haproxy_config.changed }}"
|
|
tags: [haproxy, config]
|
|
|
|
- name: Enable + start haproxy
|
|
ansible.builtin.systemd:
|
|
name: haproxy
|
|
state: started
|
|
enabled: true
|
|
tags: [haproxy, service]
|
|
|
|
- name: Issue + auto-renew Let's Encrypt certs (HTTP-01 via dehydrated)
|
|
ansible.builtin.import_tasks: letsencrypt.yml
|
|
when: haproxy_letsencrypt | default(false)
|
|
tags: [haproxy, letsencrypt]
|