diff --git a/test/anubis_configs/less_paranoid.yaml b/test/anubis_configs/less_paranoid.yaml
new file mode 100644
index 00000000..22808b74
--- /dev/null
+++ b/test/anubis_configs/less_paranoid.yaml
@@ -0,0 +1,2 @@
+bots:
+- import: (data)/common/challenge-browser-like.yaml
\ No newline at end of file
diff --git a/test/apache/Dockerfile b/test/apache/Dockerfile
new file mode 100644
index 00000000..bfc9962f
--- /dev/null
+++ b/test/apache/Dockerfile
@@ -0,0 +1,15 @@
+FROM httpd:2.4
+
+RUN sed -i \
+ -e 's/^#\(LoadModule .*mod_ssl.so\)/\1/' \
+ -e 's/^#\(LoadModule .*mod_rewrite.so\)/\1/' \
+ -e 's/^#\(LoadModule .*mod_proxy.so\)/\1/' \
+ -e 's/^#\(LoadModule .*mod_proxy_http.so\)/\1/' \
+ -e 's/^#\(LoadModule .*mod_socache_shmcb.so\)/\1/' \
+ -e 's/^#\(LoadModule .*mod_http2.so\)/\1/' \
+ conf/httpd.conf
+RUN echo '' >> conf/httpd.conf \
+ && echo 'IncludeOptional conf.d/*.conf' >> conf/httpd.conf
+
+COPY conf.d ./conf.d
+COPY snippets /etc/httpd/snippets
\ No newline at end of file
diff --git a/test/apache/conf.d/http.conf b/test/apache/conf.d/http.conf
new file mode 100644
index 00000000..1afc4649
--- /dev/null
+++ b/test/apache/conf.d/http.conf
@@ -0,0 +1,15 @@
+
+ ServerAdmin your@email.here
+ ServerName httpd.local.cetacean.club
+ DocumentRoot /var/www/httpd.local.cetacean.club
+
+ Include /etc/httpd/snippets/proxy-headers.conf
+
+ ProxyPreserveHost On
+
+ ProxyRequests Off
+ ProxyVia Off
+
+ ProxyPass / http://httpdebug:3000/
+ ProxyPassReverse / http://httpdebug:3000/
+
\ No newline at end of file
diff --git a/test/apache/conf.d/https.conf b/test/apache/conf.d/https.conf
new file mode 100644
index 00000000..bd1893e0
--- /dev/null
+++ b/test/apache/conf.d/https.conf
@@ -0,0 +1,22 @@
+
+
+ ServerAdmin me@xeiaso.net
+ ServerName httpd.local.cetacean.club
+ DocumentRoot /var/www/httpd.local.cetacean.club
+ Protocols h2 http/1.1
+
+ SSLCertificateFile /etc/techaro/pki/httpd.local.cetacean.club/cert.pem
+ SSLCertificateKeyFile /etc/techaro/pki/httpd.local.cetacean.club/key.pem
+ Include /etc/httpd/snippets/options-ssl-apache.conf
+
+ Include /etc/httpd/snippets/proxy-headers.conf
+
+ ProxyPreserveHost On
+
+ ProxyRequests Off
+ ProxyVia Off
+
+ ProxyPass / http://anubis:3000
+ ProxyPassReverse / http://anubis:3000
+
+
\ No newline at end of file
diff --git a/test/apache/conf.d/listen-443-https.conf b/test/apache/conf.d/listen-443-https.conf
new file mode 100644
index 00000000..763e1fd0
--- /dev/null
+++ b/test/apache/conf.d/listen-443-https.conf
@@ -0,0 +1 @@
+Listen 443 https
\ No newline at end of file
diff --git a/test/apache/docker-compose.yaml b/test/apache/docker-compose.yaml
new file mode 100644
index 00000000..68b3193d
--- /dev/null
+++ b/test/apache/docker-compose.yaml
@@ -0,0 +1,23 @@
+services:
+ httpd:
+ image: xxxtest/httpd
+ build: .
+ volumes:
+ - "../shared/www:/var/www/httpd.local.cetacean.club"
+ - "../pki/httpd.local.cetacean.club:/etc/techaro/pki/httpd.local.cetacean.club/"
+ ports:
+ - 8080:80
+ - 8443:443
+
+ anubis:
+ image: git.xeserv.us/techaro/anubis:cel
+ environment:
+ BIND: ":3000"
+ TARGET: http://httpdebug:3000
+ POLICY_FNAME: /etc/techaro/anubis/less_paranoid.yaml
+ volumes:
+ - ../anubis_configs:/etc/techaro/anubis
+
+ httpdebug:
+ image: ghcr.io/xe/x/httpdebug
+ pull_policy: always
diff --git a/test/apache/snippets/options-ssl-apache.conf b/test/apache/snippets/options-ssl-apache.conf
new file mode 100644
index 00000000..91adbf43
--- /dev/null
+++ b/test/apache/snippets/options-ssl-apache.conf
@@ -0,0 +1,13 @@
+SSLEngine on
+
+# Intermediate configuration, tweak to your needs
+SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
+SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
+SSLHonorCipherOrder off
+SSLSessionTickets off
+
+SSLOptions +StrictRequire
+
+# Add vhost name to log entries:
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" vhost_combined
+LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common
\ No newline at end of file
diff --git a/test/apache/snippets/proxy-headers.conf b/test/apache/snippets/proxy-headers.conf
new file mode 100644
index 00000000..642cf100
--- /dev/null
+++ b/test/apache/snippets/proxy-headers.conf
@@ -0,0 +1,3 @@
+RequestHeader set "X-Real-Ip" expr=%{REMOTE_ADDR}
+RequestHeader set "X-Forwarded-Proto" "https"
+RequestHeader set "X-Http-Version" "%{SERVER_PROTOCOL}s"
\ No newline at end of file
diff --git a/test/apache/start.sh b/test/apache/start.sh
new file mode 100755
index 00000000..079df072
--- /dev/null
+++ b/test/apache/start.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# If the transient local TLS certificate doesn't exist, mint a new one
+if [ ! -f ../pki/httpd.local.cetacean.club/cert.pem ]; then
+ # Subshell to contain the directory change
+ (
+ cd ../pki \
+ && mkdir -p httpd.local.cetacean.club \
+ && \
+ # Try using https://github.com/FiloSottile/mkcert for better DevEx,
+ # but fall back to using https://github.com/jsha/minica in case
+ # you don't have that installed.
+ (
+ mkcert \
+ --cert-file ./httpd.local.cetacean.club/cert.pem \
+ --key-file ./httpd.local.cetacean.club/key.pem httpd.local.cetacean.club \
+ || go tool minica -domains httpd.local.cetacean.club
+ )
+ )
+fi
+
+docker compose up --build
\ No newline at end of file
diff --git a/test/caddy/Caddyfile b/test/caddy/Caddyfile
new file mode 100644
index 00000000..a80a93a6
--- /dev/null
+++ b/test/caddy/Caddyfile
@@ -0,0 +1,16 @@
+:80 {
+ reverse_proxy http://anubis:3000 {
+ header_up X-Real-Ip {remote_host}
+ header_up X-Http-Version {http.request.proto}
+ }
+}
+
+:443 {
+ tls /etc/techaro/pki/caddy.local.cetacean.club/cert.pem /etc/techaro/pki/caddy.local.cetacean.club/key.pem
+
+ reverse_proxy http://anubis:3000 {
+ header_up X-Real-Ip {remote_host}
+ header_up X-Http-Version {http.request.proto}
+ header_up X-Tls-Version {http.request.tls.version}
+ }
+}
diff --git a/test/caddy/Dockerfile b/test/caddy/Dockerfile
new file mode 100644
index 00000000..d4c2d15a
--- /dev/null
+++ b/test/caddy/Dockerfile
@@ -0,0 +1,9 @@
+# FROM caddy:2.10.0-builder AS builder
+
+# RUN xcaddy build \
+# --with github.com/lolPants/caddy-requestid
+
+FROM caddy:2.10.0 AS run
+
+# COPY --from=builder /usr/bin/caddy /usr/bin/caddy
+COPY Caddyfile /etc/caddy/Caddyfile
\ No newline at end of file
diff --git a/test/caddy/docker-compose.yaml b/test/caddy/docker-compose.yaml
new file mode 100644
index 00000000..742c8530
--- /dev/null
+++ b/test/caddy/docker-compose.yaml
@@ -0,0 +1,22 @@
+services:
+ caddy:
+ image: xxxtest/caddy
+ build: .
+ ports:
+ - 8080:80
+ - 8443:443
+ volumes:
+ - "../pki/caddy.local.cetacean.club:/etc/techaro/pki/caddy.local.cetacean.club/"
+
+ anubis:
+ image: git.xeserv.us/techaro/anubis:cel
+ environment:
+ BIND: ":3000"
+ TARGET: http://httpdebug:3000
+ POLICY_FNAME: /etc/techaro/anubis/less_paranoid.yaml
+ volumes:
+ - ../anubis_configs:/etc/techaro/anubis
+
+ httpdebug:
+ image: ghcr.io/xe/x/httpdebug
+ pull_policy: always
diff --git a/test/caddy/start.sh b/test/caddy/start.sh
new file mode 100755
index 00000000..7e617e20
--- /dev/null
+++ b/test/caddy/start.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# If the transient local TLS certificate doesn't exist, mint a new one
+if [ ! -f ../pki/caddy.local.cetacean.club/cert.pem ]; then
+ # Subshell to contain the directory change
+ (
+ cd ../pki \
+ && mkdir -p caddy.local.cetacean.club \
+ && \
+ # Try using https://github.com/FiloSottile/mkcert for better DevEx,
+ # but fall back to using https://github.com/jsha/minica in case
+ # you don't have that installed.
+ (
+ mkcert \
+ --cert-file ./caddy.local.cetacean.club/cert.pem \
+ --key-file ./caddy.local.cetacean.club/key.pem caddy.local.cetacean.club \
+ || go tool minica -domains caddy.local.cetacean.club
+ )
+ )
+fi
+
+docker compose up --build
\ No newline at end of file
diff --git a/test/nginx/Dockerfile b/test/nginx/Dockerfile
new file mode 100644
index 00000000..aac5e74c
--- /dev/null
+++ b/test/nginx/Dockerfile
@@ -0,0 +1,4 @@
+FROM nginx
+
+COPY conf.d/ /etc/nginx/conf.d/
+COPY snippets /etc/nginx/snippets
\ No newline at end of file
diff --git a/test/nginx/conf.d/http.conf b/test/nginx/conf.d/http.conf
new file mode 100644
index 00000000..da828568
--- /dev/null
+++ b/test/nginx/conf.d/http.conf
@@ -0,0 +1,10 @@
+server {
+ listen 80;
+ listen [::]:80;
+ server_name nginx.local.cetacean.club;
+
+ location / {
+ proxy_pass http://anubis:3000;
+ include snippets/proxy_params;
+ }
+}
\ No newline at end of file
diff --git a/test/nginx/conf.d/https.conf b/test/nginx/conf.d/https.conf
new file mode 100644
index 00000000..0f0a3c50
--- /dev/null
+++ b/test/nginx/conf.d/https.conf
@@ -0,0 +1,14 @@
+server {
+ listen 443 ssl http2;
+ listen [::]:443 ssl http2;
+ server_name nginx.local.cetacean.club;
+
+ ssl_certificate /etc/techaro/pki/nginx.local.cetacean.club/cert.pem;
+ ssl_certificate_key /etc/techaro/pki/nginx.local.cetacean.club/key.pem;
+ include snippets/ssl_params;
+
+ location / {
+ proxy_pass http://anubis:3000;
+ include snippets/proxy_params;
+ }
+}
\ No newline at end of file
diff --git a/test/nginx/docker-compose.yaml b/test/nginx/docker-compose.yaml
new file mode 100644
index 00000000..a7476b81
--- /dev/null
+++ b/test/nginx/docker-compose.yaml
@@ -0,0 +1,22 @@
+services:
+ httpd:
+ image: xxxtest/nginx
+ build: .
+ volumes:
+ - "../pki/nginx.local.cetacean.club:/etc/techaro/pki/nginx.local.cetacean.club/"
+ ports:
+ - 8080:80
+ - 8443:443
+
+ anubis:
+ image: git.xeserv.us/techaro/anubis:cel
+ environment:
+ BIND: ":3000"
+ TARGET: http://httpdebug:3000
+ POLICY_FNAME: /etc/techaro/anubis/less_paranoid.yaml
+ volumes:
+ - ../anubis_configs:/etc/techaro/anubis
+
+ httpdebug:
+ image: ghcr.io/xe/x/httpdebug
+ pull_policy: always
diff --git a/test/nginx/snippets/proxy_params b/test/nginx/snippets/proxy_params
new file mode 100644
index 00000000..000af313
--- /dev/null
+++ b/test/nginx/snippets/proxy_params
@@ -0,0 +1,7 @@
+proxy_set_header Host $host;
+proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+proxy_set_header X-Http-Version $server_protocol;
+proxy_set_header X-Real-IP $remote_addr;
+proxy_set_header X-Forwarded-Proto $scheme;
+proxy_set_header X-Request-Id $request_id;
+proxy_set_header X-Forwarded-Host $host;
\ No newline at end of file
diff --git a/test/nginx/snippets/ssl_params b/test/nginx/snippets/ssl_params
new file mode 100644
index 00000000..d73579fb
--- /dev/null
+++ b/test/nginx/snippets/ssl_params
@@ -0,0 +1,11 @@
+ssl_protocols TLSv1.3;
+ssl_prefer_server_ciphers on;
+ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
+ssl_ecdh_curve secp384r1;
+ssl_session_timeout 10m;
+ssl_session_cache shared:SSL:10m;
+ssl_session_tickets off;
+ssl_stapling on;
+ssl_stapling_verify on;
+resolver 8.8.8.8 8.8.4.4 valid=300s;
+resolver_timeout 5s;
\ No newline at end of file
diff --git a/test/nginx/start.sh b/test/nginx/start.sh
new file mode 100755
index 00000000..72878d12
--- /dev/null
+++ b/test/nginx/start.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+# If the transient local TLS certificate doesn't exist, mint a new one
+if [ ! -f ../pki/nginx.local.cetacean.club/cert.pem ]; then
+ # Subshell to contain the directory change
+ (
+ cd ../pki \
+ && mkdir -p nginx.local.cetacean.club \
+ && \
+ # Try using https://github.com/FiloSottile/mkcert for better DevEx,
+ # but fall back to using https://github.com/jsha/minica in case
+ # you don't have that installed.
+ (
+ mkcert \
+ --cert-file ./nginx.local.cetacean.club/cert.pem \
+ --key-file ./nginx.local.cetacean.club/key.pem nginx.local.cetacean.club \
+ || go tool minica -domains nginx.local.cetacean.club
+ )
+ )
+fi
+
+docker compose up --build
\ No newline at end of file