koyomi/haproxy: Init

This commit is contained in:
Simon Bruder 2024-05-18 15:24:41 +02:00
parent 11462ce843
commit b418a56e09
Signed by: simon
GPG key ID: 347FF8699CDA0776
4 changed files with 148 additions and 2 deletions

View file

@ -2,14 +2,13 @@
# #
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
{ config, lib, pkgs, ... }:
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
../../modules ../../modules
./services/hypervisor.nix ./services/hypervisor.nix
./services/haproxy.nix
]; ];
sbruder = { sbruder = {

View file

@ -0,0 +1,111 @@
# SPDX-FileCopyrightText: 2024 Simon Bruder <simon@sbruder.de>
#
# SPDX-License-Identifier: AGPL-3.0-or-later
{ config, lib, pkgs, ... }:
let
baseDomain = "koyomi.sbruder.de";
backends = { };
fallbackCert = pkgs.runCommandNoCC "fallback-cert" { } ''
cat > openssl.cnf << EOF
[ ca ]
default_ca = CA_default
[ CA_default ]
database = database
new_certs_dir = .
serial = serial
default_md = default
policy = policy_default
[ policy_default ]
EOF
echo 01 > serial
touch database
${pkgs.openssl}/bin/openssl genpkey -algorithm ec -pkeyopt ec_paramgen_curve:P-256 -out fallback.key
${pkgs.openssl}/bin/openssl req -key fallback.key -new -out fallback.csr -subj "/"
${pkgs.openssl}/bin/openssl ca -batch -config openssl.cnf -in fallback.csr -keyfile fallback.key -selfsign -out fallback.crt -startdate 19700101000000Z -enddate 20380119031407Z
mkdir $out
cat fallback.{key,crt} > $out/full.pem
mv fallback.{crt,key} $out
'';
in
{
services.haproxy = {
enable = true;
config = ''
global
stats socket /var/run/haproxy/haproxy-admin.sock mode 600 level admin
stats timeout 2m
defaults
timeout client 30s
timeout server 30s
timeout connect 30s
resolvers system
parse-resolv-conf
frontend http-in
bind :80
mode http
${lib.concatStrings (lib.mapAttrsToList (name: domains: ''
use_backend http-${name} if { hdr(Host) -i ${lib.concatStringsSep " " domains} and path_beg '/.well-known/acme-challenge/' }
'') backends)}
default_backend https-redirect
frontend https-in
bind :443
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req.ssl_hello_type 1 }
tcp-request content reject if WAIT_END
${lib.concatStrings (lib.mapAttrsToList (name: domains: ''
use_backend https-${name} if { req.ssl_sni -i ${lib.concatStringsSep " " domains} }
'') backends)}
default_backend https-fallback
frontend v6-in
bind [::]:80
bind [::]:443 ssl crt ${fallbackCert}/full.pem
mode http
http-request return status 400 content-type text/html string "<html><body><h1>400 Bad Request</h1>For requests over IPv6, please use the address of the virtual machine directly.</body></html>"
frontend fallback
bind /var/run/haproxy/fallback.sock ssl crt ${fallbackCert}/full.pem
mode http
frontend stats
bind ${config.sbruder.wireguard.home.address}:8404
mode http
http-request use-service prometheus-exporter if { path /metrics }
stats enable
stats uri /stats
stats refresh 10s
backend https-redirect
mode http
http-request redirect scheme https
backend https-fallback
server fallback /var/run/haproxy/fallback.sock
${lib.concatStrings (lib.mapAttrsToList (name: domains: ''
backend http-${name}
mode http
server ${name} ${name}.${baseDomain}:80 resolvers system resolve-prefer ipv4 send-proxy-v2
'') backends)}
${lib.concatStrings (lib.mapAttrsToList (name: domains: ''
backend https-${name}
mode tcp
server ${name} ${name}.${baseDomain}:443 resolvers system resolve-prefer ipv4 send-proxy-v2
'') backends)}
'';
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
}

View file

@ -188,6 +188,17 @@ in
} }
]; ];
} }
{
job_name = "haproxy";
static_configs = mkStaticTargets [
"koyomi.vpn.sbruder.de:8404"
];
relabel_configs = lib.singleton {
target_label = "instance";
source_labels = lib.singleton "__address__";
regex = "(.*)\\.vpn\\.sbruder\\.de:8404";
};
}
]; ];
rules = rules =

View file

@ -11,6 +11,14 @@ in
hardening.enable = lib.mkEnableOption "nginx hardening"; hardening.enable = lib.mkEnableOption "nginx hardening";
privacy.enable = (lib.mkEnableOption "nginx privacy options") // { default = true; }; privacy.enable = (lib.mkEnableOption "nginx privacy options") // { default = true; };
recommended.enable = (lib.mkEnableOption "recommended options") // { default = true; }; recommended.enable = (lib.mkEnableOption "recommended options") // { default = true; };
proxyv4 = {
enable = (lib.mkEnableOption "PROXY protocol for IPv4 connections");
trustedAddresses = (lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "Trusted addresses which can override the source address";
default = [ "10.0.0.0/8" "127.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" ];
});
};
}; };
config = lib.mkMerge [ config = lib.mkMerge [
@ -39,5 +47,22 @@ in
recommendedTlsSettings = lib.mkDefault true; recommendedTlsSettings = lib.mkDefault true;
}; };
}) })
(lib.mkIf cfg.proxyv4.enable {
services.nginx = {
commonHttpConfig = (lib.concatMapStrings
(address: ''
set_real_ip_from ${address};
'')
cfg.proxyv4.trustedAddresses) + ''
real_ip_header proxy_protocol;
'';
defaultListen = [
{ addr = "[::]"; port = 80; ssl = false; }
{ addr = "0.0.0.0"; port = 80; proxyProtocol = true; ssl = false; }
{ addr = "[::]"; port = 443; ssl = true; }
{ addr = "0.0.0.0"; port = 443; proxyProtocol = true; ssl = true; }
];
};
})
]; ];
} }