From 66efae302fde7007359cebf1e086a00472688418 Mon Sep 17 00:00:00 2001 From: alexion Date: Tue, 13 Oct 2026 21:43:50 -0400 Subject: [PATCH] fix(nixos): address Nix review findings Render Palworld secrets through its documented settings file and remove stale RCON configuration. Harden generated commands, centralize shared modules, and codify the reviewed Nix conventions. --- configs/nixos/guests/reverse-proxy.nix | 53 +++----- configs/nixos/hosts/pikachu/default.nix | 1 - configs/nixos/hosts/zeus/default.nix | 5 +- .../nixos/modules/services/games/palworld.nix | 115 ++++++++++++------ .../nixos/modules/services/games/valheim.nix | 2 +- configs/nixos/modules/services/steamcmd.nix | 9 +- configs/nixos/modules/shell/fish/default.nix | 2 +- src/dotfiles/default.nix | 9 +- src/dotfiles/guests.nix | 11 +- src/dotfiles/hosts.nix | 3 - src/flake/apps.nix | 1 + src/skills/style/nix/rules/flake.md | 10 ++ src/skills/style/nix/rules/general.md | 88 ++++++++++++++ 13 files changed, 215 insertions(+), 94 deletions(-) diff --git a/configs/nixos/guests/reverse-proxy.nix b/configs/nixos/guests/reverse-proxy.nix index 10e378e..15ae856 100644 --- a/configs/nixos/guests/reverse-proxy.nix +++ b/configs/nixos/guests/reverse-proxy.nix @@ -12,43 +12,22 @@ in interior = { modules.services.reverse-proxy.enable = true; - services.nginx.virtualHosts = { - "games.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - "git.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - "photos.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - "plex.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - "servers.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - "todo.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - "wings.alexion.dev" = { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://10.23.20.32"; - }; - }; + services.nginx.virtualHosts = + lib.genAttrs + [ + "games.alexion.dev" + "git.alexion.dev" + "photos.alexion.dev" + "plex.alexion.dev" + "servers.alexion.dev" + "todo.alexion.dev" + "wings.alexion.dev" + ] + (_domain: { + forceSSL = true; + enableACME = true; + locations."/".proxyPass = "http://10.23.20.32"; + }); networking.firewall.allowedTCPPorts = [ 2022 ]; diff --git a/configs/nixos/hosts/pikachu/default.nix b/configs/nixos/hosts/pikachu/default.nix index b7bdf4d..8f70259 100644 --- a/configs/nixos/hosts/pikachu/default.nix +++ b/configs/nixos/hosts/pikachu/default.nix @@ -60,7 +60,6 @@ serverName = "Tracion"; autoStart = false; adminPasswordSecret = "services/game-servers/admin/password"; - publicIP = config.guests.palworld.address; reverseProxy = { enable = true; route = { diff --git a/configs/nixos/hosts/zeus/default.nix b/configs/nixos/hosts/zeus/default.nix index 14f8b19..4bb04a8 100644 --- a/configs/nixos/hosts/zeus/default.nix +++ b/configs/nixos/hosts/zeus/default.nix @@ -1,6 +1,5 @@ { config, - lib, ... }: # zeus — Ryzen desktop with AMD graphics. @@ -8,9 +7,9 @@ # `fileSystems` are derived from it, none declared here. { imports = [ + ./hardware-configuration.nix ./disk.nix - ] - ++ lib.optional (builtins.pathExists ./hardware-configuration.nix) ./hardware-configuration.nix; + ]; nixpkgs.hostPlatform = "x86_64-linux"; diff --git a/configs/nixos/modules/services/games/palworld.nix b/configs/nixos/modules/services/games/palworld.nix index 3c04327..65f04d0 100644 --- a/configs/nixos/modules/services/games/palworld.nix +++ b/configs/nixos/modules/services/games/palworld.nix @@ -62,18 +62,6 @@ description = "Start the Palworld server after the guest reaches network readiness."; }; - rcon = { - enable = lib.mkEnableOption "Palworld RCON" // { - default = true; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 25575; - description = "TCP port for Palworld RCON."; - }; - }; - passwordFile = lib.mkOption { type = lib.types.path; description = "Runtime file containing the Palworld server password."; @@ -89,65 +77,120 @@ let service = config.modules.services.games.palworld; savedDir = "${service.installDir}/Pal/Saved"; + defaultSettingsFile = "${service.installDir}/DefaultPalWorldSettings.ini"; + settingsFile = "${savedDir}/Config/LinuxServer/PalWorldSettings.ini"; + renderSettingsScript = pkgs.writeText "render-palworld-settings.py" '' + import json + import os + from pathlib import Path + import re + import sys + import tempfile + + default_path, settings_path, server_name, password_path, admin_password_path = sys.argv[1:] + default_path = Path(default_path) + settings_path = Path(settings_path) + + source_path = settings_path if settings_path.exists() else default_path + text = source_path.read_text(encoding="utf-8") + + def read_secret(path): + return Path(path).read_text(encoding="utf-8").rstrip("\r\n") + + def set_string_setting(text, name, value): + assignment = f"{name}={json.dumps(value, ensure_ascii=False)}" + pattern = re.compile(rf'(? to .bak"; argumentNames = "filename"; - body = "cp $filename $filename.bak"; + body = "cp -- $filename $filename.bak"; }; copy = { diff --git a/src/dotfiles/default.nix b/src/dotfiles/default.nix index c7421ac..86721c1 100644 --- a/src/dotfiles/default.nix +++ b/src/dotfiles/default.nix @@ -22,21 +22,21 @@ let root = root + "/registry"; }; - # TODO: Refactor guest-module composition. guestModules = import ./guests.nix { inherit inputs registry + repositoryModules specialArgs util ; - repositoryModules = modules; root = root + "/guests"; }; - modules.imports = [ + repositoryModules.imports = [ { nixpkgs.overlays = [ self.overlays.custom ]; } + registry.module ] ++ util.collectNixFiles (root + "/modules"); @@ -47,8 +47,7 @@ import ./hosts.nix { lib specialArgs guestModules + repositoryModules ; - registryModule = registry.module; - repositoryModules = modules; root = root + "/hosts"; } diff --git a/src/dotfiles/guests.nix b/src/dotfiles/guests.nix index e0e5deb..f4bec3c 100644 --- a/src/dotfiles/guests.nix +++ b/src/dotfiles/guests.nix @@ -10,7 +10,12 @@ let files = util.collectNixFiles root; mkGuest = name: - { config, lib, ... }: + { + config, + lib, + pkgs, + ... + }: let cfg = config.guests.${name}; @@ -18,10 +23,11 @@ let directoryScript = lib.concatStringsSep "\n" ( lib.mapAttrsToList (_: mount: '' - ${config.system.path}/bin/install -d \ + ${lib.getExe' pkgs.coreutils "install"} -d \ ${lib.optionalString (mount.owner != null) "-o ${lib.escapeShellArg (toString mount.owner)}"} \ ${lib.optionalString (mount.group != null) "-g ${lib.escapeShellArg mount.group}"} \ ${lib.optionalString (mount.mode != null) "-m ${lib.escapeShellArg mount.mode}"} \ + -- \ ${lib.escapeShellArg mount.directory} '') directoryMounts ); @@ -254,7 +260,6 @@ let inputs.stylix.nixosModules.stylix repositoryModules - registry.module cfg.interior { diff --git a/src/dotfiles/hosts.nix b/src/dotfiles/hosts.nix index 5ce6e53..75a7e1b 100644 --- a/src/dotfiles/hosts.nix +++ b/src/dotfiles/hosts.nix @@ -6,7 +6,6 @@ repositoryModules, guestModules, - registryModule, }: let names = lib.attrNames directories; @@ -27,8 +26,6 @@ let repositoryModules guestModules - # TODO: refactor - registryModule (root + "/${name}") { diff --git a/src/flake/apps.nix b/src/flake/apps.nix index 35777a3..cbe5d44 100644 --- a/src/flake/apps.nix +++ b/src/flake/apps.nix @@ -10,6 +10,7 @@ in { fix = { type = "app"; + meta.description = "Formats and cleans repository files."; program = lib.getExe ( pkgs.writeShellApplication { name = "fix"; diff --git a/src/skills/style/nix/rules/flake.md b/src/skills/style/nix/rules/flake.md index 3e75efc..9b0fbf4 100644 --- a/src/skills/style/nix/rules/flake.md +++ b/src/skills/style/nix/rules/flake.md @@ -11,3 +11,13 @@ Use `flake.nix` to pass inputs into that implementation. ### Rationale This keeps dependency declarations separate from output logic. + +## Describe flake apps + +### Rule + +Set `meta.description` on every flake app. + +### Rationale + +Flake tools can display each app's purpose without emitting a missing-metadata warning. diff --git a/src/skills/style/nix/rules/general.md b/src/skills/style/nix/rules/general.md index ed367ef..154c3e8 100644 --- a/src/skills/style/nix/rules/general.md +++ b/src/skills/style/nix/rules/general.md @@ -50,3 +50,91 @@ Do not read `config.home-manager.users..programs..package` for comma Home Manager uses the NixOS package set in this repository. `pkgs.` avoids dependency paths through the user tree under Home Manager. Configured NixOS package options preserve package selection when a module owns the tool. + +## Configure services through documented interfaces + +### Rule + +Use current upstream documentation when mapping Nix options to service arguments or configuration files. +Do not expose undocumented service arguments as module options. + +### Rationale + +Documented interfaces preserve configuration behavior across service updates. + +## Keep module options effective + +### Rule + +Every custom module option must change the generated configuration or behavior. +Remove unused options instead of exposing speculative configuration. + +### Rationale + +An inert option promises behavior that the module does not provide. + +## Separate public and private addresses + +### Rule + +Do not assign a private guest address to an option that advertises a public service address. +Leave optional public-address settings unset when the service can detect them. + +### Rationale + +Private addresses are not routable by public clients. + +## Separate display names from identifiers + +### Rule + +Do not derive systemd unit names or other machine identifiers from unrestricted display names. +Give identifiers constrained types or fixed values. + +### Rationale + +Display names can contain characters that machine interfaces reject or reinterpret. + +## Terminate command options before variable paths + +### Rule + +In generated shell text, pass `--` before variable-derived path operands when the command supports it. + +### Rationale + +Values that start with a hyphen remain operands instead of command options. + +## Compose repository modules once + +### Rule + +Add shared NixOS modules to `repositoryModules` in `src/dotfiles/default.nix`. +Import `repositoryModules` into each host and guest. +Do not pass a shared module through a separate parallel parameter. + +### Rationale + +A single module collection prevents host and guest configurations from diverging. + +## Generate identical named attributes + +### Rule + +Use `lib.genAttrs` when a fixed list of attribute names shares one value. +Do not repeat identical attribute bodies. + +### Rationale + +One definition prevents copied settings from diverging. + +## Import tracked host hardware directly + +### Rule + +Import each tracked `hardware-configuration.nix` directly from its host module. +Do not guard the import with `builtins.pathExists`. + +### Rationale + +A missing hardware description must fail evaluation instead of silently changing the host configuration. -- 2.47.3