Linux & Systems

Add a Swap File to a Small VPS

Check memory first, create a swap file that survives reboots, set vm.swappiness with a sysctl drop-in, and remove it cleanly if you change your mind.

6 min read
linuxmemorydebianubuntuconfiguration

Golden grassland stretching to distant hills beneath a wide blue sky full of white clouds

A 1 GB VPS runs happily until the day a package upgrade, a build, or a database wants a little more memory than the machine has. Without swap, the kernel’s out-of-memory (OOM) killer picks a process and ends it. It prefers big ones, and on a small server the biggest process is usually the one you care about.

Swap isn’t extra RAM. It’s a place to park memory pages nobody is touching so the active ones still fit, the way winter coats go to the basement so the hallway stays usable. Disk is much slower than RAM, so a machine that swaps constantly is undersized. A machine that occasionally parks a few hundred megabytes of idle pages is using swap exactly as intended.

The steps below target Debian 13 and Ubuntu 24.04 or 26.04 on the usual ext4 root filesystem. Btrfs needs one extra detail, covered where it comes up.

Look before adding anything

free -h
swapon --show
               total        used        free      shared  buff/cache   available
Mem:           957Mi       498Mi        71Mi       1.0Mi       388Mi       459Mi
Swap:             0B          0B          0B

Read available, not free. free counts memory nobody is using at all, while available estimates what a new program could get without swapping, including page cache the kernel can drop. A tiny free next to a healthy available is normal Linux.

If swapon --show prints nothing, no swap is active. If it lists something, you already have swap, maybe a partition or zram, and adding another layer needs a reason.

Check whether the OOM killer has already been busy in the current boot:

sudo journalctl -k | grep -i 'out of memory'

A few hits there make a better case for swap than any rule of thumb. Then check room and filesystem type:

df -h /
findmnt -no FSTYPE --target /

If df shows the disk is already tight, run through the disk space triage first. A swap file that fills the disk swaps one outage for another.

Pick a size

For a small VPS, 1 to 2 GiB is a sensible start. Ubuntu’s server installer is a handy reference: it suggests double the RAM up to 1 GiB, 2 GiB for machines up to 2 GiB, and the same as RAM up to 4 GiB, capped at a quarter of the free disk space. The examples below use 2 GiB.

Create the file

On util-linux 2.41 or newer (Debian 13 and Ubuntu 26.04 have it), mkswap can do the whole job:

mkswap --version
sudo mkswap --file --size 2G /swapfile
Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=530f507b-14d6-475a-8990-aa4c372d13f5

That creates the file with 0600 permissions, allocates its blocks, and sets the no-copy-on-write attribute that btrfs requires.

Older util-linux (Debian 12, Ubuntu 24.04) doesn’t have --file, so create the file first:

# Option A: instant, reserves blocks without writing them
sudo fallocate -l 2G /swapfile

# Option B: slower, writes every block
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress

sudo chmod 600 /swapfile
sudo mkswap /swapfile

The choice matters because the kernel writes to a swap file directly, without help from the filesystem, so the file can’t contain holes. fallocate works on ext4, and it’s what Ubuntu’s own installer uses there. swapon(8) warns that some filesystems treat preallocated files as having holes, though, so dd is the portable choice. If swapon later says skipping - it appears to have holes, recreate the file with dd. Don’t use truncate or cp, because both produce sparse files.

The chmod isn’t decoration. Swap holds whatever memory was paged out, which can include passwords and keys. If you forget it, mkswap complains: insecure permissions 0644, fix with: chmod 0600 /swapfile.

On btrfs, use mkswap --file or sudo btrfs filesystem mkswapfile --size 2G /swapfile. Keep in mind that a subvolume holding an active swap file can’t be snapshotted, which matters if a snapshot tool manages your root subvolume.

Turn it on and make it stick

sudo swapon /swapfile
swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   2G   0B   -2

A negative PRIO just means the kernel picked the priority. To keep the swap file across reboots, back up /etc/fstab and add a line for it:

sudo cp /etc/fstab /etc/fstab.bak
echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab
sudo systemctl daemon-reload

daemon-reload makes systemd regenerate its units from fstab now instead of at the next boot. Now check the new line without rebooting:

sudo swapoff /swapfile
sudo swapon -a
swapon --show

swapon -a activates everything marked swap in fstab. If /swapfile comes back, the line is right.

Tune swappiness

vm.swappiness takes a value from 0 to 200 and defaults to 60. It tells the kernel how to weigh swapping out program memory against dropping file cache. Lower values keep program memory in RAM longer, so swap mostly gets used when it’s actually needed.

sysctl vm.swappiness
vm.swappiness = 60

To treat swap as a safety net rather than everyday workspace, lower it with a drop-in file:

echo 'vm.swappiness = 10' | sudo tee /etc/sysctl.d/90-swappiness.conf
sudo sysctl -p /etc/sysctl.d/90-swappiness.conf
vm.swappiness = 10

No single number is right for every server. 10 is a conservative start, and the default is defensible too. Use /etc/sysctl.d/ rather than /etc/sysctl.conf. On Debian 13, systemd-sysctl no longer reads sysctl.conf at boot, so a setting there would work today and quietly disappear after the next reboot.

Watch it for a few days

free -h shows how much swap is in use. vmstat 5 shows the rate: the si and so columns count pages swapped in and out per second. Occasional blips are fine. If those columns stay above zero under normal load, the machine needs more RAM, not more swap.

Remove it cleanly

Order matters. Turn swap off before you delete the file:

free -h
sudo swapoff /swapfile
sudoedit /etc/fstab        # delete the /swapfile line
sudo systemctl daemon-reload
sudo rm /swapfile

swapoff has to pull every swapped page back into RAM, so first check free -h and make sure the swap in use fits comfortably inside available. If you added the swappiness drop-in, remove it and restore the default:

sudo rm /etc/sysctl.d/90-swappiness.conf
sudo sysctl -w vm.swappiness=60

References

Cover photo: Unsplash.