Jump to content

Swap

From NixOS Wiki


Swap allows "cold" pages of virtual memory to be stored in places other than directly in the physical RAM, effectively allowing more pages to be stored. This can be accomplished by using space on disk, such as swap file or swap partition, or through compression based methods like zram. Additionally, zswap can act as a RAM-based compressed cache sitting in front of a traditional disk-based swap device.

Configuration

The following sections describe how to configure and manage swap on NixOS.

To check your current swap setup and usage, you can use the following command: swapon --show

Note: nixos-generate-config does not automatically generate a swapDevices entry if your system uses a swap file or /dev/zram for swap. For details, see the discussion on GitHub
Note: It's generally recommended to use either zram or zswap, but not both simultaneously, as they serve overlapping roles and may lead to suboptimal memory management behavior.

Swap file

A swap file provides swap space using a regular file on your filesystem, offering greater flexibility compared to a dedicated swap partition.

To add a swap file in NixOS, add the following:

❄︎ /etc/nixos/configuration.nix
swapDevices = [{
  device = "/var/lib/swapfile";
  size = 16*1024; # 16 GB
}];

This will create a 16GB swapfile at /var/lib/swapfile. The size value is specified in megabytes. This will cause a swap file to be generated and an entry to be set up in /etc/fstab.

Swap partition

Swap partitions are typically created during the initial disk partitioning phase of a NixOS installation. For instructions on creating swap partitions, see the relevant NixOS manual sections for UEFI/MBR partition schemes and formatting.

Swap partitions can be defined in configuration.nix like above or (if GPT) be automatically discovered by systemd-gpt-auto-generator(8). Using the former allows you to have some control over swap mounting options and to enable features such as encrypted swap.

Zram swap

Zram is a kernel module for creating a compressed block device in RAM.

❄︎ /etc/nixos/configuration.nix
zramSwap.enable = true; # Creates a zram block device and uses it as a swap device

It is an alternative or complementary approach to swap disks, suitable for systems with enough RAM. In the event the system needs to swap it will move uncompressed RAM contents into the compressed area, saving RAM space while effectively increasing the available RAM at the cost of computational power for compression and decompression.

See zramSwap for a full list of available options and their descriptions.

Zram writeback

Zram supports writeback functionality, allowing idle or incompressible pages to be moved to a backing storage device rather than keeping it in memory. Currently, writeback can only use block storage devices (such as partitions) and does not support swap files. The backing partition must be manually created first, but does not require formatting.

An example configuration:

❄︎ /etc/nixos/configuration.nix
zramSwap = {
  enable = true; 
  writebackDevice = "/dev/sda1"

To verify the block storage device is being used:

cat /sys/block/zram0/backing_dev

If you see an error entry like

Jul 08 17:14:50 COMPUTER zram-generator[3056]: Error: Failed to configure write-back device into /sys/block/zram0/backing_dev
Jul 08 17:14:50 COMPUTER zram-generator[3056]: Caused by:
Jul 08 17:14:50 COMPUTER zram-generator[3056]:     Device or resource busy (os error 16)

This is probably because the writeback device has already been mounted elsewhere (e.g. as swap). To avoid this you need to do as the #Disable swap section says and make sure your writeback device is not being mounted as swap (this can happen due to systemd-gpt-auto-generator(8)). Do note that zram writeback does not respect the swap on-disk format and will destroy your existing swap header.

Zswap swap cache

Zswap is a compressed RAM cache for swap pages. It acts as a middle layer between system memory and a traditional disk-based swap device, storing compressed pages in RAM before optionally writing them out to disk-based swap if necessary. It acts as an LRU cache.

Unlike zram, zswap requires a disk-based swap device or file to back it.

Zswap is controlled by kernel parameters and can be enabled in your NixOS configuration by setting appropriate options through boot.kernelParams.

❄︎ /etc/nixos/configuration.nix
  boot.kernelParams = [
    "zswap.enabled=1" # enables zswap
    "zswap.compressor=lz4" # compression algorithm
    "zswap.max_pool_percent=20" # maximum percentage of RAM that zswap is allowed to use
    "zswap.shrinker_enabled=1" # whether to shrink the pool proactively on high memory pressure
  ];
Note: If you use the lz4 algorithm, you will also need to set boot.initrd.systemd.enable to true

You can verify zswap's runtime status via cat /sys/module/zswap/parameters/enabled and inspect usage statistics with # grep -r . /sys/kernel/debug/zswap/

Disable swap

To remove all swap devices from NixOS, set the following to remove the swap partition or file from being included in /etc/fstab.

swapDevices = lib.mkForce [ ];

If you are using GPT partitioning tables, systemd-gpt-auto-generator(8) will still mount your swap partition automatically. You must therefore turn on attribute 63 ("no-auto") on each swap partition partition in the partition table. This can be done with gptfdisk or similar:

gdisk /dev/sda
x
a
<partition number>
63
<enter>
w

Alternatively, systemd-gpt-auto-generator(8) for swap can be disabled globally through a kernel cmdline systemd.swap=0:

boot.kernelParams = [ "systemd.swap=0" ];

Tips and Tricks

Mount options

discard

Solid state drives have fast random access times, which make them great for swap if you ignore the limited lifespan. Enabling TRIM (discard) on the swap files can help avoid unnecessary copy actions on the SSD, reducing wear and potentially helping increase performance.

swapDevices = [{
  device = "/dev/sdXY";
  options = [ "discard" ]; # equivalent to swapon --discard
}];

A lower-impact option is "discard=once", which runs discard exactly once when the swap is enabled, but does not continually issue discard commands as pages are being overwritten. This could make more sense depending on your hardware.

systemd-gpt-auto-generator(8) does not automatically enable discard. Also, never enable discard on mdadm RAID setups, as ArchWiki reports that it causes lockup.

Encrypt swap with random key

Because data from memory is evicted into swap, any secret data in memory can also end up in swap. Because the disks backing the swap is often nonvolatile (data is not lost after power cut), this can represent another way for data to end up in the wrong hands if you computer is seized.

By encrypting the swap with a random key kept in memory, we make sure that the contents of the swap become unreadable as soon as the data in memory has been lost. NixOS contains a handy helper to help you do this, generating a new key on each boot:

swapDevices = [{
  device = "/dev/disk/by-partuuid/aaaaaaaaa-bbbb-cccc-dddd-0123456789ab";
  randomEncryption.enable = true; 
}];

The selected device will have all its content made unusuable at every boot. Using a partuuid or partlabel is recommended because it is less subject to change when the overall partition scheme changes.

If you want to use TRIM, set randomEncryption.allowDiscards in addition to the options. This has the security implication of:

  • telling whoever gets ahold of your swap drive which parts are being actually used (bad),
  • telling your SSD to not give out the data in unused parts and to not try to keep them around during garbage collection (good).

You will need to weigh between the two.

Using a random key makes hibernation impossible. If you want to use hibernation, use a regular Full Disk Encryption (or partial disk encryption with LUKS) scheme with an unchanging key.

Adjusting swap usage behaviour

Swappiness controls how aggressibely swap space is used, specifically how to free up memory when needed. By default, Linux uses a swappiness value of 60. Higher values will make the kernel prefer swapping out idle processes over dropping caches. Conversely lower values will try to avoid swapping as much as possible, keeping processes in RAM unless absolutely necessary. An optimal value is workload dependent and will will require experimentation.

❄︎ /etc/nixos/configuration.nix
boot.kernel.sysctl = {
  "vm.swappiness" = 10;
};

You can see your current swappiness level by cat /proc/sys/vm/swappiness. The lowest accepted value is 0 while the maximum value is 200. The lowest sane value is 1 (0 causes the system to not scan for unused anonymous pages, i.e. memory freed by processes, at all).

For more on tuning the swap, start with ArchWiki's description.

ZFS and swap

OpenZFS does not support swap on zvols nor do they support swap files on a ZFS dataset.

Instead you should set up a swap partition or swap file on a non-ZFS filesystem.[1]

Using swap files on Btrfs

For Btrfs file system-specific considerations, see the Btrfs swap file section.

Swapspace

Swapspace is a dynamic swap space manager for GNU/Linux. i.e. it allows unused disk space to be utilised as swap to handle the occasional memory-intensive task, and frees the disk space once done.

Enable it via services.swapspace.enable = true; in your nixos configuration. And after switching, check that systemctl status swapspace.service is green, that's all, swapspace will auto manage swap for you.

See all the options it supports here, search.nixos.org

You can also use zramSwap along with this service.

See your active swap partitions/files with swapon. For eg.

⚠︎
Warning: Do not run the following without swapspace active + more than 34GB free disk space (assuming 8GB ram) OR without 42GB+ ram to spare.
# Read the WARNING above, and adjust 2, 20GB according to your free space
$ # nix shell nixpkgs#stress.out -c stress --vm 2 --vm-bytes 20G
$ swapon
NAME                 TYPE       SIZE  USED PRIO
/dev/zram0           partition 13.8G  2.6G    5
/var/lib/swapspace/1 file       5.2G 59.2M   -2
/var/lib/swapspace/2 file       6.1G 56.4M   -3