Skip to content

4.Extending Your Configuration

Muhammad Talha edited this page Sep 21, 2026 · 2 revisions

Extending Your Configuration

Now that you have a working Nucleus setup, this page explains how to scale your configuration by adding more hosts, users, and features beyond the starter template.

Adding a Second Host

Expanding to multiple machines is straightforward with Nucleus. Each host is independent but can share common configuration.

Steps

  1. Create a new host directory in modules/hosts/:

    mkdir -p modules/hosts/SECOND_HOSTNAME
  2. Add host definition to flake.nix in the let block under hosts:

    hosts = {
      laptop = { ... };
      SECOND_HOSTNAME = {
        hostName = "SECOND_HOSTNAME";
        stateVersion = "YEAR.RELEASE OF THE ISO YOU ARE INSTALLING FROM";
        timeZone = "REGION/CITY";
        disko = {
          storageDevice = "/dev/DEVICE";
          swapSize = "8G";
        };
      };
    };
  3. Generate hardware report for the second machine during installation. Save the hardware_report.json file in modules/hosts/SECOND_HOSTNAME/.

  4. Create host-specific configuration at modules/hosts/SECOND_HOSTNAME/default.nix with hardware settings specific to that machine.

  5. Add a disko configuration in flake.nix outputs:

    diskoConfigurations.${hosts.SECOND_HOSTNAME.hostName} =
      import ./modules/common/disko/bare-ext4.nix hosts.SECOND_HOSTNAME.disko;
  6. Add nixosConfiguration to flake.nix outputs. Use the same pattern as the first host but reference hosts.SECOND_HOSTNAME and the second hostname's path.

  7. Optionally customize features by enabling or disabling entries in the host's modules list to select which features from modules/features/ apply to this host.


Managing Multiple Users

Nucleus supports multiple users per host. Users are defined centrally but can be customized per host.

Adding a Second User

  1. Add to users definition in flake.nix:

    users = {
      primary = { ... };
      secondary = {
        userName = "SECONDARY_USERNAME";
        realName = "REAL NAME";
        hashedPassword = "OUTPUT OF mkpasswd";
        emailAddress = "secondary@mailbox.com";
        gpgKey = "KEY_ID";
      };
    };
  2. Register The User: Register the user with the host or a feature using the following snippet

    users = {                                   
      ${users.secondary.userName} = {             
        isNormalUser = true;                    
        description = users.secondary.realName;   
        extraGroups = [ /* specify groups here */ ];                                      
        inherit (users.secondary) hashedPassword; 
      };                                        
    };                                          
  3. (optional, as per need) Pass user to Home Manager by adding them to specialArgs in the host's nixosConfigurations:

    inherit (users.secondary) userName realName hashedPassword emailAddress gpgKey;
  4. (optional, as per need) Create user-specific home configuration if needed at modules/features/home-manager/SECONDARY_USERNAME_HOME.nix, and then include the file in decl.nix as users.${hmArgs.secondary} = import ./SECONDARY_USERNAME_HOME.nix.

  5. Each user can have independent dotfiles, packages, and shell configurations managed declaratively.


Customizing Features

Features in modules/features/ are reusable components. You can enable or disable them per host.

Creating a Custom Feature

  1. Create feature directory:

    mkdir -p modules/features/my-feature
  2. Write feature module at modules/features/my-feature/default.nix:

    { pkgs, ... }:
    {
        # Your configuration here
        environment.systemPackages = with pkgs; [ package1 package2 ];
    }
  3. Enable per-host by importing it in the host's modules list:

    modules = [
      ./modules/common/nixos-core/core.nix
      ./modules/features/workstation/workstation.nix
      ./modules/features/my-feature/default.nix  # Add this
      ./modules/hosts/${hosts.laptop.hostName}/default.nix
      ...
    ];

Using Different Disko Layouts

The default bare-ext4.nix is suitable for most setups. For other layouts (encrypted, LVM, Btrfs, etc.), refer to the disko examples.

To use a different layout:

  1. Select an example from the disko repository that matches your needs.

  2. Save it to modules/common/disko/ (e.g., encrypted-ext4.nix).

  3. Update the import in flake.nix:

    diskoConfigurations.${hosts.laptop.hostName} =
      import ./modules/common/disko/encrypted-ext4.nix hosts.laptop.disko;
  4. Update the disko module reference in your host's nixosConfigurations.

Disko configuration is beyond the scope of this guide. Refer to the disko documentation for layout-specific details.


Best Practices for Scaling

Keep common configuration DRY by placing shared settings in modules/common/ rather than duplicating per host.

Use clear naming so host names and feature names reflect their purpose. Note that host names cannot contain hyphens.

Test incrementally with nh os test to preview changes before committing them to the bootloader.

Track changes in git to version control your flake.nix and module changes for easy rollback if needed.

Isolate host-specific logic by putting hardware, drivers, and host-only options in modules/hosts/HOSTNAME/default.nix.

Document custom features by adding comments to custom modules that explain their purpose and configuration options.

Next Steps

  • Explore the Nucleus repository examples for additional feature implementations.
  • Refer to the NixOS manual for detailed option documentation.
  • Use nix flake show to verify all defined configurations and outputs.
  • Consult nh os info to inspect installed generations and rollback if needed.