Configuration Initialization
This section will describe creating the minimal
template from scratch.
You do not have to do this; you can simply clone the minimal configuration template with the following command:
nix flake init -t github:yunfachi/denix#minimal
You can also copy the minimal configuration template without the rices:
nix flake init -t github:yunfachi/denix#minimal-no-rices
Flake
First, create a directory for your configuration and a flake.nix
file with the following content:
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
home-manager = {
url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
denix = {
url = "github:yunfachi/denix";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
};
outputs = {
denix,
nixpkgs,
...
} @ inputs: let
mkConfigurations = isHomeManager:
denix.lib.configurations {
homeManagerNixpkgs = nixpkgs;
homeManagerUser = "sjohn"; #!!! REPLACEME
inherit isHomeManager;
paths = [./hosts ./modules ./rices];
specialArgs = {
inherit inputs;
};
};
in {
nixosConfigurations = mkConfigurations false;
homeConfigurations = mkConfigurations true;
};
}
If you are not familiar with inputs
and outputs
, read NixOS Wiki Flakes.
Code explanation:
mkConfigurations
- a function to reduce code repetition, which takesisHomeManager
and passes it todenix.lib.configurations
.denix.lib.configurations
- Configurations (flakes) - Introduction.paths = [./hosts ./modules ./rices];
- paths to be recursively imported by Denix. Remove./rices
if you don't want to use rices.
Hosts
Create a hosts
directory, and within it, create a subdirectory with the name of your host, for example, desktop
.
In this subdirectory, create a default.nix
file with the following content:
{delib, ...}:
delib.host {
name = "desktop"; #!!! REPLACEME
}
In the same directory, create a hardware.nix
file:
{delib, ...}:
delib.host {
name = "desktop"; #!!! REPLACEME
homeManagerSystem = "x86_64-linux"; #!!! REPLACEME
home.home.stateVersion = "24.05"; #!!! REPLACEME
nixos = {
nixpkgs.hostPlatform = "x86_64-linux"; #!!! REPLACEME
system.stateVersion = "24.05"; #!!! REPLACEME
# nixos-generate-config --show-hardware-config
# other generated code here...
};
}
The default.nix
file will be modified later after adding modules and rices, so you can keep it open.
Rices
Skip this section if you do not wish to use rices.
Create a rices
directory, and within it, create a subdirectory with the name of your rice, for example, dark
.
In this subdirectory, create a default.nix
file with the following content:
{delib, ...}:
delib.rice {
name = "dark"; #!!! REPLACEME
}
Modules
Create a modules
directory, and within it, create a config
subdirectory (typically, it contains modules that are not tied to a specific program or service).
It should be mentioned that modules represent your configuration, meaning it's up to your imagination, and you are free to change the modules as you wish.
Constants
In this subdirectory, create a constants.nix
file with the following content:
{delib, ...}:
delib.module {
name = "constants";
options.constants = with delib; {
username = readOnly (strOption "sjohn"); #!!! REPLACEME
userfullname = readOnly (strOption "John Smith"); #!!! REPLACEME
useremail = readOnly (strOption "johnsmith@example.com"); #!!! REPLACEME
};
}
This file is optional, as are any of its options, which are only used by you, but it is strongly recommended as good practice.
Hosts
Also, create a hosts.nix
file in this same directory (modules/config
), and write any example from Hosts - Examples.
For example, we will take "With the type
Option":
{delib, ...}:
delib.module {
name = "hosts";
options = with delib; let
host = {config, ...}: {
options =
hostSubmoduleOptions
// {
type = noDefault (enumOption ["desktop" "server"] null);
isDesktop = boolOption (config.type == "desktop");
isServer = boolOption (config.type == "server");
};
};
in {
host = hostOption host;
hosts = hostsOption host;
};
home.always = {myconfig, ...}: {
assertions = delib.hostNamesAssertions myconfig.hosts;
};
}
If you added an example with new options (type
, displays
, etc.) or made your own options, don't forget to add values for these options in the hosts.
In our example, we added the type
option, so open the default.nix
file in your host's directory and add the attribute type
to the delib.host
function:
{delib, ...}:
delib.host {
name = "desktop"; #!!! REPLACEME
type = "desktop" #!!! REPLACEME (desktop/server)
# ...
}
Rices
Skip this section if you are not using rices.
In the modules/config
directory, create a rices.nix
file, and write any example from Rices - Examples.
For example, we will take "Minimally Recommended Rice Module":
delib.module {
name = "rices";
options = with delib; let
rice = {
options = riceSubmoduleOptions;
};
in {
rice = riceOption rice;
rices = ricesOption rice;
};
home.always = {myconfig, ...}: {
assertions = delib.riceNamesAssertions myconfig.rices;
};
}
Also, open the default.nix
file of your host and add the attribute rice
to the delib.host
function:
{delib, ...}:
delib.host {
name = "desktop"; #!!! REPLACEME
rice = "dark" #!!! REPLACEME
# ...
}
Home Manager
If you created a constants module, just create a home.nix
file with the following content:
{delib, ...}:
delib.module {
name = "home";
home.always = {myconfig, ...}: let
inherit (myconfig.constants) username;
in {
home = {
inherit username;
homeDirectory = "/home/${username}";
};
};
}
If you did not use the constants module, the content of the file will be:
{delib, ...}:
delib.module {
name = "home";
home.always.home = {
username = "sjohn"; #!!! REPLACEME
homeDirectory = "/home/sjohn"; #!!! REPLACEME
};
}
User
You can also create a user.nix
file with the configuration of your NixOS user:
{delib, ...}:
delib.module {
name = "user";
nixos.always = {myconfig, ...}: let
inherit (myconfig.constants) username;
in {
users = {
groups.${username} = {};
users.${username} = {
isNormalUser = true;
initialPassword = username;
extraGroups = ["wheel"];
};
};
};
}
If you did not use the constants module, the content of the file will be:
{delib, ...}:
delib.module {
name = "user";
nixos.always.users = {
groups.sjohn = {}; #!!! REPLACEME
users.sjohn = { #!!! REPLACEME
isNormalUser = true;
initialPassword = "sjohn"; #!!! REPLACEME
extraGroups = ["wheel"];
};
};
}
Conclusion
If you have followed the instructions precisely, you will end up with the following configuration directory tree:
hosts
- desktop
- default.nix
- hardware.nix
modules
- config
- constants.nix
- home.nix
- hosts.nix
- rices.nix
- user.nix
rices
- dark
- default.nix
flake.nix
You can check if everything is set up correctly using the command:
nix flake check .#