M .sops.yaml => .sops.yaml +7 -0
@@ 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:
A hosts/proxy/default.nix => hosts/proxy/default.nix +17 -0
@@ 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;
+ };
+}
A secrets/proxy/secrets.yaml => secrets/proxy/secrets.yaml +38 -0
@@ 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
M systems/hosts/default.nix => systems/hosts/default.nix +5 -0
@@ 42,6 42,11 @@
profile = lxc;
modules = [];
};
+ proxy = {
+ system = "x86_64-linux";
+ profile = lxc;
+ modules = [];
+ };
social = {
system = "x86_64-linux";
profile = lxc;
A systems/hosts/proxy/default.nix => systems/hosts/proxy/default.nix +157 -0
@@ 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";
+}
A systems/hosts/proxy/domainstobackends.map => systems/hosts/proxy/domainstobackends.map +20 -0
@@ 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
A systems/hosts/proxy/haproxy.conf => systems/hosts/proxy/haproxy.conf +127 -0
@@ 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