users.users.<name>.hashedPasswordFile

Browsing some old notes today and I found a newbie question about passwords that I never asked.

I am using ‘users.users.<name>.hashedPasswordFile’ in preference to ‘users.users.<name>.hashedPassword’ because the hashed password can be placed in a file that can be made ‘not world readable’ like configuration.nix & /nix/store/xxx-users-groups-json*.

The user passwords ultimately get put into /etc/shadow which has root only permissions but having the same hashed passwords in the above files seems to circumvent these permissions which is why I prefer not to do it.

I am fairly sure this is covered and explained somewhere, however when I went looking through the documentation for users.users.<name>.hashedPassword, users.users.<name>.hashedPasswordFile and the NixOS Manual I couldn’t find any ‘advice’ so to speak…

Thoughts?

In the case of hashed passwords placing them in the nix store isn’t the end of the world. Even publishing hashed passwords isn’t a massive deal; it’s effectively impossible to reverse the hash, and unlike with e.g. WPA2 passwords knowing the hash doesn’t suffice for authentication.

This is why - unlike most password options - the hashedPassword* options do not give advice as to which one you should set; they’re both pretty safe.

It’s also not unreasonable to prefer not even permitting the option of reversing the hash, especially if you publish your config online; save-now-decrypt-later is a thing, and it’s not entirely impossible to brute force, just more costly than what is realistically worthwhile for some random system you probably don’t even have unprivileged RCE on anyway - and it’s unlikely any of us hold up to a much cheaper targeted attack, whether our passwords are known plaintext or not.

users.mutableUsers and just setting the password with passwd is my personal preference; secrets should ideally not be set statically as part of configuration, but be treated as data - rotating a secret does not mean a meaningful change in system configuration.

Either way, do as is convenient for you, or as complies by your ideological constraints. All these options are quite safe, except for users.users.<name>.password - which does say so in its docs.

Personally, I think reducing the number of diverging knobs and concepts is nice, because exceptions make people with insufficient knowledge assume those exceptions are generic. Or at the very least it can confuse them, as it seems to have done for you. I.e., IMO neither password nor hashedPassword should exist, because it’s an interface new users interact with very early on, and as such it sets expectations of secret management on the platform; the expectation that you can put a secret as a string in configuration.nix is generally harmful, yet here we are teaching new users to do exactly that.

Thanks for your thoughts @TLATER. I debated even posing the question but I am glad I did and I am hoping this might be useful to someone.

I should have mentioned that I use ‘users.mutableUsers = false;’ I typically use a declarative approach for transient libvirt domains as it makes tracking easier but that was very relevant to this question. Good spot! :man_bowing:

Your last paragraph covers my thoughts - ‘very early on’ and ‘teaching new users’ by example… The notes I was looking at today were from when I first started with NixOS and I admit that I still have some configs lingering around with hashedPasswords in them. These are test VMs and as you suggested, these also have a number of other protection mechanisms such as not having open ports etc etc. I am not concerned by them but I do sort of wish that I started off with hashedPasswordFiles. I certainly didn’t realise or understand back then the (possible) implications of the nix/store and configuration.nix being world readable. :slight_smile:

I have no idea if rainbow tables are still a realistic form of attack. Looking briefly at it today, I can see why hashedPasswords can be considered “quite safe”. It seems that the 16 character salts (shown below in blue) for something like sha-512 provide a fairly enormous ~8 x 10^28 increase in the number of hashes that even a short password might produce. Wow - Time? Value? :man_shrugging:

$ mkpasswd -m sha-512 ‘FakePassword’
$6$2b33A79Y48IlzcZY$6IX1B1JOX7tcXs/g6Qlo/HJWGzaMI/pWw3cDF1Fv7q.1wfzYxdgm4Gr0SJoAeOYUkBnMy8esGrLr3Yah1Vrzt0

Repeating results in a different hash because of the random 16 character salt.

$ mkpasswd -m sha-512 ‘FakePassword’
$6$oCQi8TfM.Fkia5cb$bxovJXgMiLs1e2RP8Rlu7r.T7h1BmXmsa1voTqGVqn20Bbi65B.cDrt/5P0buMYbDZqKPpPeFeDz.ZGT.cxaC.

Repeating with the same salt from above produces the same hash.

$ mkpasswd -m sha-512 ‘FakePassword’ -s oCQi8TfM.Fkia5cb
$6$oCQi8TfM.Fkia5cb$bxovJXgMiLs1e2RP8Rlu7r.T7h1BmXmsa1voTqGVqn20Bbi65B.cDrt/5P0buMYbDZqKPpPeFeDz.ZGT.cxaC.

Yeah, exactly. I’m not concerned about people using hashedPassword, I’m concerned about the precedence it sets in new users’ minds.