{ config, lib, pkgs, ... }: { imports = [ ./hardware-configuration.nix ]; networking = { hostName = "proxy"; interfaces.ens18.ipv4.addresses = [ { address = "141.56.51.1"; prefixLength = 24; } ]; defaultGateway.address = "141.56.51.254"; nameservers = [ "9.9.9.9" "1.1.1.1" ]; firewall = { allowedTCPPorts = [ 22 80 443 1005 2142 ]; }; nftables = { enable = true; }; }; services = { openssh = { enable = true; listenAddresses = [ { addr = "141.56.51.1"; port = 1005; } ]; }; haproxy = let forwards = { plone = { dest = "141.56.51.3"; domain = "stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; }; plone_alt = { dest = "141.56.51.3"; domain = "www.stura.htw-dresden.de"; httpPort = 80; httpsPort = 443; }; tix = { dest = "141.56.51.220"; domain = "tix.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; }; vot = { dest = "141.56.51.81"; domain = "vot.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; }; dat = { dest = "141.56.51.81"; domain = "dat.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; }; pro = { dest = "141.56.51.15"; domain = "pro.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; }; cloud = { dest = "141.56.51.16"; domain = "cloud.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; }; wiki = { dest = "141.56.51.13"; domain = "wiki.htw.stura-dresden.de"; httpPort = 80; httpsPort = 443; }; }; in{ enable = true; config = '' global log /dev/log local0 maxconn 4096 # for ACME/Let's Encrypt cert + key in one file: stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners crt-base /var/lib/acme defaults log global mode tcp option tcplog timeout connect 5s timeout client 30s timeout server 30s frontend stats bind 127.0.0.1:8404 mode http stats enable stats uri /stats stats refresh 10s stats auth admin:yourpassword stats show-legends stats show-node frontend http-in bind *:80 ${ lib.foldlAttrs(prev: name: value: prev + "acl is_${name} hdr(host) -i ${value.domain}\n" ) "" forwards } ${ lib.foldlAttrs(prev: name: value: prev + "use_backend ${name}_80 if is_${name}\n" ) "" forwards } default_backend plone_80 frontend ssh_jump_alt bind *:2142 mode tcp timeout client 30m log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq dst:%[var(sess.dst)] " use_backend ssh_srs2 # ---- SNI routing (TCP, peek at handshake) ---- frontend sni_router bind *:443 mode tcp tcp-request inspect-delay 1s tcp-request content accept if { req_ssl_hello_type 1 } # terminated here ${ lib.foldlAttrs(prev: name: value: prev + "use_backend ${name}_443 if { req_ssl_sni -i ${value.domain} }\n" ) "" forwards } backend ssh_srs2 mode tcp timeout server 30m timeout connect 10s option tcpka server srs2 141.56.51.2:80 check ${ lib.foldlAttrs(prev: name: value: prev + '' backend ${name}_80 mode http server ${name} ${value.dest}:${builtins.toString value.httpPort} backend ${name}_443 mode tcp server ${name} ${value.dest}:${builtins.toString value.httpsPort} check '' ) "" forwards } ''; }; }; environment.systemPackages = with pkgs; [ openvpn tcpdump ]; system.stateVersion = "25.11"; }