From 9fde61d8a1d9bc86457f3cdd48338fdd6a63169b Mon Sep 17 00:00:00 2001 From: Jonni Liljamo Date: Sat, 14 Sep 2024 11:38:40 +0300 Subject: [PATCH] feat: add proxy --- .sops.yaml | 7 + hosts/proxy/default.nix | 17 +++ secrets/proxy/secrets.yaml | 38 ++++++ systems/hosts/default.nix | 5 + systems/hosts/proxy/default.nix | 157 ++++++++++++++++++++++ systems/hosts/proxy/domainstobackends.map | 20 +++ systems/hosts/proxy/haproxy.conf | 127 +++++++++++++++++ 7 files changed, 371 insertions(+) create mode 100644 hosts/proxy/default.nix create mode 100644 secrets/proxy/secrets.yaml create mode 100644 systems/hosts/proxy/default.nix create mode 100644 systems/hosts/proxy/domainstobackends.map create mode 100644 systems/hosts/proxy/haproxy.conf diff --git a/.sops.yaml b/.sops.yaml index e38e016..b53aa36 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -9,6 +9,7 @@ keys: - &cloud age17cw2ynlaw0ruga0u5678vas50k7neevuufk7gsqn8y8673g0mu8szhx4lr - &dns age1m5ktjargxxu04dn9c2uhvaw79z74mxsc4vdrkalxjn4aa8c86plqg0hyyw - &metrics age1m8u3a7rzyx2n6zjxjnfkla34yk3v77egxzd3lv9umt69lsynlaqqqfpt05 + - &proxy age19pj62rpxdh90q7zjvld8u6a7207ar0vmkkp5757j29xvx5e0f5kqjc9y8a - &social age173lqcfnq2a3xwdjkdua6uqyskfhpdqp2lt4jskdkg3rfqv23vu2sgplq98 # VMs - &sqbuilds age1wgzza5upq4tcpanmx3p9tg9swltz58ycufcapq9s45wpq8mtvepsr0lnzk @@ -56,6 +57,12 @@ creation_rules: - *liljamo_gpg age: - *metrics + - path_regex: secrets/proxy/[^/]+\.yaml$ + key_groups: + - pgp: + - *liljamo_gpg + age: + - *proxy - path_regex: secrets/social/[^/]+\.yaml$ key_groups: - pgp: diff --git a/hosts/proxy/default.nix b/hosts/proxy/default.nix new file mode 100644 index 0000000..d840393 --- /dev/null +++ b/hosts/proxy/default.nix @@ -0,0 +1,17 @@ +{config, ...}: { + sops.secrets.rootPwd.neededForUsers = true; + sops.secrets.liljamoPwd.neededForUsers = true; + + roles.base = { + root.hashedPasswordFile = config.sops.secrets.rootPwd.path; + primaryUser = { + username = "liljamo"; + hashedPasswordFile = config.sops.secrets.liljamoPwd.path; + }; + }; + + roles.tailscale = { + enable = true; + enableSSH = true; + }; +} diff --git a/secrets/proxy/secrets.yaml b/secrets/proxy/secrets.yaml new file mode 100644 index 0000000..e81de55 --- /dev/null +++ b/secrets/proxy/secrets.yaml @@ -0,0 +1,38 @@ +rootPwd: ENC[AES256_GCM,data:qoKUOPPB4uuK8Wykn+OI+DZdFg/IQOO354MiQUzwWeP8FEGJzY75lHPOB/fGXq9OqjmAHoFQLRa8XjNaHmpGBQpU2v737z+w3I4fHLA4fBOtDykFTKqCXXL5yccj1LKRmZ+yewvU18LAag==,iv:XhFEFxYrhCXqb01xzIoPEYfhwcZaQ+TOABgpLh+kI4E=,tag:qZSp+UAlGaIWjR377nRJxA==,type:str] +liljamoPwd: ENC[AES256_GCM,data:xdTpyxoELOTVxSqkKiR62fVsykfhpKLAfBsJKzILkNbCiPLSHKpGl/VWO5+nxv+eM8UNIMSDjf5P55BRfKc+b/1IPrkY65Va33KIcJGlvE+e9wkCdDiBcCLj3v9+Q1kIjPtptsBMm1o1DQ==,iv:Ay0JWUBH+hrnSubaaJFlqvYYLz3+fAizaR92O2J1NBw=,tag:doaRHFx68JO5zEygrCyOAg==,type:str] +wg1PrivateKey: ENC[AES256_GCM,data:XdWjyy3yNkkY1prXmhQ+pJkMzl67HCvo0Niy8WhslsNVsykHOpz4FvgighI=,iv:TUYEu46Ee91V2Ahu+MM/li7q8Sl5yM0u2ZU9nasto2Q=,tag:ylpq8QHFjLuuwZ5Xp02DCg==,type:str] +wg1PresharedKey: ENC[AES256_GCM,data:Nj9sCxDahq6jOo3dMyWGWhebjL7dwqTrGhNG3dbNQJ+AJNhjvqrnbZMCSG0=,iv:s2GldprFLFP3A10X+q2KqHZhiUSLCoagDOcAbq6TXgM=,tag:MdrLpXu9aDfHwiFuZIU3JQ==,type:str] +wg0PrivateKey: ENC[AES256_GCM,data:0GXueiosfoS0MUVpvL7Pb3qXhVoLchC2ZgelQ64MRWnQhiawMZp3JJ24Elc=,iv:wwcbySleh/ST/Dm1qBYe9dHjC573LslkFdReyZj1K6w=,tag:d6c59m4QPBMlZtFP+toFAw==,type:str] +wg0PresharedKey: ENC[AES256_GCM,data:isNyNSjJwpvWpCBCE19PE+VL/pqD6K5ho5TPPNCEdizAjxBDBFdWUlRTnaY=,iv:twOcys1cliE5hV8cUGqYh+EPOOiyvmnsbKbsWUZgZsY=,tag:H5G9Rh+OI/SWSPoGLCEciQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age19pj62rpxdh90q7zjvld8u6a7207ar0vmkkp5757j29xvx5e0f5kqjc9y8a + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSeFlmb0hZUXZwRmxOWjk1 + RXJIc21NU1pkOGovWUNYb0NNVWFIdTB5RmlNCnpxaXgvc1R6UE1wMDhzUTNOQ3RT + bnlXVm1uTG1lNVdheFdudVpJVG1pamsKLS0tIGdzZHJpRFdNbUhMZGhIK2pIR3Vx + L1ZCL0FpRnh6d0VldjAvOTlLb0tjUXcKMrvDltAuOVNF7w4CDot4wuRsLzlsgoDG + DZj/utJB/2lbNn+1dlIcAGPG9QYR7peoI3vooer+FWA2bX2JvUnifA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-09-14T08:15:50Z" + mac: ENC[AES256_GCM,data:bCWFrubXi+p/p0QzCEUNANU2hdHpmAdvNafyWG7Gq8RBnMnArAIdLr+gicUy1f5FB32O5ffSh1wkBKJVjGVJoMOiusJhpJfvEC8apLY1ApB/6LqkDeqtyRlZOy+1AR5W2GUG0JFr9bYM4VLINPjsvLqcIlxzo1cYCYYJ/8cMyTc=,iv:Ffez5U/2pgpC1nFDI0Ouz5DZNQ+lytDlGOAnoRbGPtM=,tag:znUXYZxfbSzKHLREcvo1KA==,type:str] + pgp: + - created_at: "2024-09-14T08:14:09Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4D8ab0ENzkR4wSAQdA1sS3901oRw8Jo2D+4GZZ29Yh5cHf/unaqNfJiNjKUzww + pKVmg1Dk0lv5d2/Wj6Ary9clNgDjm51Wvpv6VPH6mKb1+foA5sWGLjPm2TsMcvNY + 1GYBCQIQ3GBTHpwAh7zCm5WIUKnR2aMJfGDdIJWXOpBPQmIVJh+yF2ZuDhenaeQO + vP8m+EUDb614T0T9AOydc11stN5iYn03Uy8NGl3Uki4kT3P+b6qFekALRA5j7Pvi + re4MhgzIxko= + =8jTR + -----END PGP MESSAGE----- + fp: 848EEBCEE9F0D29D25C321A658577946A65EB712 + unencrypted_suffix: _unencrypted + version: 3.8.1 diff --git a/systems/hosts/default.nix b/systems/hosts/default.nix index 1024e25..27cb327 100644 --- a/systems/hosts/default.nix +++ b/systems/hosts/default.nix @@ -42,6 +42,11 @@ profile = lxc; modules = []; }; + proxy = { + system = "x86_64-linux"; + profile = lxc; + modules = []; + }; social = { system = "x86_64-linux"; profile = lxc; diff --git a/systems/hosts/proxy/default.nix b/systems/hosts/proxy/default.nix new file mode 100644 index 0000000..a1b8e7c --- /dev/null +++ b/systems/hosts/proxy/default.nix @@ -0,0 +1,157 @@ +{ + config, + pkgs, + ... +}: let + promtailPort = 3100; +in { + sops.secrets.wg1PrivateKey = {}; + sops.secrets.wg1PresharedKey = {}; + sops.secrets.wg0PrivateKey = {}; + sops.secrets.wg0PresharedKey = {}; + + networking.firewall.interfaces."eth0".allowedTCPPorts = [443 promtailPort 8404]; + networking.firewall.interfaces."wg0".allowedTCPPorts = [80]; + networking.firewall.interfaces."wg1".allowedTCPPorts = [80 5522]; + # TODO: Remove wg1 + networking.wg-quick = { + interfaces.wg1 = { + privateKeyFile = config.sops.secrets.wg1PrivateKey.path; + address = ["192.168.2.10"]; + listenPort = 21841; + + peers = [ + { + publicKey = "uvdeJAsxUf/bEREwCaFDHg9rO1xxC3Wzu1d2x+WiNEQ="; + presharedKeyFile = config.sops.secrets.wg1PresharedKey.path; + endpoint = "140.238.216.88:51820"; + allowedIPs = ["192.168.2.0/24"]; + persistentKeepalive = 25; + } + ]; + }; + }; + networking.wireguard.interfaces."wg0" = { + ips = ["10.100.0.10/24"]; + listenPort = 51820; + + # pubKey pxbf41wTYSpBxTQW8ksQKNd7VOjTEUWKpW381qEnQyw= + privateKeyFile = config.sops.secrets.wg0PrivateKey.path; + + peers = [ + { + publicKey = "+HChRIruvl92cxk4Ztyut28T/m1ilEy3hqDd3HH6XRk="; + presharedKeyFile = config.sops.secrets.wg0PresharedKey.path; + allowedIPs = ["10.100.0.0/24"]; + endpoint = "172.234.96.20:51820"; + persistentKeepalive = 25; + } + ]; + }; + + systemd.services.caddy.path = [ + pkgs.nssTools + ]; + + environment.etc = { + "haproxy/domainstobackends.map" = { + text = builtins.readFile ./domainstobackends.map; + }; + }; + + services = { + haproxy = { + enable = true; + config = builtins.readFile ./haproxy.conf; + }; + caddy = { + enable = true; + #email = ""; + logFormat = "level ERROR"; + globalConfig = '' + http_port 8080 + https_port 8443 + ''; + virtualHosts = { + "dns.rustylily.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.2.3:80 + ''; + + "multi.media.rustylily.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.2.30:8096 + ''; + "books.media.rustylily.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.2.30:5000 + ''; + "nextcloud.rustylily.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.2.15:80 + ''; + + "metrics.rustylily.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.2.5:3000 + ''; + + "portainer.uwulpine.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.1.10:9080 + ''; + "registry.uwulpine.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.1.10:5000 + ''; + "registryui.uwulpine.home.arpa".extraConfig = '' + tls internal + reverse_proxy http://10.1.1.10:5080 + ''; + }; + }; + }; + + services.promtail = { + enable = true; + configuration = { + server = { + http_listen_port = promtailPort; + grpc_listen_port = 0; + }; + positions = { + filename = "/tmp/positions.yaml"; + }; + clients = [ + { + url = "http://10.1.2.5:9091/loki/api/v1/push"; + } + ]; + scrape_configs = [ + { + job_name = "journal"; + journal = { + max_age = "12h"; + labels = { + job = "systemd-journal"; + host = "lxcproxy"; + }; + }; + relabel_configs = [ + { + action = "keep"; + source_labels = ["__journal__systemd_unit"]; + regex = "haproxy.service"; + } + { + source_labels = ["__journal__systemd_unit"]; + target_label = "unit"; + } + ]; + } + ]; + }; + }; + + system.stateVersion = "23.05"; +} diff --git a/systems/hosts/proxy/domainstobackends.map b/systems/hosts/proxy/domainstobackends.map new file mode 100644 index 0000000..61d7733 --- /dev/null +++ b/systems/hosts/proxy/domainstobackends.map @@ -0,0 +1,20 @@ +auth.liljamo.com autheliamain +cloud.liljamo.com nextcloud +docs.liljamo.com outline +rss.liljamo.com miniflux + +liljamo.dev liljamodev +registry.liljamo.dev registry +umami.liljamo.dev umami + +lothlorien.social akkoma +media.lothlorien.social akkomamedia + +src.quest sourcequest +builds.src.quest sourcequest +git.src.quest sourcequest +lists.src.quest sourcequest +man.src.quest sourcequest +meta.src.quest sourcequest +paste.src.quest sourcequest +todo.src.quest sourcequest diff --git a/systems/hosts/proxy/haproxy.conf b/systems/hosts/proxy/haproxy.conf new file mode 100644 index 0000000..01a932c --- /dev/null +++ b/systems/hosts/proxy/haproxy.conf @@ -0,0 +1,127 @@ +global + log /dev/log local0 + daemon + maxconn 512 + +defaults + log global + mode http + option httplog + timeout connect 5s + timeout client 1m + timeout server 1m + +frontend stats + bind *:8404 + http-request capture req.fhdr(User-Agent) len 512 + log-format "client_ip=\"%ci\" client_port=\"%cp\" time=\"%t\" frontend_name=\"%f\" backend_name=\"%b\" request=\"%r\" request_headers=\"%hr\"" + + http-request use-service prometheus-exporter if { path /metrics } + stats enable + stats uri /stats + stats refresh 10s + +frontend http-in + bind 0.0.0.0:80 + http-request capture req.fhdr(User-Agent) len 512 + log-format "client_ip=\"%ci\" client_port=\"%cp\" time=\"%t\" frontend_name=\"%f\" backend_name=\"%b\" request=\"%r\" request_headers=\"%hr\"" + + acl host_media req.hdr(Host) media.liljamo.com + acl allow_media_metrics src 10.1.2.5 + acl media_metrics path_beg /metrics + http-request deny if media_metrics !allow_media_metrics + use_backend be_jellyfin if host_media + + acl host_liljamocom req.hdr(Host) liljamo.com + acl liljamocom_webfinger path_beg /.well-known/webfinger + acl liljamocom_matrix path_beg /_matrix + use_backend be_liljamocom_webfinger if host_liljamocom liljamocom_webfinger + use_backend be_liljamocom_matrix if host_liljamocom liljamocom_matrix + use_backend be_liljamocom if host_liljamocom + + acl host_alderaanfi req.hdr(Host) alderaan.fi + acl alderaanfi_matrix path_beg /_matrix + use_backend be_alderaan_matrix if host_alderaanfi alderaanfi_matrix + + use_backend be_%[req.hdr(Host),map(/etc/haproxy/domainstobackends.map,caddy-http)] + +frontend https-in + bind 0.0.0.0:443 + mode tcp + option tcplog + log-format "client_ip=\"%ci\" client_port=\"%cp\" time=\"%t\" frontend_name=\"%f\" backend_name=\"%b\" request_headers=\"%hr\"" + + default_backend be_caddy-https + +frontend sourcequest-ssh-in + bind 0.0.0.0:5522 + mode tcp + option tcplog + log-format "client_ip=\"%ci\" client_port=\"%cp\" time=\"%t\" frontend_name=\"%f\" backend_name=\"%b\" request_headers=\"%hr\"" + + use_backend be_ssh_sourcequest + +backend be_caddy-http + server caddy localhost:8080 + +backend be_caddy-https + mode tcp + server caddy localhost:8443 + +# liljamo.com +backend be_liljamocom + server liljamocom 10.1.1.10:8100 + +backend be_liljamocom_webfinger + server liljamocomwebfinger 10.1.2.12:80 + +backend be_liljamocom_matrix + server conduit 10.1.1.10:8448 + +backend be_autheliamain + server autheliamain 10.1.2.12:3001 + +backend be_outline + server outline 10.1.2.15:3000 + +backend be_miniflux + server miniflux 10.1.1.10:8600 + +backend be_nextcloud + server nextcloud 10.1.2.15:80 + +backend be_jellyfin + option httpchk + option forwardfor + http-check send meth GET uri /health + http-check expect string Healthy + server jellyfin 10.1.2.30:8096 + +# lothlorien.social +backend be_akkoma + server akkoma 10.1.2.17:4000 + +backend be_akkomamedia + server akkoma 10.1.2.17:4000 + +# liljamo.dev +backend be_liljamodev + server liljamodev 10.1.1.10:8110 + +backend be_registry + server registry 10.1.1.10:5000 + +backend be_umami + server umami 10.1.1.10:8700 + +# src.quest +backend be_sourcequest + server sourcequest 10.1.1.20:80 + +backend be_ssh_sourcequest + mode tcp + server sourcequest 10.1.1.20:22 + +# alderaan.fi +backend be_alderaan_matrix + server conduit 10.1.2.16:6167 -- 2.44.1