# Deliberately untagged, and deliberately without an OPENSSL_FIPS of our own.
#
# The base moves, and twice in three days a move of it closed the public door
# with no commit of ours behind it. On 2026-09-02 the base began preferring
# OpenSSL's FIPS provider — Photon's openssl.cnf reads the preference straight
# out of the environment as `default_properties = ?fips=$ENV::OPENSSL_FIPS` —
# and that provider cannot produce an X25519MLKEM768 key, so HAProxy offered a
# group it could not use and refused every client that asks for post-quantum key
# exchange. `ENV OPENSSL_FIPS=no` fixed that, and was right for that base.
#
# On the 2026-09-04 base it is the other way round: with "no" HAProxy cannot load
# an ECDSA certificate at all and exits at parse time on `bind *:443`, saying
# "inconsistencies between private key and certificate" about a leaf and key that
# openssl confirms are one pair. The base's own "yes" loads it and still
# negotiates TLS 1.3. Measured on testnet2 against the live certificate, same
# image, only the variable changed:
#
#     OPENSSL_FIPS=no    config check fails at `bind *:443`
#     OPENSSL_FIPS=yes   config check passes, curl 200, TLSv1.3
#
# So the value that is right depends on the base, and hard-coding either one is
# how the next base move breaks this image. Take what the base ships.
#
# The base is not pinned either: there are no version tags to pin to (only
# `latest` exists), and a digest would have to be raised by hand for every
# security update. What catches a bad base is the testnet stand — Watchtower
# there picks up each rebuild within seconds, which is exactly how both of these
# were found. **Production does not run Watchtower and is updated by hand**, so
# a base that breaks the door is seen on the stand first. When it happens again,
# the two lines above are the first thing to check.
FROM bitnami/haproxy

# The FIPS preference is left exactly as the base ships it, and that is a
# reversal. The base is Photon OS, whose openssl.cnf reads the variable straight
# out of the environment:
#
#     [alg_sect]
#     default_properties = ?fips=$ENV::OPENSSL_FIPS
#
# On the 2026-09-02 base "yes" meant every algorithm fetch preferred the FIPS
# provider, which cannot produce an X25519MLKEM768 key, so haproxy offered a
# group it could not use and refused every modern client. `ENV OPENSSL_FIPS=no`
# fixed that and was correct for that base.
#
# On the base pinned above it is the other way round: with "no" haproxy cannot
# load an ECDSA certificate at all and exits at parse time, while the shipped
# "yes" loads it and still negotiates TLS 1.3. Measured on testnet2 against the
# live certificate, same image, only the variable changed:
#
#     OPENSSL_FIPS=no    config check fails at `bind *:443`
#     OPENSSL_FIPS=yes   config check passes, curl 200, TLSv1.3
#
# So the override is gone rather than inverted. Pinning the base is what makes
# leaving it alone safe: the value that is right depends on the base, and the
# base no longer moves on its own.

# Copy config
COPY ./docker/haproxy.cfg /bitnami/haproxy/conf/haproxy.cfg

# Directory for the runtime API socket. HAProxy runs as uid 1001 here and binds
# a unix socket by creating `<path>.<pid>.tmp` and renaming it over the target,
# so it needs write permission on the *directory*, not just the file — which is
# also why a stale socket left by a previous run is harmless.
#
# /var/lib is owned by root, hence the explicit USER switch. Docker copies this
# ownership onto an empty named volume when it initialises one here, so the
# volume shared with certbot comes up writable by HAProxy without a chown at
# runtime.
USER root
RUN mkdir -p /var/lib/haproxy && chown 1001:1001 /var/lib/haproxy
USER 1001

# The base image's entrypoint is the haproxy binary itself, with no shell in
# between, so this wrapper is the whole chain: it fills in XFF_HMAC_KEY when
# nothing else did (see the script for why that is better than requiring it) and
# execs the same binary with the same arguments. CMD is restated rather than
# left to inheritance — it would be inherited, but a changed ENTRYPOINT is
# exactly where that stops being obvious to the next reader.
COPY --chmod=0755 ./docker/entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["-f", "/bitnami/haproxy/conf/haproxy.cfg"]

