Sister to s8n/production-deb. Edge-box config + provision script for
running the OpenBSD-edge role per s8n/production-setup-audit Topology 02.
v0.1 = stock OpenBSD install ISO (interactive, 5 min) + scripted provision
from onyx. Autoinstall ISO build deferred to v0.2.
Layout:
README.md workflow + service mapping (Debian → OpenBSD)
flash.sh burn stock install76.iso to USB
etc/ pf / relayd / acme-client / unbound /
hostname.wg0.example / sshd_config / doas.conf
scripts/
provision.sh from onyx: SSH+git clone+run install.sh
install.sh on edge: copy /etc/*, validate, restart, cron
cert-renew-check.sh weekly LE renewal
read-logs.sh pull /var/log/* for offline diagnostics
docs/
setup-checklist.md 7-phase first-time install walkthrough
Hardware target: Dell Precision T5600 per
s8n/production-setup-audit/hardware/dell-t5600.md
WG mesh: 10.10.10.0/29 between edge (.1) and nullstone (.2). UDP 51820.
Keys generated per-host (NEVER committed to repo).
Public traffic flow after migration:
Internet → router → edge T5600 (relayd TLS term) → wg0 →
nullstone Traefik (10.10.10.2:8443, private only)
CVE delta vs single-host Debian: regreSSHion + xz backdoor mitigated;
public IP runs OpenBSD base only — no systemd, no glibc, no Docker.
63 lines
2.1 KiB
Text
63 lines
2.1 KiB
Text
# /etc/relayd.conf — TLS terminator + reverse proxy to nullstone backend
|
|
#
|
|
# Listens on egress IP for 80 (redirect to https) + 443 (TLS termination)
|
|
# Forwards decrypted requests to nullstone's WG IP on configured backend ports.
|
|
#
|
|
# Reload: rcctl reload relayd
|
|
# Test config: relayd -n
|
|
|
|
# === Macros ===
|
|
ext_addr = "egress:0"
|
|
backend = "10.10.10.2" # nullstone over wg0
|
|
backend_port = "8443" # nullstone Traefik listens on this internal port
|
|
|
|
# === Logging ===
|
|
log connection
|
|
log state changes
|
|
|
|
# === Tables ===
|
|
table <backend> { $backend }
|
|
|
|
# === HTTP → HTTPS redirect ===
|
|
http protocol "http_redirect" {
|
|
return error
|
|
match request header set "Strict-Transport-Security" \
|
|
value "max-age=31536000; includeSubDomains"
|
|
block
|
|
pass quick path "/.well-known/acme-challenge/*" forward to <acme-server>
|
|
}
|
|
|
|
# === HTTPS terminator ===
|
|
http protocol "https_term" {
|
|
return error
|
|
match request header set "X-Forwarded-For" value "$REMOTE_ADDR"
|
|
match request header set "X-Forwarded-Proto" value "https"
|
|
match request header set "X-Forwarded-Port" value "443"
|
|
match response header set "Strict-Transport-Security" \
|
|
value "max-age=31536000; includeSubDomains"
|
|
match response header set "X-Frame-Options" value "DENY"
|
|
match response header set "X-Content-Type-Options" value "nosniff"
|
|
match response header set "Referrer-Policy" value "strict-origin-when-cross-origin"
|
|
match response header remove "Server"
|
|
tls keypair s8n.ru
|
|
tls keypair veilor.uk
|
|
pass
|
|
}
|
|
|
|
# === acme-client target (port 80 only, for HTTP-01 challenge if you ever need it;
|
|
# DNS-01 challenge via Gandi is the primary path so this is a fallback) ===
|
|
table <acme-server> { 127.0.0.1 }
|
|
|
|
# === Relay: HTTP redirect on 80 ===
|
|
relay www_http {
|
|
listen on $ext_addr port 80
|
|
protocol "http_redirect"
|
|
forward to <acme-server> port 8081 check tcp
|
|
}
|
|
|
|
# === Relay: HTTPS terminator forwarding to nullstone ===
|
|
relay www_https {
|
|
listen on $ext_addr port 443 tls
|
|
protocol "https_term"
|
|
forward to <backend> port $backend_port check http "/" code 200
|
|
}
|