Harden NixOS config defaults and setup guidance #4

Merged
Copilot merged 13 commits from copilot/review-nixos-setup-issues into main 2026-02-01 21:17:59 +00:00
Copilot commented 2026-02-01 20:39:57 +00:00 (Migrated from github.com)

The current NixOS setup had fragile defaults and placeholder-driven paths that could break evaluation or confuse users. This PR tightens configuration validation and clarifies setup steps to avoid common misconfigurations.

  • Configuration defaults & validation
    • Centralize hostname/username in flake.nix and pass via specialArgs
    • Validate usernames and ensure host hardware config exists before evaluation
  • User/password handling
    • Standardize password hash path usage and document required location/permissions
  • Documentation clarity
    • Update README to reflect new defaults and the correct order of host directory/hostname changes

Example:

let
  hostname = "atlas";
  username = "pinj";
  hostConfig = assert builtins.pathExists (./hosts + "/${hostname}/hardware-configuration.nix");
    ./hosts + "/${hostname}/hardware-configuration.nix";
in
...
Original prompt

Review the current setup and look for issues. Compare to similar nixos setups. Fix all issues


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

The current NixOS setup had fragile defaults and placeholder-driven paths that could break evaluation or confuse users. This PR tightens configuration validation and clarifies setup steps to avoid common misconfigurations. - **Configuration defaults & validation** - Centralize `hostname`/`username` in `flake.nix` and pass via `specialArgs` - Validate usernames and ensure host hardware config exists before evaluation - **User/password handling** - Standardize password hash path usage and document required location/permissions - **Documentation clarity** - Update README to reflect new defaults and the correct order of host directory/hostname changes Example: ```nix let hostname = "atlas"; username = "pinj"; hostConfig = assert builtins.pathExists (./hosts + "/${hostname}/hardware-configuration.nix"); ./hosts + "/${hostname}/hardware-configuration.nix"; in ... ``` <!-- START COPILOT CODING AGENT SUFFIX --> <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > Review the current setup and look for issues. Compare to similar nixos setups. Fix all issues </details> <!-- START COPILOT CODING AGENT TIPS --> --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
ragusa-it (Migrated from github.com) reviewed 2026-02-01 20:39:57 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-02-01 21:21:02 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

This PR hardens the NixOS configuration by centralizing hostname and username settings, adding validation, and improving password handling. The changes move away from inline placeholder values to a centralized configuration approach in flake.nix.

Changes:

  • Centralize hostname and username in flake.nix with validation and propagate via specialArgs
  • Replace inline username references with parameterized values across all modules
  • Switch from hashedPassword to hashedPasswordFile for improved security
  • Update documentation to reflect new centralized configuration approach

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
flake.nix Adds hostname/username centralization, username validation, host config path assertion, and password hash file path configuration
modules/common.nix Updates to use parameterized hostname/username, adds username validation assertion, switches to hashedPasswordFile, reorganizes environment variables
modules/dev.nix Updates to use parameterized username for user-specific configurations
modules/gaming.nix Updates to use parameterized username for user-specific configurations
README.md Updates setup instructions to reflect centralized configuration defaults and new password hash file approach

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview This PR hardens the NixOS configuration by centralizing hostname and username settings, adding validation, and improving password handling. The changes move away from inline placeholder values to a centralized configuration approach in `flake.nix`. **Changes:** - Centralize `hostname` and `username` in `flake.nix` with validation and propagate via `specialArgs` - Replace inline username references with parameterized values across all modules - Switch from `hashedPassword` to `hashedPasswordFile` for improved security - Update documentation to reflect new centralized configuration approach ### Reviewed changes Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | flake.nix | Adds hostname/username centralization, username validation, host config path assertion, and password hash file path configuration | | modules/common.nix | Updates to use parameterized hostname/username, adds username validation assertion, switches to `hashedPasswordFile`, reorganizes environment variables | | modules/dev.nix | Updates to use parameterized username for user-specific configurations | | modules/gaming.nix | Updates to use parameterized username for user-specific configurations | | README.md | Updates setup instructions to reflect centralized configuration defaults and new password hash file approach | </details> --- 💡 <a href="/ragusa-it/nixos/new/main/.github/instructions?filename=*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-01 21:21:01 +00:00

The setup instructions don't mention creating the password hash file before the first build, but this is required because hashedPasswordFile is used in the user configuration. Add a new step between "Review Configuration Defaults" and "Stage Files in Git" that instructs users to create the password hash file. This is a prerequisite for the first successful build.

The setup instructions don't mention creating the password hash file before the first build, but this is required because `hashedPasswordFile` is used in the user configuration. Add a new step between "Review Configuration Defaults" and "Stage Files in Git" that instructs users to create the password hash file. This is a prerequisite for the first successful build.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-01 21:21:00 +00:00

The README instructions for password setup in the "Post-Installation" section should be moved to the setup instructions before the first build. The current flow requires users to successfully build the system first, but the build will fail if the password hash file doesn't exist. Users need to create this file before running nixos-rebuild for the first time.

The README instructions for password setup in the "Post-Installation" section should be moved to the setup instructions before the first build. The current flow requires users to successfully build the system first, but the build will fail if the password hash file doesn't exist. Users need to create this file before running `nixos-rebuild` for the first time.
@@ -41,1 +43,3 @@
specialArgs = { inherit inputs system; };
usernameValid =
builtins.match "^[a-z_][a-z0-9_]*$" username != null
&& builtins.match "^_+$" username == null
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-01 21:21:01 +00:00

The username validation regex allows usernames that consist only of underscores followed by other characters (e.g., "___abc"), but the second check builtins.match "^_+$" username == null only rejects usernames that are entirely underscores. According to standard Unix username conventions, usernames starting with underscore are typically reserved for system accounts. Consider strengthening the validation to reject any username starting with underscore unless that's intentionally allowed for system accounts.

      builtins.match "^[a-z][a-z0-9_]*$" username != null
The username validation regex allows usernames that consist only of underscores followed by other characters (e.g., "___abc"), but the second check `builtins.match "^_+$" username == null` only rejects usernames that are entirely underscores. According to standard Unix username conventions, usernames starting with underscore are typically reserved for system accounts. Consider strengthening the validation to reject any username starting with underscore unless that's intentionally allowed for system accounts. ```suggestion builtins.match "^[a-z][a-z0-9_]*$" username != null ```
@@ -42,0 +47,4 @@
&& username != "root";
hostConfig = assert builtins.pathExists (./hosts + "/${hostname}/hardware-configuration.nix");
./hosts + "/${hostname}/hardware-configuration.nix";
passwordHashPath = "/etc/nixos/secrets/${username}/password.hash";
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-01 21:21:01 +00:00

The assertion for hostConfig will fail at evaluation time with a cryptic error if the path doesn't exist. The assert statement should provide a helpful error message to guide users. Consider using a let-binding with an abort statement that provides a clear message like: "Hardware configuration not found at ./hosts/${hostname}/hardware-configuration.nix. Please ensure the directory exists and contains the hardware configuration file."

    hostConfig =
      let
        hardwarePath = ./hosts + "/${hostname}/hardware-configuration.nix";
      in
      if builtins.pathExists hardwarePath then
        hardwarePath
      else
        builtins.abort "Hardware configuration not found at ./hosts/${hostname}/hardware-configuration.nix. Please ensure the directory exists and contains the hardware configuration file.";
The assertion for `hostConfig` will fail at evaluation time with a cryptic error if the path doesn't exist. The assert statement should provide a helpful error message to guide users. Consider using a let-binding with an abort statement that provides a clear message like: "Hardware configuration not found at ./hosts/${hostname}/hardware-configuration.nix. Please ensure the directory exists and contains the hardware configuration file." ```suggestion hostConfig = let hardwarePath = ./hosts + "/${hostname}/hardware-configuration.nix"; in if builtins.pathExists hardwarePath then hardwarePath else builtins.abort "Hardware configuration not found at ./hosts/${hostname}/hardware-configuration.nix. Please ensure the directory exists and contains the hardware configuration file."; ```
@@ -42,0 +48,4 @@
hostConfig = assert builtins.pathExists (./hosts + "/${hostname}/hardware-configuration.nix");
./hosts + "/${hostname}/hardware-configuration.nix";
passwordHashPath = "/etc/nixos/secrets/${username}/password.hash";
specialArgs = { inherit inputs system hostname username usernameValid passwordHashPath; };
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-02-01 21:21:01 +00:00

The passwordHashPath is hardcoded to a system location that may not exist on first installation, but there's no validation or assertion to check if this file exists. This will cause the system build to fail with an unclear error. Consider adding an assertion in common.nix to check if the password hash file exists, with a helpful error message directing users to the password setup instructions in the README. Alternatively, document that users must create this file before their first build.

    passwordHashPath =
      let
        path = "/etc/nixos/secrets/${username}/password.hash";
      in
      if builtins.pathExists path then
        path
      else
        builtins.throw ''
          Password hash file not found at ${path}.
          
          Please create this file before your first build.
          See the password setup instructions in the project README.
        '';
The `passwordHashPath` is hardcoded to a system location that may not exist on first installation, but there's no validation or assertion to check if this file exists. This will cause the system build to fail with an unclear error. Consider adding an assertion in `common.nix` to check if the password hash file exists, with a helpful error message directing users to the password setup instructions in the README. Alternatively, document that users must create this file before their first build. ```suggestion passwordHashPath = let path = "/etc/nixos/secrets/${username}/password.hash"; in if builtins.pathExists path then path else builtins.throw '' Password hash file not found at ${path}. Please create this file before your first build. See the password setup instructions in the project README. ''; ```
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ragusa-it/nixos#4