# Home Manager Module for Port Management # # This module provides centralized port management for Home Manager configurations. # Define ports once and use them consistently across user services, with support # for host-specific overrides. # # Usage in your Home Manager configuration: # # # In your home.nix or flake: # imports = [ inputs.m3ta-nixpkgs.homeManagerModules.default ]; # # m3ta.ports = { # enable = true; # # # Define your default ports # definitions = { # vscodium = 8080; # jupyter = 8888; # dev-server = 3000; # local-api = 8000; # docs-preview = 4000; # }; # # # Define host-specific overrides # hostOverrides = { # laptop = { # dev-server = 3001; # vscodium = 8081; # }; # desktop = { # jupyter = 9999; # }; # }; # # # Set the current hostname # currentHost = "laptop"; # Or use config.networking.hostName if available # }; # # # Use ports in your configuration: # home.file.".config/myapp/config.json".text = builtins.toJSON { # port = config.m3ta.ports.get "dev-server"; # }; # # # Generate environment variables: # home.sessionVariables = { # DEV_SERVER_PORT = toString (config.m3ta.ports.get "dev-server"); # JUPYTER_PORT = toString (config.m3ta.ports.get "jupyter"); # }; { config, lib, pkgs, ... }: with lib; let cfg = config.m3ta.ports; portsLib = import ../../lib/ports.nix {inherit lib;}; portHelpers = if cfg.enable then portsLib.mkPortHelpers { ports = cfg.definitions; hostPorts = cfg.hostOverrides; } else null; in { options.m3ta.ports = { enable = mkEnableOption "centralized port management for Home Manager"; definitions = mkOption { type = types.attrsOf types.port; default = {}; description = "Default port definitions for user services."; }; hostOverrides = mkOption { type = types.attrsOf (types.attrsOf types.port); default = {}; description = "Host-specific port overrides."; }; currentHost = mkOption { type = types.nullOr types.str; default = null; description = "Hostname to use for port resolution."; }; # Internal computed options get = mkOption { type = types.raw; readOnly = true; internal = true; }; getForHost = mkOption { type = types.raw; readOnly = true; internal = true; }; all = mkOption { type = types.attrsOf types.port; readOnly = true; internal = true; }; allForHost = mkOption { type = types.raw; readOnly = true; internal = true; }; services = mkOption { type = types.listOf types.str; readOnly = true; internal = true; }; # Env var generation generateEnvVars = mkOption { type = types.bool; default = false; description = "Generate environment variables for all ports."; }; envVarPrefix = mkOption { type = types.str; default = "PORT_"; description = "Prefix for generated environment variables."; }; }; config = mkIf cfg.enable { m3ta.ports.get = service: portHelpers.getPort service cfg.currentHost; m3ta.ports.getForHost = host: service: portHelpers.getPort service host; m3ta.ports.all = portHelpers.getHostPorts cfg.currentHost; m3ta.ports.allForHost = portHelpers.getHostPorts; m3ta.ports.services = portHelpers.listServices; home.sessionVariables = mkIf cfg.generateEnvVars ( let toEnvVarName = service: cfg.envVarPrefix + (lib.toUpper (builtins.replaceStrings ["-"] ["_"] service)); in builtins.listToAttrs ( map (service: { name = toEnvVarName service; value = toString (cfg.get service); }) cfg.services ) ); home.file.".config/m3ta/ports.json".text = builtins.toJSON { hostname = cfg.currentHost; ports = cfg.all; allDefinitions = cfg.definitions; hostOverrides = cfg.hostOverrides; }; }; }