diff --git a/hosts/tsuki/services/nginx/default.nix b/hosts/tsuki/services/nginx/default.nix new file mode 100644 index 0000000..5e510e0 --- /dev/null +++ b/hosts/tsuki/services/nginx/default.nix @@ -0,0 +1,154 @@ +{ pkgs, config, secrets, inputs, ... }: + let + # TODO: fix lib + lib = pkgs.lib; + + inherit (secrets) ips ports; + in +{ + + # All of these nginx endpoints are hosted through a cloudflare proxy. + # This has several implications for the configuration: + # - The sites I want to protect using a client side certificate needs to + # use a client side certificate given by cloudflare, since the client cert set here + # only works to secure communication between nginx and cloudflare + # - I don't need to redirect http traffic to https manually, as cloudflare does it for me + # - I don't need to request ACME certificates manually, as cloudflare does it for me. + + services.nginx = let + generateServerAliases = + domains: subdomains: + lib.lists.flatten (map (s: map (d: "${s}.${d}") domains) subdomains); + + s = toString; + in { + enable = true; + enableReload = true; + + statusPage = true; + + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + + virtualHosts = let + inherit (lib.attrsets) nameValuePair listToAttrs recursiveUpdate; + inherit (lib.lists) head drop; + inherit (secrets) domains keys; + + cloudflare-origin-pull-ca = builtins.fetchurl { + url = "https://developers.cloudflare.com/ssl/static/authenticated_origin_pull_ca.pem"; + sha256 = "0hxqszqfzsbmgksfm6k0gp0hsx9k1gqx24gakxqv0391wl6fsky1"; + }; + + host = + subdomains: extraSettings: let + settings = with keys.certificates; { + serverAliases = drop 1 (generateServerAliases domains subdomains); + onlySSL = true; + sslCertificate = server.crt; + sslCertificateKey = server.key; + + extraConfig = '' + ssl_client_certificate ${cloudflare-origin-pull-ca}; + ssl_verify_client on; + ''; + }; + in + nameValuePair "${head subdomains}.${head domains}" (recursiveUpdate settings extraSettings); + + proxy = + subdomains: url: extraSettings: + host subdomains (recursiveUpdate { locations."/".proxyPass = url; } extraSettings); + + in (listToAttrs [ + { + name = "nani.wtf"; + value = { + locations = { + "/.well-known/".alias = "${./well-known}/"; + "/.well-known/openpgpkey/hu/" = { + alias = "${./well-known/openpgpkey/hu}/"; + extraConfig = '' + default_type application/octet-stream; + ''; + }; + }; + + onlySSL = true; + + sslCertificate = keys.certificates.server.crt; + sslCertificateKey = keys.certificates.server.key; + + extraConfig = '' + ssl_client_certificate ${cloudflare-origin-pull-ca}; + ssl_verify_client on; + add_header Access-Control-Allow-Origin *; + default_type text/plain; + ''; + }; + } + (proxy ["plex"] "http://localhost:${s ports.plex}" {}) + (host ["www"] { root = "${inputs.website.defaultPackage.${pkgs.system}}/"; }) + (proxy ["matrix"] "http://localhost:${s ports.matrix.listener}" {}) + (host ["madmin"] { root = "${pkgs.synapse-admin}/"; }) + (host ["cache"] { root = "/var/lib/nix-cache"; }) + (proxy ["git"] "http://localhost:${s ports.gitea}" {}) + (proxy ["px1"] "https://${ips.px1}:${s ports.proxmox}" { + locations."/".proxyWebsockets = true; + }) + (proxy ["idrac"] "https://${ips.idrac}" {}) + (proxy ["searx"] "http://localhost:${s ports.searx}" {}) + (proxy ["dyn"] "http://${ips.crafty}:${s ports.dynmap}" { + # basicAuthFile = keys.htpasswds.default; + }) + (proxy ["log"] "http://localhost:${s ports.grafana}" { + locations."/".proxyWebsockets = true; + }) + (proxy ["pg"] "http://localhost:${s ports.pgadmin}" {}) + # (host ["vpn"] "" {}) + (proxy ["hydra"] "http://localhost:${s ports.hydra}" {}) + (proxy ["air"] "https://${ips.kansei}:${s ports.kansei}" {}) + + # (proxy ["sync" "drive"] "" {}) + # (proxy ["music" "mpd"] "" {}) + ]) // { + # Disabled for time being + # ${config.services.jitsi-meet.hostName} = { + # enableACME = true; + # forceSSL = true; + # }; + }; + + upstreams = {}; + + streamConfig = '' + upstream minecraft { + server ${ips.crafty}:${s ports.minecraft}; + } + + server { + listen 0.0.0.0:${s ports.minecraft}; + listen [::0]:${s ports.minecraft}; + proxy_pass minecraft; + } + ''; + # upstream openvpn { + # server localhost:${s ports.openvpn}; + # } + + # server { + # listen 0.0.0.0:${s ports.openvpn}; + # listen [::0]:${s ports.openvpn}; + # proxy_pass openvpn; + # } + }; + + networking.firewall.allowedTCPPorts = [ + 80 + 443 + # secrets.ports.openvpn + ports.minecraft + ]; +} diff --git a/hosts/tsuki/services/nginx/well-known/keybase.txt b/hosts/tsuki/services/nginx/well-known/keybase.txt new file mode 100644 index 0000000..7c9f6ba --- /dev/null +++ b/hosts/tsuki/services/nginx/well-known/keybase.txt @@ -0,0 +1,56 @@ +================================================================== +https://keybase.io/h7x4 +-------------------------------------------------------------------- + +I hereby claim: + + * I am an admin of https://nani.wtf + * I am h7x4 (https://keybase.io/h7x4) on keybase. + * I have a public key ASBBMSnXp8vf1AF8SeYrJM2RzWLs2O8L04B9b6ZnIFzcVAo + +To do so, I am signing this object: + +{ + "body": { + "key": { + "eldest_kid": "0120413129d7a7cbdfd4017c49e62b24cd91cd62ecd8ef0bd3807d6fa667205cdc540a", + "host": "keybase.io", + "kid": "0120413129d7a7cbdfd4017c49e62b24cd91cd62ecd8ef0bd3807d6fa667205cdc540a", + "uid": "2babc56f964d025472c1fd3b17797f19", + "username": "h7x4" + }, + "merkle_root": { + "ctime": 1665673950, + "hash": "c30191d602dd4c4398baa0fc27df683da11d66cf929831f529c1832e0447430e1eb39251a62dfbc384ae1136d9524b953e805727eaa9a02e5dd0fc7044c9585f", + "hash_meta": "921bb14b4294b8b4b0b02ee477b705a8f3c04cab6c8fe7bc0ed5123fbdcad88e", + "seqno": 23362018 + }, + "service": { + "entropy": "wJLA9sRUHzPa6ElFEAnNZS1r", + "hostname": "nani.wtf", + "protocol": "https:" + }, + "type": "web_service_binding", + "version": 2 + }, + "client": { + "name": "keybase.io go client", + "version": "6.0.1" + }, + "ctime": 1665674008, + "expire_in": 504576000, + "prev": "4fd3a7f075610e1c7e0618dd4f96ba8e4bc2b6b81a8af58f80ab2f29b93d4794", + "seqno": 6, + "tag": "signature" +} + +which yields the signature: + +hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgQTEp16fL39QBfEnmKyTNkc1i7NjvC9OAfW+mZyBc3FQKp3BheWxvYWTESpcCBsQgT9On8HVhDhx+BhjdT5a6jkvCtrgaivWPgKsvKbk9R5TEIBXMUT8iq+cGZ4AJrwj9JxtSFFe/n2xYNktUj0c8sKeLAgHCo3NpZ8RA0SD45xOcGUZc7sfdpH4aXbMMvdYN+BybprXp1MBthURIaW4x15omCwFgN56cG7hKVRx1S00Dgc4k31g8Dm5WD6hzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEIKpqM0TI6eMUtwHMKVzgK5Dx8LGLBDMip+KCHfTTE3F0o3RhZ80CAqd2ZXJzaW9uAQ== + +And finally, I am proving ownership of this host by posting or +appending to this document. + +View my publicly-auditable identity here: https://keybase.io/h7x4 + +================================================================== diff --git a/hosts/tsuki/services/nginx/well-known/matrix/server b/hosts/tsuki/services/nginx/well-known/matrix/server new file mode 100644 index 0000000..1cb220f --- /dev/null +++ b/hosts/tsuki/services/nginx/well-known/matrix/server @@ -0,0 +1 @@ +{"m.server": "matrix.nani.wtf:443"} diff --git a/hosts/tsuki/services/nginx/well-known/openpgpkey/hu/o51os3b94w9rd8pwh986hxu56icaqq65 b/hosts/tsuki/services/nginx/well-known/openpgpkey/hu/o51os3b94w9rd8pwh986hxu56icaqq65 new file mode 100644 index 0000000..4b454d9 Binary files /dev/null and b/hosts/tsuki/services/nginx/well-known/openpgpkey/hu/o51os3b94w9rd8pwh986hxu56icaqq65 differ diff --git a/hosts/tsuki/services/nginx/well-known/openpgpkey/policy b/hosts/tsuki/services/nginx/well-known/openpgpkey/policy new file mode 100644 index 0000000..e69de29 diff --git a/hosts/tsuki/services/nginx/well-known/security.txt b/hosts/tsuki/services/nginx/well-known/security.txt new file mode 100644 index 0000000..6eb9524 --- /dev/null +++ b/hosts/tsuki/services/nginx/well-known/security.txt @@ -0,0 +1,15 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA512 + +Contact: mailto:fixplz@nani.wtf +Expires: 2025-10-12T22:00:00.000Z +Encryption: https://nani.wtf/.well-known/openpgpkey/hu/o51os3b94w9rd8pwh986hxu56icaqq65 +Preferred-Languages: en,no +Canonical: https://nani.wtf/.well-known/security.txt +-----BEGIN PGP SIGNATURE----- + +iHUEARYKAB0WIQTzzahsxVqfENegaYGfL32CUPNRRgUCY0iFxwAKCRCfL32CUPNR +Rqc3AQDSncBCpI8PKxneo5mp76APB86xYliZkKDRfwdrm1ClTQEA3arl1+UYg2Ry +XQSn2NLaJ7sdZkicZB2ChB6gvD2NeAw= +=5dxn +-----END PGP SIGNATURE-----