From 89282230f5839a72cc37d2ac315af0cbc102bc8d Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sun, 15 Feb 2026 16:25:46 +0000 Subject: [PATCH 1/2] test: add haproxy smoke test Assisted-by: GLM 5 via Claude Code Signed-off-by: Xe Iaso --- test/haproxy-simple/anubis.env | 11 ++++++ test/haproxy-simple/conf/anubis/anubis.yaml | 11 ++++++ test/haproxy-simple/conf/haproxy/haproxy.cfg | 27 ++++++++++++++ test/haproxy-simple/docker-compose.yaml | 27 ++++++++++++++ test/haproxy-simple/test.mjs | 39 ++++++++++++++++++++ test/haproxy-simple/test.sh | 31 ++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 test/haproxy-simple/anubis.env create mode 100644 test/haproxy-simple/conf/anubis/anubis.yaml create mode 100644 test/haproxy-simple/conf/haproxy/haproxy.cfg create mode 100644 test/haproxy-simple/docker-compose.yaml create mode 100644 test/haproxy-simple/test.mjs create mode 100755 test/haproxy-simple/test.sh diff --git a/test/haproxy-simple/anubis.env b/test/haproxy-simple/anubis.env new file mode 100644 index 000000000..a2c459417 --- /dev/null +++ b/test/haproxy-simple/anubis.env @@ -0,0 +1,11 @@ +# /etc/anubis/default.env + +BIND=/shared/anubis.sock +BIND_NETWORK=unix +SOCKET_MODE=0666 +DIFFICULTY=4 +METRICS_BIND=:9090 +COOKIE_DYNAMIC_DOMAIN=true +# address and port of the actual application (httpdebug container) +TARGET=http://httpdebug:3000 +POLICY_FNAME=/cfg/anubis.yaml diff --git a/test/haproxy-simple/conf/anubis/anubis.yaml b/test/haproxy-simple/conf/anubis/anubis.yaml new file mode 100644 index 000000000..ac870407e --- /dev/null +++ b/test/haproxy-simple/conf/anubis/anubis.yaml @@ -0,0 +1,11 @@ +bots: + - name: mozilla + user_agent_regex: Mozilla + action: CHALLENGE + challenge: + difficulty: 2 + algorithm: fast + +status_codes: + CHALLENGE: 401 + DENY: 403 diff --git a/test/haproxy-simple/conf/haproxy/haproxy.cfg b/test/haproxy-simple/conf/haproxy/haproxy.cfg new file mode 100644 index 000000000..38c825000 --- /dev/null +++ b/test/haproxy-simple/conf/haproxy/haproxy.cfg @@ -0,0 +1,27 @@ +# /etc/haproxy/haproxy.cfg + +frontend FE-application + mode http + timeout client 5s + timeout connect 5s + timeout server 5s + bind :80 + # ssl offloading on port 8443 using a certificate from /etc/haproxy/ssl/ + bind :8443 ssl crt /etc/techaro/pki/haproxy-simple.test.pem alpn h2,http/1.1 ssl-min-ver TLSv1.2 no-tls-tickets + + # set X-Real-IP header required for Anubis + http-request set-header X-Real-IP "%[src]" + + # redirect HTTP to HTTPS + http-request redirect scheme https code 301 unless { ssl_fc } + # add HSTS header + http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" + + # route to Anubis backend by default + default_backend BE-anubis-application + +backend BE-anubis-application + mode http + timeout connect 5s + timeout server 5s + server anubis /shared/anubis.sock diff --git a/test/haproxy-simple/docker-compose.yaml b/test/haproxy-simple/docker-compose.yaml new file mode 100644 index 000000000..65ebbeb86 --- /dev/null +++ b/test/haproxy-simple/docker-compose.yaml @@ -0,0 +1,27 @@ +services: + haproxy: + image: haproxytech/haproxy-alpine:3.0 + ports: + - 80:80 + - 8443:8443 + volumes: + - ./conf/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg + - ./pki:/etc/techaro/pki:ro + - anubis-socket:/shared + + anubis: + image: ghcr.io/techarohq/anubis:main + env_file: ./anubis.env + user: root + volumes: + - anubis-socket:/shared + - ./conf/anubis:/cfg:ro + depends_on: + - httpdebug + + httpdebug: + image: ghcr.io/xe/x/httpdebug + pull_policy: always + +volumes: + anubis-socket: diff --git a/test/haproxy-simple/test.mjs b/test/haproxy-simple/test.mjs new file mode 100644 index 000000000..be41af1cd --- /dev/null +++ b/test/haproxy-simple/test.mjs @@ -0,0 +1,39 @@ +#!/usr/bin/env node + +async function main() { + console.log("Starting HAProxy simple smoke test..."); + + console.log("trying to hit backend through haproxy"); + let resp = await fetch( + "https://localhost:8443", + { + headers: { + "User-Agent": "Anubis testing", + } + } + ); + + if (resp.status !== 200) { + throw new Error(`Expected 200, got ${resp.status}`); + } + console.log("Got 200 as expected"); + + console.log("trying to get stopped by anubis"); + resp = await fetch( + "https://localhost:8443", + { + headers: { + "User-Agent": "Mozilla/5.0", + } + } + ); + + if (resp.status !== 401) { + throw new Error(`Expected 401, got ${resp.status}`); + } + console.log("Got 401 as expected"); + + console.log("All runtime tests passed successfully!"); +} + +await main(); diff --git a/test/haproxy-simple/test.sh b/test/haproxy-simple/test.sh new file mode 100755 index 000000000..ef716a4b8 --- /dev/null +++ b/test/haproxy-simple/test.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +source ../lib/lib.sh + +export KO_DOCKER_REPO=ko.local + +set -euo pipefail + +# Step 1: Config validation +mint_cert haproxy-simple.test + +# Combine cert and key for HAProxy SSL directory format +cat pki/haproxy-simple.test/cert.pem pki/haproxy-simple.test/key.pem >pki/haproxy-simple.test/haproxy.pem + +docker run --rm \ + -v $PWD/conf/haproxy:/usr/local/etc/haproxy:ro \ + -v $PWD/pki:/etc/techaro/pki:ro \ + haproxytech/haproxy-alpine:3.0 \ + haproxy -c -f /usr/local/etc/haproxy/haproxy.cfg + +# Step 2: Runtime testing +echo "Starting services..." +docker compose up -d + +sleep 5 + +echo "Services are healthy. Starting runtime tests..." +export NODE_TLS_REJECT_UNAUTHORIZED=0 +node test.mjs + +# Cleanup happens automatically via trap in lib.sh From c414ddd9dc45f5d81f3382b797bd441ab0cefbe0 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Sun, 15 Feb 2026 16:27:41 +0000 Subject: [PATCH 2/2] ci(smoke-tests): add smoke test for haproxy (simple) Signed-off-by: Xe Iaso --- .github/workflows/smoke-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index a7df66eed..da485accd 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -24,6 +24,7 @@ jobs: - i18n - log-file - nginx + - haproxy-simple - palemoon/amd64 #- palemoon/i386 - robots_txt