NixOS Laptop Configuration: Power, WiFi, and Tips
Running NixOS on a laptop requires attention to power management, wireless connectivity, and hardware-specific quirks. This guide covers common configurations and gotchas.
Power Management
TLP (Recommended)
TLP provides automatic power optimization:
{
services.tlp = {
enable = true;
settings = {
# CPU scaling
CPU_SCALING_GOVERNOR_ON_AC = "performance";
CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
# CPU performance limits
CPU_MIN_PERF_ON_AC = 0;
CPU_MAX_PERF_ON_AC = 100;
CPU_MIN_PERF_ON_BAT = 0;
CPU_MAX_PERF_ON_BAT = 50;
# Turbo boost
CPU_BOOST_ON_AC = 1;
CPU_BOOST_ON_BAT = 0;
# WiFi power saving
WIFI_PWR_ON_AC = "off";
WIFI_PWR_ON_BAT = "on";
};
};
# Conflicts with power-profiles-daemon
services.power-profiles-daemon.enable = false;
}Power Profiles Daemon (Alternative)
GNOME-friendly alternative:
{
services.power-profiles-daemon.enable = true;
# Don't use with TLP
services.tlp.enable = false;
}Switch profiles via GNOME settings or:
powerprofilesctl set power-saver
powerprofilesctl set balanced
powerprofilesctl set performanceLid Switch Behavior
{
services.logind = {
lidSwitch = "suspend";
lidSwitchDocked = "ignore"; # When external display connected
lidSwitchExternalPower = "lock";
};
}Screen Brightness
{
programs.light.enable = true;
# Add user to video group
users.users.yourname.extraGroups = [ "video" ];
}Then use:
light -A 10 # Increase 10%
light -U 10 # Decrease 10%
light -S 50 # Set to 50%WiFi Configuration
NetworkManager (Recommended)
{
networking.networkmanager.enable = true;
users.users.yourname.extraGroups = [ "networkmanager" ];
# Don't use wireless with NetworkManager
networking.wireless.enable = false;
}Manage networks via nmcli or GUI applet:
# List available networks
nmcli device wifi list
# Connect to network
nmcli device wifi connect "SSID" password "password"
# Show saved connections
nmcli connection showiwd Backend
For better WiFi performance and reliability:
{
networking.networkmanager.wifi.backend = "iwd";
# iwd settings
networking.wireless.iwd = {
enable = true;
settings = {
General = {
EnableNetworkConfiguration = true;
};
Network = {
EnableIPv6 = true;
};
};
};
}Manual wpa_supplicant
For minimal setups:
{
networking.wireless = {
enable = true;
networks = {
"HomeWifi" = {
psk = "password"; # Or use pskRaw for hashed password
};
"WorkWifi" = {
auth = ''
key_mgmt=WPA-EAP
eap=PEAP
identity="user@domain"
password="secret"
'';
};
};
};
}Guest WiFi and Captive Portals
The neverssl.com Trick
Captive portals (hotel WiFi, coffee shops) work by intercepting HTTP traffic. Modern browsers use HTTPS everywhere, which prevents the interception.
Solution: Visit http://neverssl.com
This site intentionally uses plain HTTP, allowing the captive portal to intercept and redirect you to the login page.
Automatic Detection
NetworkManager usually detects captive portals automatically and opens a browser. If not:
{
# Ensure connectivity checking is enabled
networking.networkmanager = {
enable = true;
# Uses NetworkManager's built-in captive portal detection
};
# Or install a dedicated captive portal helper
programs.captive-browser = {
enable = true;
interface = "wlan0";
};
}Manual Portal Detection
# Check if behind captive portal
curl -I http://neverssl.com
# If redirected (301/302), you're behind a portal
# Open the redirect URL in a browserZFS and Hibernation
The Problem
ZFS does not safely support hibernation. When the system hibernates, pool state is written to RAM image. On resume, if the pool was modified (from another boot), data corruption can occur.
ZFS explicitly refuses to import pools that may be in an inconsistent state.
Workarounds
Option 1: Disable Hibernation
{
# Only allow suspend, not hibernate
services.logind.lidSwitch = "suspend";
services.logind.extraConfig = ''
HandleHibernateKey=ignore
HandleSuspendKey=suspend
'';
# Disable hibernate entirely
systemd.targets.hibernate.enable = false;
systemd.targets.hybrid-sleep.enable = false;
}Option 2: Swap on Non-ZFS Partition
If you must hibernate, use a separate ext4 or swap partition:
{
# Swap on dedicated partition, not ZVOL
swapDevices = [{ device = "/dev/nvme0n1p3"; }];
boot.resumeDevice = "/dev/nvme0n1p3";
}This allows hibernation but requires careful pool management.
Option 3: Export Pool Before Hibernate (Manual)
# Before hibernate
zpool export tank
systemctl hibernate
# On resume
zpool import tankNot practical for daily use.
Recommendation
Use suspend instead of hibernate. With modern SSDs and fast boot, the time difference is minimal, and you avoid corruption risk.
Additional Laptop Tips
Battery Status
{
# Include power info in status
services.upower.enable = true;
}Check via:
upower -i /org/freedesktop/UPower/devices/battery_BAT0Touchpad Configuration
{
services.libinput = {
enable = true;
touchpad = {
naturalScrolling = true;
tapping = true;
clickMethod = "clickfinger";
disableWhileTyping = true;
};
};
}External Monitor Handling
{
# Auto-detect and configure displays
services.autorandr.enable = true;
}Save profiles:
autorandr --save docked
autorandr --save mobileThermald (Intel)
{
services.thermald.enable = true; # Intel thermal management
}Firmware Updates
{
services.fwupd.enable = true;
}Check for updates:
fwupdmgr get-updates
fwupdmgr updateCommon Issues
WiFi Drops After Suspend
{
# Reload WiFi module on resume
powerManagement.resumeCommands = ''
modprobe -r iwlwifi
modprobe iwlwifi
'';
}Slow Wake from Suspend
{
boot.kernelParams = [ "mem_sleep_default=deep" ];
}Function Keys Not Working
{
# For ThinkPad
services.throttled.enable = true;
# For many laptops
boot.kernelModules = [ "thinkpad_acpi" ]; # Or appropriate module
}