From da4896341cd0e26fe7c8eb76d583654d5acdc952 Mon Sep 17 00:00:00 2001 From: Tigor Hutasuhut Date: Sun, 24 Nov 2024 20:16:30 +0700 Subject: [PATCH] prepare nginx migration --- hardware-configuration/homeserver.nix | 16 ++- options/services.nix | 1 + profiles/homeserver.nix | 11 +- system/podman/memos.nix | 6 + system/podman/morphos.nix | 6 + system/podman/pihole.nix | 15 +- system/podman/qbittorrent.nix | 8 ++ system/podman/redmage-demo.nix | 8 ++ system/podman/redmage.nix | 8 ++ system/podman/servarr/bazarr.nix | 8 ++ system/podman/servarr/prowlarr.nix | 8 ++ system/podman/servarr/qbittorrent.nix | 9 ++ system/podman/servarr/radarr.nix | 9 ++ system/podman/servarr/rdtclient.nix | 9 ++ system/podman/servarr/real-debrid-manager.nix | 9 ++ system/podman/servarr/sonarr.nix | 18 +++ system/podman/soulseek.nix | 9 ++ system/podman/suwayomi.nix | 8 ++ system/podman/ytptube.nix | 15 +- system/services/cockpit.nix | 10 ++ system/services/default.nix | 7 +- system/services/forgejo.nix | 20 +++ system/services/jellyfin.nix | 1 + system/services/nginx.nix | 131 ++++++++++++++++++ 24 files changed, 331 insertions(+), 19 deletions(-) create mode 100644 system/services/nginx.nix diff --git a/hardware-configuration/homeserver.nix b/hardware-configuration/homeserver.nix index c40ffa2..080914a 100644 --- a/hardware-configuration/homeserver.nix +++ b/hardware-configuration/homeserver.nix @@ -137,11 +137,17 @@ ]; }; - services.caddy.virtualHosts."public.tigor.web.id".extraConfig = # caddy - '' - file_server browse - root * /nas/public - ''; + services.nginx.virtualHosts."public.tigor.web.id" = { + enableACME = true; + forceSSL = true; + locations."/" = { + root = "/nas/public"; + tryFiles = "$uri $uri/ $uri.html =404"; + extraConfig = '' + autoindex on; + ''; + }; + }; systemd.tmpfiles.settings = { "100-nas-public-dir" = { diff --git a/options/services.nix b/options/services.nix index 5969e49..1c1c952 100644 --- a/options/services.nix +++ b/options/services.nix @@ -10,6 +10,7 @@ in { options.profile.services = { caddy.enable = mkEnableOption "caddy"; + nginx.enable = mkEnableOption "nginx"; cockpit.enable = mkEnableOption "cockpit"; forgejo.enable = mkEnableOption "forgejo"; kavita.enable = mkEnableOption "kavita"; diff --git a/profiles/homeserver.nix b/profiles/homeserver.nix index 939e1da..bcd6a40 100644 --- a/profiles/homeserver.nix +++ b/profiles/homeserver.nix @@ -37,12 +37,12 @@ servarr.recyclarr.enable = true; servarr.real-debrid-manager.enable = false; servarr.rdtclient.enable = true; - openobserve.enable = true; + openobserve.enable = false; minecraft.enable = false; memos.enable = true; morphos.enable = true; soulseek.enable = true; - valheim.enable = true; + valheim.enable = false; }; home.programs.zellij = { @@ -53,7 +53,8 @@ }; services = { - caddy.enable = true; + caddy.enable = false; + nginx.enable = true; cockpit.enable = true; forgejo.enable = true; kavita.enable = true; @@ -65,12 +66,12 @@ jellyfin.enable = true; rust-motd.enable = true; wireguard.enable = true; - photoprism.enable = true; + photoprism.enable = false; navidrome.enable = true; telemetry.enable = true; ntfy-sh.enable = true; ntfy-sh.client.enable = false; - couchdb.enable = true; + couchdb.enable = false; technitium.enable = false; }; }; diff --git a/system/podman/memos.nix b/system/podman/memos.nix index d30cad2..fd486e7 100644 --- a/system/podman/memos.nix +++ b/system/podman/memos.nix @@ -17,6 +17,12 @@ in reverse_proxy ${ip}:5230 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://${ip}:5230"; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${rootVolume} chown ${uid}:${gid} ${rootVolume} diff --git a/system/podman/morphos.nix b/system/podman/morphos.nix index 981c72e..e074915 100644 --- a/system/podman/morphos.nix +++ b/system/podman/morphos.nix @@ -16,6 +16,12 @@ in reverse_proxy ${ip}:8080 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://${ip}:8080"; + }; + virtualisation.oci-containers.containers.${name} = { inherit image; hostname = name; diff --git a/system/podman/pihole.nix b/system/podman/pihole.nix index b1a6f14..7be3beb 100644 --- a/system/podman/pihole.nix +++ b/system/podman/pihole.nix @@ -16,6 +16,19 @@ in reverse_proxy ${ip}:80 ''; + services.nginx.virtualHosts."pihole.tigor.web.id" = { + enableACME = true; + forceSSL = true; + locations = { + "= /" = { + return = "301 /admin"; + }; + "/" = { + proxyPass = "http://${ip}:80"; + }; + }; + }; + sops.secrets."pihole/env" = { sopsFile = ../../secrets/pihole.yaml; }; @@ -50,7 +63,7 @@ in ${strings.concatStringsSep "\n" ( attrsets.mapAttrsToList ( name: _: "192.168.100.5 ${strings.removePrefix "https://" name}" - ) config.services.caddy.virtualHosts + ) config.services.nginx.virtualHosts )} ''; }; diff --git a/system/podman/qbittorrent.nix b/system/podman/qbittorrent.nix index 4f8bb7d..c2feba5 100644 --- a/system/podman/qbittorrent.nix +++ b/system/podman/qbittorrent.nix @@ -24,6 +24,14 @@ lib.mkMerge [ reverse_proxy ${ip}:8080 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8080"; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${volume}/{config,downloads,progress,watch} chown ${uid}:${gid} ${volume} ${volume}/{config,downloads,progress,watch} diff --git a/system/podman/redmage-demo.nix b/system/podman/redmage-demo.nix index 15c34c2..f9e02ea 100644 --- a/system/podman/redmage-demo.nix +++ b/system/podman/redmage-demo.nix @@ -17,6 +17,14 @@ in reverse_proxy ${ip}:8080 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8080"; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${rootVolume}/db mkdir -p ${rootVolume}/images diff --git a/system/podman/redmage.nix b/system/podman/redmage.nix index 2af29ae..19694da 100644 --- a/system/podman/redmage.nix +++ b/system/podman/redmage.nix @@ -24,6 +24,14 @@ in reverse_proxy ${ip}:8080 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8080"; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${rootVolume}/db mkdir -p ${rootVolume}/images diff --git a/system/podman/servarr/bazarr.nix b/system/podman/servarr/bazarr.nix index 722abd1..75f2a6b 100644 --- a/system/podman/servarr/bazarr.nix +++ b/system/podman/servarr/bazarr.nix @@ -20,6 +20,14 @@ in reverse_proxy ${ip}:6767 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:6767"; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${configVolume} chown ${uid}:${gid} ${mediaVolume} ${configVolume} diff --git a/system/podman/servarr/prowlarr.nix b/system/podman/servarr/prowlarr.nix index bdf0483..283f056 100644 --- a/system/podman/servarr/prowlarr.nix +++ b/system/podman/servarr/prowlarr.nix @@ -22,6 +22,14 @@ in reverse_proxy ${ip}:9696 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:9696"; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${configVolume} chown ${uid}:${gid} ${configVolume} diff --git a/system/podman/servarr/qbittorrent.nix b/system/podman/servarr/qbittorrent.nix index 349696c..0f1373c 100644 --- a/system/podman/servarr/qbittorrent.nix +++ b/system/podman/servarr/qbittorrent.nix @@ -20,6 +20,15 @@ in reverse_proxy ${ip}:8080 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8080"; + proxyWebsockets = true; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${configVolume} ${mediaVolume} chown ${uid}:${gid} ${mediaVolume} ${configVolume} diff --git a/system/podman/servarr/radarr.nix b/system/podman/servarr/radarr.nix index c3a8a50..7218b14 100644 --- a/system/podman/servarr/radarr.nix +++ b/system/podman/servarr/radarr.nix @@ -20,6 +20,15 @@ in reverse_proxy ${ip}:7878 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:7878"; + proxyWebsockets = true; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${configVolume} ${mediaVolume} chown ${uid}:${gid} ${mediaVolume} ${configVolume} diff --git a/system/podman/servarr/rdtclient.nix b/system/podman/servarr/rdtclient.nix index 4405284..072510b 100644 --- a/system/podman/servarr/rdtclient.nix +++ b/system/podman/servarr/rdtclient.nix @@ -20,6 +20,15 @@ in reverse_proxy ${ip}:6500 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:6500"; + proxyWebsockets = true; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${volumeConfig} ${mediaVolume} chown ${uid}:${gid} ${volumeConfig} ${mediaVolume} diff --git a/system/podman/servarr/real-debrid-manager.nix b/system/podman/servarr/real-debrid-manager.nix index c479c9c..3357fc6 100644 --- a/system/podman/servarr/real-debrid-manager.nix +++ b/system/podman/servarr/real-debrid-manager.nix @@ -21,6 +21,15 @@ in reverse_proxy ${ip}:5000 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:5000"; + proxyWebsockets = true; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${configVolume} ${mediaVolume} ${watchVolume} chown ${uid}:${gid} ${configVolume} ${mediaVolume} ${watchVolume} diff --git a/system/podman/servarr/sonarr.nix b/system/podman/servarr/sonarr.nix index 7437123..e0bf389 100644 --- a/system/podman/servarr/sonarr.nix +++ b/system/podman/servarr/sonarr.nix @@ -24,10 +24,28 @@ in reverse_proxy ${ip}:8989 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8989"; + proxyWebsockets = true; + }; + }; + services.caddy.virtualHosts.${domain-anime}.extraConfig = '' reverse_proxy ${ip-anime}:8989 ''; + services.nginx.virtualHosts.${domain-anime} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8989"; + proxyWebsockets = true; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${configVolume} ${mediaVolume} ${configVolumeAnime} chown ${uid}:${gid} ${mediaVolume} ${configVolume} ${configVolumeAnime} diff --git a/system/podman/soulseek.nix b/system/podman/soulseek.nix index 24cf66c..d71ecb8 100644 --- a/system/podman/soulseek.nix +++ b/system/podman/soulseek.nix @@ -29,6 +29,15 @@ in reverse_proxy ${ip}:6080 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:6080"; + proxyWebsockets = true; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${rootVolume}/{config,downloads,incomplete} chown ${uid}:${gid} ${rootVolume} ${rootVolume}/{config,downloads,incomplete} diff --git a/system/podman/suwayomi.nix b/system/podman/suwayomi.nix index 1d38551..b93cd31 100644 --- a/system/podman/suwayomi.nix +++ b/system/podman/suwayomi.nix @@ -21,6 +21,14 @@ in reverse_proxy ${ip}:4567 ''; + services.nginx.virtualHosts.${domain} = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:4567"; + }; + }; + system.activationScripts."podman-${name}" = '' mkdir -p ${volume} chown ${uid}:${gid} ${volume} diff --git a/system/podman/ytptube.nix b/system/podman/ytptube.nix index 04a22e3..e58a7e2 100644 --- a/system/podman/ytptube.nix +++ b/system/podman/ytptube.nix @@ -15,11 +15,6 @@ let user = config.profile.user; uid = toString user.uid; gid = toString user.gid; - basic_auth = { - username = "caddy/basic_auth/username"; - password = "caddy/basic_auth/password"; - template = "caddy/basic_auth"; - }; webhook = builtins.readFile ( (pkgs.formats.json { }).generate "webhooks.json" [ { @@ -68,6 +63,16 @@ let in lib.mkMerge [ (mkIf podman.${name}.enable { + services.nginx.virtualHosts.${domain} = { + enableACME = true; + # useACMEHost = "ytptube.tigor.web.id"; + forceSSL = true; + locations."/" = { + proxyPass = "http://${ip}:8081"; + proxyWebsockets = true; + }; + }; + services.caddy.virtualHosts.${domain}.extraConfig = '' @require_auth not remote_ip private_ranges diff --git a/system/services/cockpit.nix b/system/services/cockpit.nix index f76a0f9..6c5319e 100644 --- a/system/services/cockpit.nix +++ b/system/services/cockpit.nix @@ -13,6 +13,16 @@ in environment.systemPackages = mkIf config.profile.podman.enable [ (pkgs.callPackage ../packages/cockpit-podman.nix { }) ]; + + services.nginx.virtualHosts."cockpit.tigor.web.id" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://0.0.0.0:9090"; + proxyWebsockets = true; + }; + }; + services.caddy.virtualHosts."cockpit.tigor.web.id".extraConfig = # caddyfile '' @denied not remote_ip private_ranges diff --git a/system/services/default.nix b/system/services/default.nix index f308e09..67a4fed 100644 --- a/system/services/default.nix +++ b/system/services/default.nix @@ -11,14 +11,15 @@ ./kavita.nix ./navidrome.nix ./nextcloud.nix + ./nginx.nix + ./ntfy-sh.nix ./openvpn.nix + ./photoprism.nix ./rust-motd.nix ./samba.nix ./stubby.nix ./syncthing.nix - ./wireguard.nix - ./photoprism.nix - ./ntfy-sh.nix ./technitium.nix + ./wireguard.nix ]; } diff --git a/system/services/forgejo.nix b/system/services/forgejo.nix index 7949d9b..bbaa666 100644 --- a/system/services/forgejo.nix +++ b/system/services/forgejo.nix @@ -10,6 +10,26 @@ let in { config = mkIf cfg.enable { + services.nginx.virtualHosts."git.tigor.web.id" = { + enableACME = true; + forceSSL = true; + locations = { + "= /" = { + extraConfig = + #nginx + '' + if ($http_cookie !~ "gitea_incredible") { + rewrite ^(.*)$ /Tigor redirect; + } + ''; + proxyPass = "http://unix:/run/forgejo/forgejo.sock"; + }; + "/" = { + proxyPass = "http://unix:/run/forgejo/forgejo.sock"; + }; + }; + }; + services.caddy.virtualHosts."git.tigor.web.id".extraConfig = '' @home_not_login { not header_regexp Cookie gitea_incredible diff --git a/system/services/jellyfin.nix b/system/services/jellyfin.nix index b5a074a..c747212 100644 --- a/system/services/jellyfin.nix +++ b/system/services/jellyfin.nix @@ -15,6 +15,7 @@ in mkdir -p ${dataDir} chmod -R 0777 /nas/mediaserver ''; + services.caddy.virtualHosts.${domain}.extraConfig = '' @public not remote_ip private_ranges diff --git a/system/services/nginx.nix b/system/services/nginx.nix new file mode 100644 index 0000000..c5ac0e5 --- /dev/null +++ b/system/services/nginx.nix @@ -0,0 +1,131 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.profile.services.nginx; + inherit (lib) + mkIf + attrsets + strings + lists + ; +in +{ + config = mkIf cfg.enable { + services.nginx = { + enable = true; + additionalModules = [ + pkgs.nginxModules.pam + ]; + recommendedTlsSettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedZstdSettings = true; + recommendedBrotliSettings = true; + }; + + users.users.nginx.extraGroups = [ "acme" ]; + + security.acme = { + acceptTerms = true; + defaults.email = "tigor.hutasuhut@gmail.com"; + }; + + # Enable Basic Authentication via PAM + security.pam.services.nginx.setEnvironment = false; + systemd.services.nginx.serviceConfig = { + SupplementaryGroups = [ "shadow" ]; + }; + + environment.etc."nginx/static/tigor.web.id/index.html" = { + text = + let + domains = attrsets.mapAttrsToList ( + name: _: strings.removePrefix "https://" name + ) config.services.nginx.virtualHosts; + sortedDomains = lists.sort (a: b: a < b) domains; + list = map ( + domain: # html + '' +
+ ${domain} +
+ '') sortedDomains; + items = strings.concatStringsSep "\n" list; + in + # html + '' + + + + Hosted Sites + + + +

Hosted Sites

+
+ ${items} +
+ + + ''; + user = "nginx"; + group = "nginx"; + }; + + services.nginx.virtualHosts."tigor.web.id" = { + enableACME = true; + forceSSL = true; + locations."/" = { + root = "/etc/nginx/static/tigor.web.id"; + tryFiles = "$uri $uri/ $uri.html =404"; + }; + }; + + # Enable Real IP from Cloudflare + services.nginx.commonHttpConfig = + let + realIpsFromList = lib.strings.concatMapStringsSep "\n" (x: "set_real_ip_from ${x};"); + fileToList = x: lib.strings.splitString "\n" (builtins.readFile x); + cfipv4 = fileToList ( + pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v4"; + sha256 = "0ywy9sg7spafi3gm9q5wb59lbiq0swvf0q3iazl0maq1pj1nsb7h"; + } + ); + cfipv6 = fileToList ( + pkgs.fetchurl { + url = "https://www.cloudflare.com/ips-v6"; + sha256 = "1ad09hijignj6zlqvdjxv7rjj8567z357zfavv201b9vx3ikk7cy"; + } + ); + in + #nginx + '' + geo $auth_ip { + default "Password required"; + 10.0.0.0/8 "off"; + 172.16.0.0/12 "off"; + 192.168.0.0/16 "off"; + } + + auth_pam_service_name "nginx"; + + ${realIpsFromList cfipv4} + ${realIpsFromList cfipv6} + real_ip_header CF-Connecting-IP; + ''; + + # This is needed for nginx to be able to read other processes + # directories in `/run`. Else it will fail with (13: Permission denied) + systemd.services.nginx.serviceConfig.ProtectHome = false; + }; +}