Hardening README
📌 How to Use This Guide
Read warnings: Advanced hardening can break compatibility or cause data loss! Pause and research before enabling anything not listed above unless you understand the consequences.
The guide is broken up into 2 chapters:
Getting Started
There is a lot covered in this guide which can get overwhelming when trying to decide what is worth implementing. Here, I will list some common recommendations that most users should follow to harden their stance.
Baseline Hardening
Before diving into advanced or specialized hardening, apply these baseline security measures suitable for all NixOS users. These settings help protect your system with minimal risk of breaking workflows or causing admin headaches.
-
Use Disk Encryption (LUKS) to protect your data at rest.
-
Keep your system up to date (update regularly).
-
Use strong, unique passwords.
-
Avoid reusing passwords, use a password manager.
-
Only enable what you use, and actively disable what's no longer in use.
-
Enable at least a basic firewall, a more complex firewall example that utilizes nftables is shared in the Hardening Networking Chapter
The firewall is enabled by default on NixOS. To explicitly ensure it's enabled,
add the following to your configuration.nix
or equivalent:
# configuration.nix
# this denies incoming connections but allows outgoing and established connections
networking.firewall.enable = true;
Many services provide an option to open the required firewall ports automatically. For example:
services.tor.openFirewall = true;
This prevents you from having to manually open ports
Audit and remove local user accounts that are no longer needed: Regularly review and remove unused or outdated accounts to reduce your system’s attack surface, improve compliance, and ensure only authorized users have access. The following setting ensures that user (and group) management is fully declarative:
# configuration.nix
# All users must be declared
users.mutableUsers = false;
With users.mutableUsers = false;
, all non-declaratively managed (imperative)
user management including creation, modification, or password changes will fail
or be reset on rebuild. User and group definitions become entirely controlled by
your system configuration for maximum reproducibility and security. If you need
to add, remove, or modify users, you must do so in your configuration.nix
and
rebuild the system.
NOTE: There is mention of making userborn the default for NixOS in the future. It can be more secure by prohibiting UID/GID re-use and giving warnings about insecure password hashing schemes.
To enable userborn
, just add the following to your configuration.nix
or
equivalent:
# users.nix
{pkgs,...}:{
services.userborn = {
enable = true;
# Only needed if `/etc` is immutable
# passwordFilesLocation = "/var/lib/nixos/userborn"
};
users.users = {
"newuser" = {
homeMode = "755";
uid = 1000;
isNormalUser = true;
description = "New user account";
extraGroups = [ "networkmanager" "wheel" "libvirtd" ];
shell = pkgs.bash;
ignoreShellProgramCheck = true;
packages = with pkgs; [];
};
};
}
With userborn
, you configure your users as you normally would declaratively
with NixOS with users.users
, change "newuser"
to your desired username.
Explicitly setting uid = 1000;
is a best practice for compatibility and
predictability.
You can also specify which users or groups are allowed to do anything with the
Nix daemon and Nix package manager. The following setting will only allow
members of the wheel
group access to commands that require elevated
privileges, such as installing or modifying system-wide packages:
# configuration.nix
{ ... }:
{
nix.settings.allowed-users = [ "@wheel" ];
}
OR Only allow the root
user:
# configuration.nix
{ ... }:
{
nix.settings.allowed-users = [ "root" ];
}
This is more restrictive and much less convenient, think twice before going this restrictive.
Only install, enable, and run what is needed: Disable or uninstall unnecessary software and services to minimize potential vulnerabilities. Take advantage of NixOS’s easy package management and minimalism to keep your system lean and secure.
Avoid permanently installing temporary tools: Use tools like nix-shell
,
comma
, devShells
and nix-direnv
to test or run software temporarily. This
prevents clutter and reduces potential risks from unused software lingering on
the system.
Update regularly: Keep your system and software up to date to receive the latest security patches. Delaying updates leaves known vulnerabilities open to exploitation.
Apply the Principle of Least Privilege: Never run tools or services as root unless absolutely necessary. Create dedicated users and groups with the minimum required permissions to limit potential damage if compromised.
Use strong passwords and passphrases: Aim for at least 14–16 characters by
combining several unrelated words, symbols, and numbers. For example:
sunset-CoffeeHorse$guitar!
. Strong passphrases are both memorable and secure.
Use a password manager and enable multi-factor authentication (MFA): Manage unique, strong passwords effectively with a trusted manager and protect accounts with MFA wherever possible for a second layer of defense.
Check logs regularly: Reviewing your system logs helps you spot unusual
activity, errors, or failed login attempts that could indicate a security
problem. NixOS uses journald
by default, which makes this easy. For example,
to see the logs for your current boot session:
journalctl -b
# for the previous session
journalctl -b -1
After establishing some standard best practices and a hardened base, it’s time to dive deeper into system hardening, the process of adding layered safeguards throughout your NixOS setup. This next section guides you through concrete steps and options for hardening critical areas of your system: from encryption and secure boot to managing secrets, tightening kernel security, and leveraging platform-specific tools. Hardening NixOS