On a typical Linux system, user accounts are created and changed with commands:
$ sudo useradd -m yurii$ sudo usermod -aG wheel yurii$ sudo chsh -s /run/current-system/sw/bin/fish yurii
Every one of those mutates the machine you are sitting at. NixOS describes the same account inside the system configuration instead, so it can be reviewed, copied and recreated.
The attribute name after users.users is the
login name, and everything about that person hangs off it. Here the login name
is me, and description is the longer name a login screen will show.
Declare me as a normal human user described as "The Learner".
users.users.me.isNormalUser=trueusers.users.me.description="The Learner"
isNormalUser tells a person apart from the accounts services run under. A
service account wants no home directory, no shell and no password, which is
exactly what leaving this off gives it.
Four fields on that set decide who the account is:
isNormalUsera human being: a home directory, a login shell, and a uid in the human rangea personisSystemUserthe opposite, and the one a service runs as. No home, no logging ina service accountgroupthe one primary group the account belongs to, usually named after themwho owns their filesextraGroupsevery other group they join, which is where permissions actually come fromwhat they may doYou will use the first and the last of those constantly. The middle two turn up the day you write a service of your own.
extraGroups adds the user to existing system groups.
On NixOS, being in wheel is what lets you run administrative commands through
sudo. Other distributions use a different group for the same job.
Add me to the wheel group.
users.users.me.extraGroupsincludeswheel
The shell option takes a package value. NixOS installs it and records it as
the user’s login shell.
Use Fish as the login shell for me.
users.users.me.shellispkgs.fish
environment.systemPackages serves everyone. users.users.me.packages installs
packages for only this account.
Give me Git and Vim as personal packages.
users.users.me.packageshaspkgs.git,pkgs.vim
The system doesn’t need every user’s favorite editor in the shared toolbox.
By default a tool like passwd can still change an account after
activation, which is what
mutable means here. Set users.mutableUsers = false
and every account is rebuilt from the configuration instead, so a password the
configuration never mentions is not part of the machine.
Which means bringing one with you: a hash in hashedPassword, or better, a file
named by hashedPasswordFile that a secrets tool puts there. Never a plaintext
one in a Nix file, since the store is world-readable.
You set `users.mutableUsers = false`, declare one wheel account with no password of any kind, and rebuild. What happens?
Kinder than a machine you cannot get into, but learn the shape of it: the check only asks that one privileged account can still get in. Give root a password and forget your own, and the assertion is perfectly happy.
Leave mutableUsers alone and life is simpler: rebuild once, then sudo passwd me. Until an account has a password or an SSH key, declaring it does not make it
possible to log in.
Put the account settings together in one grouped attribute set.
Finish the account so every requirement is satisfied.
users.users.me.isNormalUseristrueusers.users.me.descriptionis"The Learner"users.users.me.extraGroupshas"wheel"users.users.me.shellispkgs.fishusers.users.me.packageshaspkgs.git,pkgs.vim
users.users.<name>describes one account.isNormalUsermarks an account intended for a person.extraGroupsgrants access such aswheelfor sudo.shellselects the login shell package.packagesinstalls software for one user.users.mutableUserscontrols whether normal commands may change accounts, and turning it off means declaring a password hash as well.
User accounts are now part of the same declarative system description as packages, programs, and networking.


Share your thoughts