From 6513755670892983db88a6633b8c1ea6019c03d1 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Fri, 15 Nov 2024 14:55:37 -0500 Subject: Re-namespace some stuff to Omni I was getting confused about what is a product and what is internal infrastructure; I think it is good to keep those things separate. So I moved a bunch of stuff to an Omni namespace, actually most stuff went there. Only things that are explicitly external products are still in the Biz namespace. --- Omni/Cloud/Web.nix | 303 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 Omni/Cloud/Web.nix (limited to 'Omni/Cloud/Web.nix') diff --git a/Omni/Cloud/Web.nix b/Omni/Cloud/Web.nix new file mode 100644 index 0000000..0e080f5 --- /dev/null +++ b/Omni/Cloud/Web.nix @@ -0,0 +1,303 @@ +{ config, ... }: + +let + rootDomain = config.networking.domain; + ports = import ./Ports.nix; +in { + imports = [ ./Gmnisrv.nix ]; + networking.firewall = { + allowedTCPPorts = [ + ports.ssh + ports.git + ports.http + ports.https + ports.sabten + ports.gemini + ports.radicale + ports.znc + ports.gerrit-ssh + ]; + }; + + services = { + + libreddit = { + enable = true; + address = "127.0.0.1"; + openFirewall = true; + port = ports.libreddit; + }; + + invidious = { + enable = true; + database.createLocally = true; + domain = "youtube.${rootDomain}"; + nginx.enable = false; # do this myself, below + port = ports.invidious; + }; + + radicale = { + enable = true; + rights = { + # Allow reading root collection for authenticated users + root = { + user = ".+"; + collection = ""; + permissions = "R"; + }; + # Allow reading and writing principal collection (same as username) + principal = { + user = ".+"; + collection = "{user}"; + permissions = "RW"; + }; + # Allow reading and writing calendars and address books that are direct + # children of the principal collection + calendars = { + user = ".+"; + collection = "{user}/[^/]+"; + permissions = "rw"; + }; + # Allow any authenticated user to modify the public collection + public = { + user = ".*"; + collection = "public/.*"; + permissions = "rw"; + }; + }; + settings = { + server = { + hosts = [ + "0.0.0.0:${toString ports.radicale}" + "[::]:${toString ports.radicale}" + ]; + }; + auth = { + type = "htpasswd"; + htpasswd_filename = "/etc/radicale/users"; + htpasswd_encryption = "plain"; + }; + }; + }; + + gmnisrv = { + enable = false; + listen = "0.0.0.0:${toString ports.gemini} [::]:${toString ports.gemini}"; + settings = { + ":tls" = { store = "/var/lib/gmnisrv"; }; + "bsima.me" = { "root" = "/var/web/ben"; }; + "${rootDomain}" = { + "root" = "/var/web/simatime.com"; + "cgi" = "on"; + }; + }; + }; + + nginx = { + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + statusPage = true; + + user = "nginx"; + group = "nginx"; + + virtualHosts = { + ${rootDomain} = { + forceSSL = true; + enableACME = true; + locations = { + # the nginx/cgit module puts a '/' at the end of 'location', so we need to + # redirect '/git' to '/git/' + "/git".return = "301 https://$host/git/"; + # nostr nip-5 verification + "/.well-known/nostr.json".return = "200 '${ + builtins.toJSON { + names.bensima = + "2fa4b9ba71b6dab17c4723745bb7850dfdafcb6ae1a8642f76f9c64fa5f43436"; + } + }'"; + # disabled for nixpert test + "/" = { + root = "/var/web/simatime.com"; + extraConfig = '' + autoindex on; + ''; + }; + # serve /~$USER paths + "~ ^/~(.+?)(/.*)?$" = { + alias = "/var/web/$1$2"; + index = "index.html index.htm"; + extraConfig = '' + autoindex on; + ''; + }; + }; + }; + + "bsima.me" = { + locations."/" = { + root = "/var/web/ben"; + index = "index.html index.htm"; + extraConfig = '' + autoindex on; + ''; + }; + serverAliases = [ "www.bsima.me" ]; + forceSSL = true; + useACMEHost = rootDomain; + }; + + "hoogle.${rootDomain}" = { + locations."/".proxyPass = + "http://${ports.bensIp}:${toString ports.hoogle}"; + forceSSL = true; + useACMEHost = rootDomain; + }; + + "tv.${rootDomain}" = { + locations."/".proxyPass = + "http://${ports.bensIp}:${toString ports.jellyfin}"; + forceSSL = true; + useACMEHost = rootDomain; + }; + + "cal.${rootDomain}" = { + locations."/".proxyPass = + "http://localhost:${toString ports.radicale}"; + forceSSL = true; + useACMEHost = rootDomain; + extraConfig = '' + proxy_set_header X-Script-Name /radicale; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_pass_header Authorization; + ''; + }; + + "reddit.${rootDomain}" = { + locations."/".proxyPass = + "http://localhost:${toString ports.libreddit}"; + forceSSL = true; + useACMEHost = rootDomain; + }; + "www.reddit.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + globalRedirect = "reddit.${rootDomain}"; + }; + "old.reddit.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + globalRedirect = "reddit.${rootDomain}"; + }; + + "youtube.${rootDomain}" = { + locations."/".proxyPass = + "http://localhost:${toString ports.invidious}"; + forceSSL = true; + useACMEHost = rootDomain; + }; + "www.youtube.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + globalRedirect = "youtube.${rootDomain}"; + }; + "m.youtube.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + globalRedirect = "youtube.${rootDomain}"; + }; + + "dandel-rovbur.${rootDomain}" = { + locations."/".proxyPass = + "http://${ports.bensIp}:${toString ports.dandel-rovbur}"; + forceSSL = true; + useACMEHost = rootDomain; + }; + + "sabten.${rootDomain}" = { + locations."/".proxyPass = "http://localhost:${toString ports.sabten}"; + forceSSL = true; + useACMEHost = rootDomain; + }; + + "sd.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + locations."/" = { + proxyPass = + "http://${ports.bensIp}:${toString ports.stableDiffusion}"; + proxyWebsockets = true; + }; + }; + + "music.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + locations."/".proxyPass = + "http://localhost:${toString ports.botamusique}"; + }; + + "nostr.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + locations."/" = { + proxyPass = "http://localhost:${toString ports.nostr-relay}"; + extraConfig = '' + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + ''; + }; + }; + + "notebook.${rootDomain}" = { + forceSSL = true; + useACMEHost = rootDomain; + locations = { + "/" = { + proxyPass = "http://${ports.bensIp}:${toString ports.jupyter}"; + proxyWebsockets = true; + extraConfig = '' + proxy_buffering off; + proxy_read_timeout 86400; + ''; + }; + "/(api/kernels/[^/]+/channels|terminals/websocket)/" = { + proxyPass = "http://${ports.bensIp}:${toString ports.jupyter}"; + proxyWebsockets = true; + }; + }; + }; + + }; + }; + }; + + # This must contain all of the other domains we host + security.acme.certs.${rootDomain}.extraDomainNames = + [ "bsima.me" "www.bsima.me" ] ++ map (sub: "${sub}.${rootDomain}") [ + "music" + "tv" + "matrix" + "chat" + "hoogle" + "dandel-rovbur" + "sabten" + "cal" + "notebook" + "nostr" + "reddit" + "old.reddit" + "www.reddit" + "youtube" + "www.youtube" + "m.youtube" + "sd" + "gerrit" + ]; +} -- cgit v1.2.3