diff --git a/hosts/apu/configuration.nix b/hosts/apu/configuration.nix index f170052..15456a7 100644 --- a/hosts/apu/configuration.nix +++ b/hosts/apu/configuration.nix @@ -3,18 +3,6 @@ # https://search.nixos.org/options and in the NixOS manual (`nixos-help`). { lib, pkgs, config, ... }: -let - nginxVhost = options: { - http2 = true; - forceSSL = true; - enableACME = true; - acmeRoot = null; - } // options; - - nginxProxy = options: { - proxyWebsockets = true; - } // options; -in { boot.loader.grub.enable = true; boot.loader.grub.device = "/dev/sda"; @@ -72,12 +60,16 @@ in }; }; - modules.firewall.rules = { - koti = [ "dhcp" "dns" "ssh" ]; - gast = [ "dhcp" "dns" ]; - iot = [ "dhcp" "dns" ]; - cfg = [ "dhcp" "dns" ]; - "tailscale*" = [ "ssh" "web" ]; + modules.firewall = { + enable = true; + interfaces = { + koti = [ "dhcp" "dns" "ssh" "web" ]; + gast = [ "dhcp" "dns" ]; + iot = [ "dhcp" "dns" ]; + cfg = [ "dhcp" "dns" ]; + "tailscale*" = [ "ssh" "web" ]; + }; + allInterfaces = [ ]; }; systemd.network = { @@ -228,31 +220,12 @@ in }; }; - services.nginx.virtualHosts."koti.repomaa.com" = nginxVhost { - extraConfig = '' - proxy_buffering off; - ''; - locations."/" = nginxProxy { - proxyPass = "http://127.0.0.1:8123"; - }; - }; - - services.nginx = { + modules.webserver = { enable = true; - recommendedProxySettings = true; - recommendedTlsSettings = true; - recommendedBrotliSettings = true; - recommendedGzipSettings = true; - recommendedZstdSettings = true; - recommendedOptimisation = true; - }; - - security.acme = { - acceptTerms = true; - defaults = { - dnsProvider = "hetzner"; - environmentFile = "/var/secrets/lego"; - email = "admin@j.repomaa.com"; + acme.dnsChallenge = true; + vHosts."koti.repomaa.com" = { + proxyBuffering = false; + locations."/".proxy = "http://127.0.0.1:8123"; }; }; diff --git a/hosts/freun.dev/default.nix b/hosts/freun.dev/default.nix index a20f53e..3581646 100644 --- a/hosts/freun.dev/default.nix +++ b/hosts/freun.dev/default.nix @@ -6,7 +6,7 @@ in imports = [ ./hardware-configuration.nix ./configuration.nix - ./services.nix + ./services gtrackmap.nixosModules.x86_64-linux.default ]; } diff --git a/hosts/freun.dev/gtrackmap.nix b/hosts/freun.dev/gtrackmap.nix deleted file mode 100644 index 5b12abf..0000000 --- a/hosts/freun.dev/gtrackmap.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ config, ... }: -let - fqdn = "trackmap.freun.dev"; -in -{ - services.gtrackmap = { - enable = true; - port = 3200; - }; - - services.caddy.virtualHosts = { - "${fqdn}".extraConfig = '' - reverse_proxy localhost:${toString config.services.gtrackmap.port} - ''; - }; -} diff --git a/hosts/freun.dev/hydra.nix b/hosts/freun.dev/hydra.nix deleted file mode 100644 index 608a53a..0000000 --- a/hosts/freun.dev/hydra.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ ... }: -let - fqdn = "ci.freun.dev"; - port = 3400; -in -{ - services.hydra = { - enable = true; - hydraURL = "https://${fqdn}"; - notificationSender = "Hydra "; - buildMachinesFiles = []; - useSubstitutes = true; - inherit port; - }; - - services.caddy.virtualHosts = { - "${fqdn}".extraConfig = '' - reverse_proxy localhost:${builtins.toString port} - ''; - }; -} diff --git a/hosts/freun.dev/owncast.nix b/hosts/freun.dev/owncast.nix deleted file mode 100644 index b71b26f..0000000 --- a/hosts/freun.dev/owncast.nix +++ /dev/null @@ -1,16 +0,0 @@ -{ ... }: -let - fqdn = "stream.freun.dev"; -in -{ - services.owncast = { - enable = true; - openFirewall = true; - }; - - services.caddy.virtualHosts = { - "${fqdn}".extraConfig = '' - reverse_proxy localhost:8080 - ''; - }; -} diff --git a/hosts/freun.dev/services.nix b/hosts/freun.dev/services/default.nix similarity index 83% rename from hosts/freun.dev/services.nix rename to hosts/freun.dev/services/default.nix index c9557c2..fb1533b 100644 --- a/hosts/freun.dev/services.nix +++ b/hosts/freun.dev/services/default.nix @@ -1,13 +1,5 @@ { pkgs, ... }: { - networking.firewall.allowedTCPPorts = [ 80 443 ]; - - services.caddy = { - enable = true; - enableReload = true; - email = "admin@pimeys.pm"; - }; - services.postgresql = { enable = true; package = pkgs.postgresql_17; @@ -30,6 +22,8 @@ interfaces.podman1.allowedUDPPorts = [ 53 ]; }; + modules.webserver.enable = true; + imports = [ ./vaultwarden.nix ./immich.nix diff --git a/hosts/freun.dev/gotosocial.nix b/hosts/freun.dev/services/gotosocial.nix similarity index 58% rename from hosts/freun.dev/gotosocial.nix rename to hosts/freun.dev/services/gotosocial.nix index 536c5b8..c0423e6 100644 --- a/hosts/freun.dev/gotosocial.nix +++ b/hosts/freun.dev/services/gotosocial.nix @@ -1,6 +1,7 @@ -{ config, ... }: +{ config, lib, ... }: let - fqdn = "social.freun.dev"; + domain = "freun.dev"; + fqdn = "social.${domain}"; port = 3500; in { @@ -26,17 +27,21 @@ in setupPostgresqlDB = true; }; - services.caddy.virtualHosts = { - "freun.dev".extraConfig = '' - redir /.well-known/host-meta* https://${fqdn}{uri} permanent - redir /.well-known/webfinger* https://${fqdn}{uri} permanent - redir /.well-known/nodeinfo* https://${fqdn}{uri} permanent - ''; + modules.webserver.vHosts = { + ${domain}.locations = lib.listToAttrs ( + lib.map + (path: { + name = "/.well-known/${path}"; + value.extraConfig = '' + rewrite ^.*$ https://${fqdn}/.well-known/${path} permanent; + ''; + }) [ + "host-meta" + "webfinger" + "nodeinfo" + ] + ); - "${fqdn}".extraConfig = '' - reverse_proxy localhost:${toString config.services.gotosocial.settings.port} { - flush_interval -1 - } - ''; + "${fqdn}".locations."/".proxy = "http://localhost:${toString port}"; }; } diff --git a/hosts/freun.dev/grafana.nix b/hosts/freun.dev/services/grafana.nix similarity index 84% rename from hosts/freun.dev/grafana.nix rename to hosts/freun.dev/services/grafana.nix index a6a7f33..5730e27 100644 --- a/hosts/freun.dev/grafana.nix +++ b/hosts/freun.dev/services/grafana.nix @@ -9,7 +9,7 @@ in settings = { server = { - root_url = "https://${fqdn}"; + root_url = "https://${fqdn}"; http_port = port; }; @@ -43,11 +43,7 @@ in ]; }; - services.caddy.virtualHosts = { - "${fqdn}".extraConfig = '' - reverse_proxy localhost:${builtins.toString port} - ''; - }; + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; services.postgresql = { ensureDatabases = [ "grafana" ]; @@ -57,4 +53,3 @@ in }]; }; } - diff --git a/hosts/freun.dev/services/gtrackmap.nix b/hosts/freun.dev/services/gtrackmap.nix new file mode 100644 index 0000000..e9d8d3e --- /dev/null +++ b/hosts/freun.dev/services/gtrackmap.nix @@ -0,0 +1,13 @@ +{ ... }: +let + fqdn = "trackmap.freun.dev"; + port = 3200; +in +{ + services.gtrackmap = { + enable = true; + inherit port; + }; + + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; +} diff --git a/hosts/freun.dev/immich.nix b/hosts/freun.dev/services/immich.nix similarity index 96% rename from hosts/freun.dev/immich.nix rename to hosts/freun.dev/services/immich.nix index f17ee32..ba45c72 100644 --- a/hosts/freun.dev/immich.nix +++ b/hosts/freun.dev/services/immich.nix @@ -1,6 +1,9 @@ { pkgs, lib, ... }: let + fqdn = "img.freun.dev"; + port = 2283; + immich_version = "v1.125.2"; storage_dir = "/mnt/storage/syncthing"; immich_data_dir = "/mnt/storage/immich"; @@ -115,7 +118,7 @@ in "${storage_dir}:${storage_dir}:ro" ]; ports = [ - "2283:2283/tcp" + "${toString port}:2283/tcp" ]; dependsOn = [ "immich_postgres" @@ -164,11 +167,7 @@ in wantedBy = [ "multi-user.target" ]; }; - services.caddy.virtualHosts = { - "img.freun.dev".extraConfig = '' - reverse_proxy localhost:2283 - ''; - }; + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; fileSystems."${immich_data_dir}" = { device = "//u407959.your-storagebox.de/backup/immich"; diff --git a/hosts/freun.dev/invidious.nix b/hosts/freun.dev/services/invidious.nix similarity index 61% rename from hosts/freun.dev/invidious.nix rename to hosts/freun.dev/services/invidious.nix index 2f7474d..fd878f8 100644 --- a/hosts/freun.dev/invidious.nix +++ b/hosts/freun.dev/services/invidious.nix @@ -1,11 +1,14 @@ { ... }: let fqdn = "vid.freun.dev"; + port = 3000; in { services.invidious = { enable = true; domain = fqdn; + address = "127.0.0.1"; + inherit port; settings = { external_port = 443; @@ -16,10 +19,5 @@ in }; }; - services.caddy.virtualHosts = { - "${fqdn}".extraConfig = '' - reverse_proxy localhost:3000 - ''; - }; - + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; } diff --git a/hosts/freun.dev/services/owncast.nix b/hosts/freun.dev/services/owncast.nix new file mode 100644 index 0000000..5a460f3 --- /dev/null +++ b/hosts/freun.dev/services/owncast.nix @@ -0,0 +1,14 @@ +{ ... }: +let + fqdn = "stream.freun.dev"; + port = 8080; +in +{ + services.owncast = { + enable = true; + openFirewall = true; + inherit port; + }; + + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; +} diff --git a/hosts/freun.dev/snips.nix b/hosts/freun.dev/services/snips.nix similarity index 100% rename from hosts/freun.dev/snips.nix rename to hosts/freun.dev/services/snips.nix diff --git a/hosts/freun.dev/services/syncthing.nix b/hosts/freun.dev/services/syncthing.nix new file mode 100644 index 0000000..eba9e44 --- /dev/null +++ b/hosts/freun.dev/services/syncthing.nix @@ -0,0 +1,33 @@ +{ pkgs, config, lib, ... }: +let + fqdn = "sync.freun.dev"; + port = 8384; + + storage_dir = "/mnt/storage/syncthing"; +in +{ + services.syncthing = { + enable = true; + dataDir = "/mnt/storage/syncthing"; + openDefaultPorts = true; + guiAddress = "127.0.0.1:${toString port}"; + }; + + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; + + fileSystems."${storage_dir}" = { + device = "//u407959.your-storagebox.de/backup/syncthing"; + fsType = "cifs"; + options = + let + # this line prevents hanging on network split + automount_opts = "x-systemd.automount,auto,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"; + uid = builtins.toString config.users.users.syncthing.uid; + gid = builtins.toString config.users.groups.syncthing.gid; + in + [ "${automount_opts},credentials=/var/secrets/smb-storage,uid=${uid},gid=${gid}" ]; + }; + + + environment.systemPackages = [ pkgs.cifs-utils ]; +} diff --git a/hosts/freun.dev/tailscale.nix b/hosts/freun.dev/services/tailscale.nix similarity index 100% rename from hosts/freun.dev/tailscale.nix rename to hosts/freun.dev/services/tailscale.nix diff --git a/hosts/freun.dev/vaultwarden.nix b/hosts/freun.dev/services/vaultwarden.nix similarity index 76% rename from hosts/freun.dev/vaultwarden.nix rename to hosts/freun.dev/services/vaultwarden.nix index c54987c..6157622 100644 --- a/hosts/freun.dev/vaultwarden.nix +++ b/hosts/freun.dev/services/vaultwarden.nix @@ -1,11 +1,14 @@ -{ ... }: +{ lib, ... }: +let + fqdn = "pw.freun.dev"; +in { services.vaultwarden = { enable = true; dbBackend = "postgresql"; environmentFile = "/var/secrets/vaultwarden.env"; config = { - DOMAIN = "https://pw.freun.dev"; + DOMAIN = "https://${fqdn}"; DATABASE_URL = "postgres://%2Fvar%2Frun%2Fpostgresql/vaultwarden"; WEBSOCKET_ENABLED = true; WEBSOCKET_ADDRESS = "127.0.0.1"; @@ -23,13 +26,9 @@ }; }; - services.caddy.virtualHosts = { - "pw.freun.dev".extraConfig = '' - reverse_proxy /notifications/hub localhost:3012 - reverse_proxy localhost:8000 { - header_up X-Real-IP {remote_host} - } - ''; + modules.webserver.vHosts.${fqdn}.locations = { + "/".proxy = "http://localhost:8000"; + "/notifications/hub".proxy = "http://localhost:3012"; }; services.postgresql = { diff --git a/hosts/freun.dev/workout-tracker.nix b/hosts/freun.dev/services/workout-tracker.nix similarity index 87% rename from hosts/freun.dev/workout-tracker.nix rename to hosts/freun.dev/services/workout-tracker.nix index b01408a..76734b6 100644 --- a/hosts/freun.dev/workout-tracker.nix +++ b/hosts/freun.dev/services/workout-tracker.nix @@ -31,9 +31,5 @@ in }; }; - services.caddy.virtualHosts = { - "${fqdn}".extraConfig = '' - reverse_proxy localhost:${toString port} - ''; - }; + modules.webserver.vHosts.${fqdn}.locations."/".proxy = "http://localhost:${toString port}"; } diff --git a/hosts/freun.dev/syncthing.nix b/hosts/freun.dev/syncthing.nix deleted file mode 100644 index cc8235a..0000000 --- a/hosts/freun.dev/syncthing.nix +++ /dev/null @@ -1,33 +0,0 @@ -{ pkgs, config, lib, ... }: -let - storage_dir = "/mnt/storage/syncthing"; -in -{ - services.syncthing = { - enable = true; - dataDir = "/mnt/storage/syncthing"; - openDefaultPorts = true; - }; - - services.caddy.virtualHosts = { - "sync.freun.dev".extraConfig = '' - reverse_proxy localhost:8384 { - header_up Host {upstream_hostport} - } - ''; - }; - - fileSystems."${storage_dir}" = { - device = "//u407959.your-storagebox.de/backup/syncthing"; - fsType = "cifs"; - options = let - # this line prevents hanging on network split - automount_opts = "x-systemd.automount,auto,x-systemd.device-timeout=5s,x-systemd.mount-timeout=5s"; - uid = builtins.toString config.users.users.syncthing.uid; - gid = builtins.toString config.users.groups.syncthing.gid; - in ["${automount_opts},credentials=/var/secrets/smb-storage,uid=${uid},gid=${gid}"]; - }; - - - environment.systemPackages = [ pkgs.cifs-utils ]; -} diff --git a/modules/default.nix b/modules/default.nix index 8288022..315dfc8 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -3,5 +3,6 @@ imports = [ ./vlans.nix ./firewall.nix + ./webserver.nix ]; } diff --git a/modules/firewall.nix b/modules/firewall.nix index 4a193fb..5206198 100644 --- a/modules/firewall.nix +++ b/modules/firewall.nix @@ -16,18 +16,25 @@ let { allowedUDPPorts = [ ]; allowedTCPPorts = [ ]; } enabledServices; - cfg = config.modules.firewall.rules; + cfg = config.modules.firewall; in { - options.modules.firewall.rules = lib.mkOption { - type = lib.types.attrsOf (lib.types.listOf (lib.types.enum (lib.attrNames services))); - default = { }; - }; - - config = lib.mkIf (lib.length (lib.attrNames cfg) > 0) { - networking.firewall = { - enable = lib.mkDefault true; - interfaces = lib.mapAttrs (_: enabledServices: rulesForServices enabledServices) cfg; + options.modules.firewall = { + enable = lib.mkEnableOption "Enable the firewall"; + interfaces = lib.mkOption { + type = lib.types.attrsOf (lib.types.listOf (lib.types.enum (lib.attrNames services))); + default = { }; + }; + allInterfaces = lib.mkOption { + type = lib.types.listOf (lib.types.enum (lib.attrNames services)); + default = [ ]; }; }; + + config = lib.mkIf cfg.enable { + networking.firewall = { + enable = true; + interfaces = lib.mapAttrs (_: enabledServices: rulesForServices enabledServices) cfg.interfaces; + } // rulesForServices cfg.allInterfaces; + }; } diff --git a/modules/webserver.nix b/modules/webserver.nix new file mode 100644 index 0000000..462b91f --- /dev/null +++ b/modules/webserver.nix @@ -0,0 +1,99 @@ +{ lib, config, ... }: +let + cfg = config.modules.webserver; + + nginxVhost = options: { + http2 = true; + forceSSL = true; + enableACME = true; + acmeRoot = null; + } // options; + + nginxProxy = options: { + proxyWebsockets = true; + } // options; + + types = { + location = lib.types.submodule { + options = { + proxy = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + }; + extraConfig = lib.mkOption { + type = lib.types.str; + default = ""; + }; + }; + }; + + vhost = lib.types.submodule { + options = { + proxyBuffering = lib.mkOption { + type = lib.types.bool; + default = true; + }; + locations = lib.mkOption { + type = lib.types.attrsOf types.location; + }; + }; + }; + }; +in +{ + options.modules.webserver = { + enable = lib.mkEnableOption "Enable nginx"; + acme = { + dnsChallenge = lib.mkEnableOption "Enable DNS challenge"; + dnsProvider = lib.mkOption { + type = lib.types.str; + default = "hetzner"; + }; + environmentFile = lib.mkOption { + type = lib.types.str; + default = "/var/secrets/lego"; + }; + }; + vHosts = lib.mkOption { + type = lib.types.attrsOf types.vhost; + default = { }; + }; + }; + + config = lib.mkIf cfg.enable { + services.nginx = { + enable = lib.mkDefault true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + recommendedBrotliSettings = true; + recommendedGzipSettings = true; + recommendedZstdSettings = true; + recommendedOptimisation = true; + + virtualHosts = lib.mapAttrs + (_: { proxyBuffering, locations }: nginxVhost { + extraConfig = lib.mkIf (!proxyBuffering) '' + proxy_buffering off; + ''; + locations = lib.mapAttrs + (_: { proxy, extraConfig }: lib.mergeAttrsList [ + { inherit extraConfig; } + (if (lib.isString proxy) then (nginxProxy { proxyPass = proxy; }) else { }) + ]) + locations; + }) + cfg.vHosts; + }; + + security.acme = { + acceptTerms = true; + defaults = { + email = "admin@j.repomaa.com"; + dnsProvider = lib.mkIf cfg.acme.dnsChallenge cfg.acme.dnsProvider; + webroot = lib.mkIf (!cfg.acme.dnsChallenge) "/var/lib/acme/"; + }; + }; + + modules.firewall.allInterfaces = lib.mkDefault [ "web" ]; + }; +}