From 46b249560f310f7eba555478d41761d589a7538d Mon Sep 17 00:00:00 2001 From: mjallen18 Date: Wed, 18 Mar 2026 20:39:24 -0500 Subject: [PATCH] cleanup --- lib/base64/ascii | 3 - lib/base64/default.nix | 62 ----- lib/default.nix | 14 -- lib/examples/default.nix | 8 - lib/examples/file-utils.nix | 60 ----- lib/examples/home-sops.nix | 40 ---- lib/examples/reverseproxy.nix | 117 ---------- lib/examples/sops.nix | 45 ---- lib/examples/system-utils.nix | 132 ----------- lib/module/default.nix | 150 ++++-------- lib/reverseproxy/default.nix | 220 ------------------ lib/system/common.nix | 103 -------- lib/system/default.nix | 5 - modules/nixos/services/grafana/default.nix | 2 +- modules/nixos/services/owncloud/default.nix | 4 +- .../nixos/services/your-spotify/options.nix | 6 +- systems/x86_64-linux/jallen-nas/default.nix | 2 +- .../x86_64-linux/jallen-nas/nas-defaults.nix | 86 +++++++ 18 files changed, 142 insertions(+), 917 deletions(-) delete mode 100644 lib/base64/ascii delete mode 100644 lib/base64/default.nix delete mode 100644 lib/examples/default.nix delete mode 100644 lib/examples/file-utils.nix delete mode 100644 lib/examples/home-sops.nix delete mode 100644 lib/examples/reverseproxy.nix delete mode 100644 lib/examples/sops.nix delete mode 100644 lib/examples/system-utils.nix delete mode 100644 lib/reverseproxy/default.nix delete mode 100644 lib/system/common.nix delete mode 100644 lib/system/default.nix create mode 100644 systems/x86_64-linux/jallen-nas/nas-defaults.nix diff --git a/lib/base64/ascii b/lib/base64/ascii deleted file mode 100644 index 27ab38e..0000000 --- a/lib/base64/ascii +++ /dev/null @@ -1,3 +0,0 @@ - - - !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ \ No newline at end of file diff --git a/lib/base64/default.nix b/lib/base64/default.nix deleted file mode 100644 index 93ba695..0000000 --- a/lib/base64/default.nix +++ /dev/null @@ -1,62 +0,0 @@ -{ inputs }: -let - inherit (inputs.nixpkgs.lib) - concatLists - concatMapStrings - foldl' - genList - hasSuffix - imap0 - length - mod - nameValuePair - stringToCharacters - sublist - substring - take - ; -in -rec { - base64Table = builtins.listToAttrs ( - imap0 (i: c: nameValuePair c i) ( - # The '=' is included so the main algorithm doesn't fail before we can trim the result - stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" - ) - ); - - # Generated using python3: - # print(''.join([ chr(n) for n in range(1, 256) ]), file=open('ascii', 'w')) - ascii = builtins.readFile ./ascii; - - decode = - str: - let - paddingCount = - if hasSuffix "==" str then - 2 - else if hasSuffix "=" str then - 1 - else - 0; - - numbers64 = map (c: base64Table.${c}) (stringToCharacters str); - - allBytes = concatLists ( - genList ( - i: - let - v = foldl' (acc: el: acc * 64 + el) 0 (sublist (i * 4) 4 numbers64); - in - [ - (mod (v / 256 / 256) 256) - (mod (v / 256) 256) - (mod v 256) - ] - ) (length numbers64 / 4) - ); - - finalBytes = take (length allBytes - paddingCount) allBytes; - - in - concatMapStrings (n: substring (n - 1) 1 ascii) finalBytes; -} diff --git a/lib/default.nix b/lib/default.nix index 5707ed3..715954c 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,22 +1,8 @@ { inputs, ... }: { mjallen-lib = { - # Import module utilities module = import ./module { inherit inputs; }; - - # Import file utilities file = import ./file { inherit inputs; }; - - # Import system utilities - system = import ./system { inherit inputs; }; - - # Import reverse proxy utilities - reverseproxy = import ./reverseproxy { inherit inputs; }; - - # Import examples - examples = import ./examples { inherit inputs; }; - - # Import versioning utilities versioning = import ./versioning { lib = inputs.nixpkgs.lib; inherit inputs; diff --git a/lib/examples/default.nix b/lib/examples/default.nix deleted file mode 100644 index 4b15ff4..0000000 --- a/lib/examples/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ ... }: -{ - # Import all examples - sops = import ./sops.nix; - homeSops = import ./home-sops.nix; - fileUtils = import ./file-utils.nix; - systemUtils = import ./system-utils.nix; -} diff --git a/lib/examples/file-utils.nix b/lib/examples/file-utils.nix deleted file mode 100644 index 7d63c0d..0000000 --- a/lib/examples/file-utils.nix +++ /dev/null @@ -1,60 +0,0 @@ -{ lib, namespace, ... }: -let - inherit (lib.${namespace}.file) - readFile - pathExists - safeImport - scanDir - getFile - importModulesRecursive - scanSystems - filterNixOSSystems - filterDarwinSystems - scanHomes - ; -in -{ - # Example of reading a file - myFileContent = readFile ./example.txt; - - # Example of checking if a file exists - fileExists = pathExists ./example.txt; - - # Example of safely importing a file - myConfig = safeImport ./my-config.nix { }; - - # Example of scanning a directory - directoryContents = scanDir ./modules; - - # Example of getting a file path relative to the flake root - flakeFile = getFile "flake.nix"; - - # Example of importing modules recursively - modules = importModulesRecursive ./modules; - - # Example of scanning systems - allSystems = scanSystems ./systems; - - # Example of filtering systems - nixosSystems = filterNixOSSystems allSystems; - darwinSystems = filterDarwinSystems allSystems; - - # Example of scanning homes - allHomes = scanHomes ./homes; - - # Example of using these functions together - nixosConfigurations = lib.mapAttrs' ( - _name: - { system, hostname, ... }: - { - name = hostname; - value = lib.nixosSystem { - inherit system; - modules = [ - { networking.hostName = hostname; } - ] - ++ importModulesRecursive ./modules/nixos; - }; - } - ) nixosSystems; -} diff --git a/lib/examples/home-sops.nix b/lib/examples/home-sops.nix deleted file mode 100644 index 7585e93..0000000 --- a/lib/examples/home-sops.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ - config, - lib, - pkgs, - namespace, - ... -}: -let - inherit (lib.${namespace}.module) mkModule mkOpt; -in -mkModule { - name = "sops"; - description = "SOPS secret management for home-manager"; - options = { - defaultSopsFile = mkOpt lib.types.path null "Default sops file."; - - sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [ ] "SSH Key paths to use."; - }; - config = { - home.packages = with pkgs; [ - age - sops - ssh-to-age - ]; - - sops = { - inherit (config.${namespace}.sops) defaultSopsFile; - defaultSopsFormat = "yaml"; - - age = { - generateKey = true; - keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt"; - sshKeyPaths = [ - "${config.home.homeDirectory}/.ssh/id_ed25519" - ] - ++ config.${namespace}.sops.sshKeyPaths; - }; - }; - }; -} diff --git a/lib/examples/reverseproxy.nix b/lib/examples/reverseproxy.nix deleted file mode 100644 index 8b073f2..0000000 --- a/lib/examples/reverseproxy.nix +++ /dev/null @@ -1,117 +0,0 @@ -# Example usage of the reverse proxy utilities -{ lib, namespace, ... }: -let - inherit (lib.${namespace} - lib.reverseproxy) - mkReverseProxy - mkReverseProxies - templates - middlewares - urls - ; -in -{ - # Example 1: Simple reverse proxy for a local service - simpleProxy = mkReverseProxy { - name = "myapp"; - subdomain = "myapp"; - url = "http://127.0.0.1:3000"; - }; - - # Example 2: Authenticated service with custom middlewares - authProxy = mkReverseProxy { - name = "admin-panel"; - subdomain = "admin"; - url = "http://127.0.0.1:8080"; - middlewares = middlewares.authBasic; - }; - - # Example 3: Container-based service - containerProxy = mkReverseProxy { - name = "nextcloud"; - subdomain = "cloud"; - url = urls.container "nextcloud" 80; - middlewares = middlewares.basic; - }; - - # Example 4: Multiple proxies at once - multipleProxies = mkReverseProxies [ - { - name = "grafana"; - subdomain = "grafana"; - url = urls.localhost 3000; - middlewares = middlewares.authBasic; - } - { - name = "prometheus"; - subdomain = "prometheus"; - url = urls.localhost 9090; - middlewares = middlewares.internal; - } - { - name = "alertmanager"; - subdomain = "alerts"; - url = urls.localhost 9093; - middlewares = middlewares.authBasic; - } - ]; - - # Example 5: Using templates for common patterns - webappExample = templates.webapp { - name = "webapp"; - subdomain = "app"; - port = 8080; - }; - - authWebappExample = templates.authWebapp { - name = "secure-app"; - subdomain = "secure"; - port = 9000; - }; - - containerExample = templates.containerService { - name = "gitea"; - subdomain = "git"; - containerName = "gitea"; - port = 3000; - }; - - internalExample = templates.internalService { - name = "internal-api"; - subdomain = "api-internal"; - port = 8000; - }; - - # Example 6: Custom domain and advanced configuration - customProxy = mkReverseProxy { - name = "custom-service"; - subdomain = "custom"; - url = "http://10.0.1.100:8080"; - domain = "example.com"; - priority = 20; - rule = "Host(`custom.example.com`) && PathPrefix(`/api`)"; - middlewares = [ - "crowdsec" - "whitelist-geoblock" - "rate-limit" - ]; - }; - - # Example usage in a Traefik configuration: - # - # mjallen.services.traefik = { - # enable = true; - # extraServices = multipleProxies.extraServices; - # extraRouters = multipleProxies.extraRouters; - # }; - # - # Or for individual proxies: - # - # mjallen.services.traefik = { - # enable = true; - # extraServices = [ simpleProxy.service ]; - # extraRouters = [{ - # inherit (simpleProxy.router) subdomain entryPoints middlewares; - # service = simpleProxy.router.service; - # }]; - # }; -} diff --git a/lib/examples/sops.nix b/lib/examples/sops.nix deleted file mode 100644 index 28e03d1..0000000 --- a/lib/examples/sops.nix +++ /dev/null @@ -1,45 +0,0 @@ -{ - config, - lib, - namespace, - ... -}: -let - inherit (lib.${namespace}.module) mkModule mkOpt mkBoolOpt; -in -mkModule { - name = "sops"; - description = "SOPS secret management"; - options = { - defaultSopsFile = mkOpt lib.types.path null "Default sops file."; - - generateAgeKey = mkBoolOpt true "Whether to automatically generate an age key if one doesn't exist."; - - ageKeyPath = - mkOpt (lib.types.nullOr lib.types.str) null - "Custom path to the age key file. If null, will use the default path."; - - sshKeyPaths = mkOpt (lib.types.listOf lib.types.str) [ - "/etc/ssh/ssh_host_ed25519_key" - ] "SSH Key paths to use."; - - validateSopsFiles = mkBoolOpt false "Whether to validate that sops files exist."; - }; - config = { - sops = { - inherit (config.${namespace}.sops) defaultSopsFile validateSopsFiles; - - age = { - inherit (config.${namespace}.sops) generateAgeKey; - - keyFile = - if config.${namespace}.sops.ageKeyPath != null then - config.${namespace}.sops.ageKeyPath - else - "${config.users.users.${config.${namespace}.user.name}.home}/.config/sops/age/keys.txt"; - - sshKeyPaths = config.${namespace}.sops.sshKeyPaths; - }; - }; - }; -} diff --git a/lib/examples/system-utils.nix b/lib/examples/system-utils.nix deleted file mode 100644 index 7949194..0000000 --- a/lib/examples/system-utils.nix +++ /dev/null @@ -1,132 +0,0 @@ -{ inputs, namespace, ... }: -let - inherit (inputs.self.${namespace} - lib.system.common) - mkExtendedLib - mkNixpkgsConfig - mkHomeConfigs - mkHomeManagerConfig - mkSpecialArgs - ; -in -{ - # Example of creating NixOS configurations - nixosConfigurations = - let - # Get all systems - allSystems = inputs.self.${namespace} - lib.file.scanSystems ../systems; - - # Filter for NixOS systems - nixosSystems = inputs.self.${namespace} - lib.file.filterNixOSSystems allSystems; - in - inputs.nixpkgs.lib.mapAttrs' ( - _name: - { system, hostname, ... }: - let - # Create extended lib with mjallen-lib - extendedLib = mkExtendedLib inputs.self inputs.nixpkgs; - - # Find matching home configurations for this system - matchingHomes = mkHomeConfigs { - flake = inputs.self; - inherit system hostname; - }; - - # Create home-manager configuration - homeManagerConfig = mkHomeManagerConfig { - inherit - extendedLib - inputs - system - matchingHomes - ; - isNixOS = true; - }; - in - { - name = hostname; - value = inputs.nixpkgs.lib.nixosSystem { - inherit system; - - # Pass special arguments to modules - specialArgs = mkSpecialArgs { - inherit inputs hostname extendedLib; - username = "mjallen"; - }; - - modules = [ - # Set lib to extended lib - { _module.args.lib = extendedLib; } - - # Configure nixpkgs - { - nixpkgs = { - inherit system; - } - // mkNixpkgsConfig inputs.self; - } - - # Import home-manager module - inputs.home-manager.nixosModules.home-manager - - # Auto-inject home configurations - homeManagerConfig - - # Import all nixos modules recursively - ../${system}/${hostname} - ] - ++ (extendedLib.${namespace}.file.importModulesRecursive ../modules/nixos); - }; - } - ) nixosSystems; - - # Example of creating home-manager configurations - homeConfigurations = - let - # Get all homes - allHomes = inputs.self.${namespace} - lib.file.scanHomes ../homes; - in - inputs.nixpkgs.lib.mapAttrs' ( - _name: - { - system, - username, - hostname, - userAtHost, - path, - ... - }: - let - # Create extended lib with mjallen-lib - extendedLib = mkExtendedLib inputs.self inputs.nixpkgs; - in - { - name = userAtHost; - value = inputs.home-manager.lib.homeManagerConfiguration { - pkgs = import inputs.nixpkgs { - inherit system; - inherit ((mkNixpkgsConfig inputs.self)) config overlays; - }; - - extraSpecialArgs = { - inherit - inputs - hostname - username - system - ; - inherit (inputs) self; - lib = extendedLib; - }; - - modules = [ - # Set lib to extended lib - { _module.args.lib = extendedLib; } - - # Import the home configuration - path - ] - ++ (extendedLib.${namespace}.file.importModulesRecursive ../modules/home); - }; - } - ) allHomes; -} diff --git a/lib/module/default.nix b/lib/module/default.nix index cf02a38..5a2c664 100644 --- a/lib/module/default.nix +++ b/lib/module/default.nix @@ -14,8 +14,6 @@ let mkDefault mkForce ; - - base64Lib = import ../base64 { inherit inputs; }; in rec { @@ -26,7 +24,9 @@ rec { mod: mod.systems or [ ] == [ ] || builtins.elem system (mod.systems or [ ]) ) modules; - # Create a module with common options + # Create a NixOS module with standard options (enable, port, reverseProxy, + # firewall, user, postgresql, redis) and optional caller-supplied options and + # config. All config is gated behind `cfg.enable`. mkModule = { name, @@ -51,9 +51,6 @@ rec { defaultConfig = { # Caddy reverse proxy: when reverseProxy.enable = true, contribute this # service's named-matcher block into the shared wildcard virtual host. - # The TLS block stays in the caddy module itself; all services merge - # their handle blocks into the same "*.${domain}" extraConfig via the - # lines type (which concatenates automatically). services.caddy.virtualHosts."*.${cfg.reverseProxy.domain}" = lib.mkIf cfg.reverseProxy.enable { extraConfig = '' @${name} host ${fqdn} @@ -79,20 +76,15 @@ rec { groups.${name} = { }; }; - systemd.services.${serviceName} = { - requires = [ - "media-nas-main.mount" - # "openvpn-us.protonvpn.udp.service" - ]; - after = lib.mkForce [ - "media-nas-main.mount" - # "openvpn-us.protonvpn.udp.service" - ]; - # serviceConfig = { - # NetworkNamespacePath = lib.mkIf cfg.enableVpn "/run/netns/vpn"; - # # Consider also setting DNS *inside* the netns (see note below). - # }; - }; + # Ensure the service waits for the filesystem that hosts configDir and + # dataDir to be mounted before starting. RequiresMountsFor is the + # idiomatic systemd way to express this: if the paths live on the root + # filesystem the directive is silently ignored, so it is safe on every + # host — not just the NAS. + systemd.services.${serviceName}.unitConfig.RequiresMountsFor = [ + cfg.configDir + cfg.dataDir + ]; services = { postgresql = lib.mkIf cfg.configureDb { @@ -110,12 +102,6 @@ rec { port = cfg.redis.port; }; }; - - # systemd.tmpfiles.rules = [ - # "d ${cfg.configDir} 0700 ${name} ${name} - -" - # # "d ${cfg.configDir}/server-files 0775 ${name} ${name} - -" - # # "d ${cfg.configDir}/user-files 0775 ${name} ${name} - -" - # ]; }; in { lib, ... }: @@ -134,44 +120,42 @@ rec { options = { enable = lib.mkEnableOption description; - port = mkOpt types.int 80 "Port for ${name} to be hosted on"; + port = mkOpt types.int 80 "Port for ${name} to listen on"; - configDir = mkOpt types.str "/media/nas/main/appdata" "Path to the config dir"; + configDir = mkOpt types.str "/var/lib/${name}" "Path to the config directory"; - dataDir = mkOpt types.str "/media/nas/main" "Path to the data dir"; + dataDir = mkOpt types.str "/var/lib/${name}/data" "Path to the data directory"; - createUser = mkBoolOpt false "create a user for this module/service"; + createUser = mkBoolOpt false "Create a dedicated system user for this service"; - configureDb = mkBoolOpt false "Manage db for this service"; + configureDb = mkBoolOpt false "Manage a PostgreSQL database for this service"; - environmentFile = mkOpt types.str "" "Environment File"; + environmentFile = + mkOpt (types.nullOr types.str) null + "Path to an environment file (EnvironmentFile=)"; - puid = mkOpt types.str "911" "default user id"; + puid = mkOpt types.str "911" "User ID for container-based services"; - pgid = mkOpt types.str "1000" "default group id"; + pgid = mkOpt types.str "100" "Group ID for container-based services"; - timeZone = mkOpt types.str "America/Chicago" "default timezone"; + timeZone = mkOpt types.str "UTC" "Timezone for container-based services"; - listenAddress = mkOpt types.str "0.0.0.0" "Environment File"; + listenAddress = mkOpt types.str "0.0.0.0" "Listen address"; - openFirewall = mkBoolOpt true "Open the firewall"; - - enableVpn = mkBoolOpt true "Enable routing through VPN"; + openFirewall = mkBoolOpt true "Open firewall ports for this service"; redis = { - enable = lib.mkEnableOption "enable redis"; - - port = mkOpt types.int 80 "Port for ${name} redis to be hosted on"; + enable = lib.mkEnableOption "a dedicated Redis server for this service"; + port = mkOpt types.int 6379 "Redis port for ${name}"; }; hashedPassword = - mkOpt (types.nullOr types.str) - "$y$j9T$EkPXmsmIMFFZ.WRrBYCxS1$P0kwo6e4.WM5DsqUcEqWC3MrZp5KfCjxffraMFZWu06" - "Hashed password for code-server authentication"; + mkOpt (types.nullOr types.str) null + "Hashed password (e.g. for web-based authentication)"; extraEnvironment = mkOpt (types.attrsOf types.str) { } - "Extra environment variables for code-server"; + "Extra environment variables passed to the service"; reverseProxy = mkReverseProxyOpt name; } @@ -181,58 +165,15 @@ rec { }; }; - # container - mkContainer = - { - name, - localAddress ? "127.0.0.1", - ports ? [ 80 ], - bindMounts ? { }, - config ? { }, - }: - { lib, ... }: - { - containers.${name} = { - inherit localAddress bindMounts; - - config = config // { - networking = { - firewall = { - enable = true; - allowedTCPPorts = ports; - }; - # Use systemd-resolved inside the container - # Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686 - useHostResolvConf = lib.mkForce false; - }; - - services.resolved.enable = true; - system.stateVersion = "23.11"; - }; - autoStart = lib.mkDefault true; - privateNetwork = lib.mkDefault true; - hostAddress = lib.mkDefault "10.0.1.3"; - }; - - networking = { - nat.forwardPorts = map (port: { - destination = lib.mkDefault "${localAddress}:${toString port}"; - sourcePort = lib.mkDefault port; - }) ports; - firewall = { - allowedTCPPorts = ports; - allowedUDPPorts = ports; - }; - }; - }; - - # Migrated mjallen utilities + # --------------------------------------------------------------------------- # Option creation helpers + # --------------------------------------------------------------------------- + mkOpt = type: default: description: mkOption { inherit type default description; }; - mkOpt' = type: default: mkOpt type default null; + mkOpt' = type: default: mkOpt type default ""; mkBoolOpt = mkOpt types.bool; @@ -245,26 +186,28 @@ rec { domain = mkOpt types.str "mjallen.dev" "Base domain for the reverse proxy"; - # Override the upstream URL if the backend is not on localhost at cfg.port. - # Leave empty to use http://127.0.0.1: automatically. upstreamUrl = mkOpt (types.nullOr types.str) null - "Override upstream URL (e.g. for services on a different host). Defaults to http://127.0.0.1:."; + "Override upstream URL (e.g. for a service on a different host). Defaults to http://127.0.0.1:."; - # Extra Caddyfile directives inserted inside the virtual host block. - extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives for this virtual host block"; + extraCaddyConfig = mkOpt types.lines "" "Extra Caddyfile directives inside this virtual host block"; }; - # Standard enable/disable patterns + # --------------------------------------------------------------------------- + # Convenience shorthands + # --------------------------------------------------------------------------- + enabled = { enable = true; }; - disabled = { enable = false; }; + # --------------------------------------------------------------------------- # String utilities + # --------------------------------------------------------------------------- + capitalize = s: let @@ -272,10 +215,16 @@ rec { in if len == 0 then "" else (toUpper (substring 0 1 s)) + (substring 1 len s); + # --------------------------------------------------------------------------- # Boolean utilities + # --------------------------------------------------------------------------- + boolToNum = bool: if bool then 1 else 0; + # --------------------------------------------------------------------------- # Attribute manipulation utilities + # --------------------------------------------------------------------------- + default-attrs = mapAttrs (_key: mkDefault); force-attrs = mapAttrs (_key: mkForce); @@ -284,4 +233,3 @@ rec { nested-force-attrs = mapAttrs (_key: force-attrs); } -// base64Lib diff --git a/lib/reverseproxy/default.nix b/lib/reverseproxy/default.nix deleted file mode 100644 index 0170150..0000000 --- a/lib/reverseproxy/default.nix +++ /dev/null @@ -1,220 +0,0 @@ -{ inputs }: -let - inherit (inputs.nixpkgs.lib) - listToAttrs - nameValuePair - ; -in -rec { - # Create a service configuration for Traefik - mkService = - { - name, - url, - loadBalancer ? { }, - }: - { - inherit name url; - config = { - loadBalancer = { - servers = [ { inherit url; } ]; - } - // loadBalancer; - }; - }; - - # Create a router configuration for Traefik - mkRouter = - { - subdomain, - domain ? "mjallen.dev", - service, - entryPoints ? [ "websecure" ], - middlewares ? [ - "crowdsec" - "whitelist-geoblock" - ], - priority ? null, - rule ? null, - tls ? { - certResolver = "letsencrypt"; - }, - }: - { - inherit - subdomain - service - entryPoints - middlewares - ; - config = { - inherit - entryPoints - service - middlewares - tls - ; - rule = if rule != null then rule else "Host(`${subdomain}.${domain}`)"; - } - // (if priority != null then { inherit priority; } else { }); - }; - - # Create both service and router for a simple reverse proxy setup - mkReverseProxy = - { - name, - subdomain, - url, - domain ? "mjallen.dev", - entryPoints ? [ "websecure" ], - middlewares ? [ - "crowdsec" - "whitelist-geoblock" - ], - priority ? null, - rule ? null, - tls ? { - certResolver = "letsencrypt"; - }, - loadBalancer ? { }, - }: - { - service = mkService { - inherit name url loadBalancer; - }; - router = mkRouter { - inherit - subdomain - domain - entryPoints - middlewares - priority - rule - tls - ; - service = name; - }; - }; - - # Convert a list of services to the format expected by Traefik module - servicesToConfig = - services: listToAttrs (map (service: nameValuePair service.name service.config) services); - - # Convert a list of routers to the format expected by Traefik module - routersToConfig = - routers: listToAttrs (map (router: nameValuePair router.subdomain router.config) routers); - - # Helper to create multiple reverse proxies at once - mkReverseProxies = - proxies: - let - results = map mkReverseProxy proxies; - services = map (result: result.service) results; - routers = map (result: result.router) results; - in - { - services = servicesToConfig services; - routers = routersToConfig routers; - extraServices = services; - extraRouters = map (router: { - inherit (router) subdomain entryPoints middlewares; - service = router.service; - }) routers; - }; - - # Common middleware configurations - middlewares = { - # Authentication middleware - auth = [ "authentik" ]; - - # Basic security (default) - basic = [ - "crowdsec" - "whitelist-geoblock" - ]; - - # Internal only access - internal = [ - "crowdsec" - "whitelist-geoblock" - "internal-ipallowlist" - ]; - - # WebSocket support - websocket = [ - "crowdsec" - "whitelist-geoblock" - "onlyoffice-websocket" - ]; - - # Authenticated with basic security - authBasic = [ - "crowdsec" - "whitelist-geoblock" - "authentik" - ]; - }; - - # Common service URL builders - urls = { - # Local container service - container = - containerName: port: "http://\${config.containers.${containerName}.localAddress}:${toString port}"; - - # Local host service - localhost = port: "http://127.0.0.1:${toString port}"; - - # Network service - network = ip: port: "http://${ip}:${toString port}"; - - # Server IP service (using your server IP pattern) - server = port: "http://\${serverIp}:${toString port}"; - }; - - # Pre-configured reverse proxy templates - templates = { - # Standard web application - webapp = - { port, ... }@args: - mkReverseProxy ( - { - url = urls.localhost port; - middlewares = middlewares.basic; - } - // args - ); - - # Authenticated web application - authWebapp = - { port, ... }@args: - mkReverseProxy ( - { - url = urls.localhost port; - middlewares = middlewares.authBasic; - } - // args - ); - - # Container-based service - containerService = - { containerName, port, ... }@args: - mkReverseProxy ( - { - url = urls.container containerName port; - middlewares = middlewares.basic; - } - // args - ); - - # Internal-only service - internalService = - { port, ... }@args: - mkReverseProxy ( - { - url = urls.localhost port; - middlewares = middlewares.internal; - } - // args - ); - }; -} diff --git a/lib/system/common.nix b/lib/system/common.nix deleted file mode 100644 index c40a9c2..0000000 --- a/lib/system/common.nix +++ /dev/null @@ -1,103 +0,0 @@ -{ inputs, namespace }: -let - inherit (inputs.nixpkgs.lib) filterAttrs mapAttrs'; -in -{ - mkExtendedLib = - flake: nixpkgs: - nixpkgs.lib.extend ( - _final: _prev: { - mjallen = flake.${namespace} - lib; - } - ); - - mkNixpkgsConfig = flake: { - overlays = builtins.attrValues flake.overlays; - config = { - allowAliases = false; - allowUnfree = true; - permittedInsecurePackages = [ - # Add any permitted insecure packages here - "mbedtls-2.28.10" - ]; - }; - }; - - mkHomeConfigs = - { - flake, - system, - hostname, - }: - let - inherit (flake.${namespace} - lib.file) scanHomes; - homesPath = ../../homes; - allHomes = scanHomes homesPath; - in - filterAttrs ( - _name: homeConfig: homeConfig.system == system && homeConfig.hostname == hostname - ) allHomes; - - mkHomeManagerConfig = - { - extendedLib, - inputs, - system, - matchingHomes, - isNixOS ? true, - }: - if matchingHomes != { } then - { - home-manager = { - useGlobalPkgs = true; - useUserPackages = true; - extraSpecialArgs = { - inherit inputs system; - inherit (inputs) self; - lib = extendedLib; - }; - sharedModules = [ - { _module.args.lib = extendedLib; } - ] - ++ (extendedLib.${namespace}.file.importModulesRecursive ../../modules/home); - users = mapAttrs' (_name: homeConfig: { - name = homeConfig.username; - value = { - imports = [ homeConfig.path ]; - home = { - inherit (homeConfig) username; - homeDirectory = inputs.nixpkgs.lib.mkDefault ( - if isNixOS then "/home/${homeConfig.username}" else "/Users/${homeConfig.username}" - ); - }; - } - // ( - if isNixOS then - { - _module.args.username = homeConfig.username; - } - else - { } - ); - }) matchingHomes; - }; - } - else - { }; - - mkSpecialArgs = - { - inputs, - hostname, - username, - extendedLib, - }: - { - inherit inputs hostname username; - inherit (inputs) self; - lib = extendedLib; - namespace = "mjallen"; - format = "system"; - host = hostname; - }; -} diff --git a/lib/system/default.nix b/lib/system/default.nix deleted file mode 100644 index 193c703..0000000 --- a/lib/system/default.nix +++ /dev/null @@ -1,5 +0,0 @@ -{ inputs }: -{ - # Common utilities used by system builders - common = import ./common.nix { inherit inputs; }; -} diff --git a/modules/nixos/services/grafana/default.nix b/modules/nixos/services/grafana/default.nix index d6f1d20..525f5b2 100755 --- a/modules/nixos/services/grafana/default.nix +++ b/modules/nixos/services/grafana/default.nix @@ -77,7 +77,7 @@ let }; }; - dataDir = "/media/nas/main/nix-app-data/grafana"; + dataDir = "${cfg.configDir}/grafana"; provision = { enable = true; diff --git a/modules/nixos/services/owncloud/default.nix b/modules/nixos/services/owncloud/default.nix index dd5eeb0..c29c787 100755 --- a/modules/nixos/services/owncloud/default.nix +++ b/modules/nixos/services/owncloud/default.nix @@ -34,12 +34,12 @@ in dataPath = mkOption { type = types.str; - default = "/media/nas/main/ocis"; + default = "/var/lib/ocis"; }; configPath = mkOption { type = types.str; - default = "/media/nas/main/nix-app-data/ocis"; + default = "/var/lib/ocis/config"; }; puid = mkOption { diff --git a/modules/nixos/services/your-spotify/options.nix b/modules/nixos/services/your-spotify/options.nix index dea5d89..88f86b4 100755 --- a/modules/nixos/services/your-spotify/options.nix +++ b/modules/nixos/services/your-spotify/options.nix @@ -36,7 +36,7 @@ with lib; configPath = mkOption { type = types.str; - default = "/media/nas/main/nix-app-data/your_spotify"; + default = "/var/lib/your-spotify"; }; puid = mkOption { @@ -46,12 +46,12 @@ with lib; pgid = mkOption { type = types.str; - default = "1000"; + default = "100"; }; timeZone = mkOption { type = types.str; - default = "America/Chicago"; + default = "UTC"; }; }; } diff --git a/systems/x86_64-linux/jallen-nas/default.nix b/systems/x86_64-linux/jallen-nas/default.nix index 0a6513c..c015414 100755 --- a/systems/x86_64-linux/jallen-nas/default.nix +++ b/systems/x86_64-linux/jallen-nas/default.nix @@ -11,6 +11,7 @@ in { imports = [ ./boot.nix + ./nas-defaults.nix ./apps.nix ./disabled.nix # ./nas-pool.nix @@ -18,7 +19,6 @@ in ./services.nix ./sops.nix ./vpn.nix - # testcontainer ]; services.kmscon = disabled; diff --git a/systems/x86_64-linux/jallen-nas/nas-defaults.nix b/systems/x86_64-linux/jallen-nas/nas-defaults.nix new file mode 100644 index 0000000..6341c76 --- /dev/null +++ b/systems/x86_64-linux/jallen-nas/nas-defaults.nix @@ -0,0 +1,86 @@ +# NAS-wide defaults for all mkModule services. +# +# Every service's configDir and dataDir default to paths on the NAS bcachefs +# pool. Setting them here via lib.mkDefault means individual service +# declarations in apps.nix only need to override when they deviate from the +# convention, keeping apps.nix concise. +# +# The companion RequiresMountsFor in mkModule uses these paths to derive the +# correct systemd mount dependency automatically — no service needs to hardcode +# "media-nas-main.mount" by name. +{ lib, namespace, ... }: +let + appdata = "/media/nas/main/appdata"; + data = "/media/nas/main"; + + svcDefault = name: { + ${namespace}.services.${name} = { + configDir = lib.mkDefault appdata; + dataDir = lib.mkDefault data; + }; + }; +in +{ + # Bespoke services that define their own path options (not via mkModule). + # Set NAS-specific paths here so the module defaults stay generic. + ${namespace}.services.your_spotify.configPath = lib.mkDefault "${appdata}/your_spotify"; + ${namespace}.services.ocis = { + dataPath = lib.mkDefault "${data}/ocis"; + configPath = lib.mkDefault "${appdata}/ocis"; + }; + + imports = map svcDefault [ + "actual" + "ai" + "arrs" + "attic" + "authentik" + "authentikRac" + "booklore" + "caddy" + "calibre" + "calibre-web" + "code-server" + "collabora" + "coturn" + "crowdsec" + "dispatcharr" + "free-games-claimer" + "gitea" + "glance" + "glances" + "grafana" + "guacd" + "headscale" + "immich" + "jellyfin" + "jellyseerr" + "lubelogger" + "manyfold" + "matrix" + "minecraft" + "mongodb" + "nebula" + "nebula-lighthouse" + "netbootxyz" + "nextcloud" + "ntfy" + "onlyoffice" + "opencloud" + "orca-slicer" + "paperless" + "paperless-ai" + "protonmail-bridge" + "restic" + "sparky-fitness" + "sparky-fitness-server" + "sparky-fitness-db" + "sunshine" + "tdarr" + "termix" + "tunarr" + "unmanic" + "uptime-kuma" + "wyoming" + ]; +}