stura-infra/hosts/proxy/default.nix
2026-02-27 20:28:49 +01:00

251 lines
5.8 KiB
Nix

{
config,
lib,
pkgs,
...
}:
{
imports = [
./hardware-configuration.nix
./hetzner-disk.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 =
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.57";
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;
};
beach = {
dest = "141.56.51.51";
domain = "beach.htw.stura-dresden.de";
httpPort = 80;
httpsPort = 443;
};
studicloud = {
dest = "141.56.51.17";
domain = "dat.stu.htw.stura-dresden.de";
httpPort = 80;
httpsPort = 443;
};
};
indexPage = pkgs.writeTextFile {
name = "index.html";
text = ''
<html>
<head>
<title>
StuRa HTWD Index
</title>
</head>
<body>
<ul>
${lib.foldlAttrs (
prev: name: value:
prev
+ ''
<li><a href="https://${value.domain}">${name}</a></li>
''
) "" forwards}
</ul>
</body>
</html>
'';
};
in
{
openssh = {
enable = true;
listenAddresses = [
{
addr = "141.56.51.1";
port = 1005;
}
];
};
nginx = {
enable = true;
virtualHosts."localhost" = {
listen = [
{
addr = "127.0.0.1";
port = 6942;
}
];
locations."/" = {
extraConfig = ''
try_files ${indexPage} =404;
'';
};
};
};
haproxy = {
enable = true;
config = ''
global
log /dev/log format raw local0
maxconn 50000
#stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
tune.bufsize 32762
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 show-legends
stats show-node
stats show-modules
frontend http-in
bind *:80
${lib.foldlAttrs (
prev: name: value:
prev + "acl is_${name} hdr(host) -i ${value.domain}\n"
) "" forwards}
acl is_acme path_beg /.well-known/acme-challenge/
${lib.foldlAttrs (
prev: name: value:
prev + "use_backend ${name}_80 if is_${name}\n"
) "" forwards}
http-request redirect scheme https code 301 if !is_acme
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";
}