Configuring Swap Space on Low Memory VPS

Configuring Swap Space on Low Memory VPS

What You’ll Need

  • Hetzner VPS or Contabo VPS for hosting (or DigitalOcean as an alternative)
  • Namecheap if you need a custom domain for server management tools
  • A Linux server running Ubuntu 22.04 LTS or Ubuntu 24.04 LTS with root or sudo access
  • Basic familiarity with SSH and Linux command-line operations

Table of Contents

Understanding Swap Space and Linux Memory Management

When I run lightweight workloads, microservices, or single-node database databases on inexpensive infrastructure, system RAM gets exhausted quickly. Out of Memory (OOM) Killer issues can strike without warning. The OOM Killer is a kernel task that terminates high-RAM processes like PostgreSQL, Redis, or Node.js when free physical memory hits zero.

Swap space acts as a safety cushion. It converts secondary storage, such as NVMe or SSD drives, into simulated physical memory. When RAM fills up, the Linux kernel shifts inactive memory pages from physical RAM to the dedicated swap area on disk.

Swap is not a replacement for high-speed physical RAM. Disk I/O speed is several orders of magnitude slower than DDR4 or DDR5 RAM bandwidth. However, having 1GB to 4GB of swap space keeps your system responsive and prevents application crashes during brief memory spikes.

If you run lightweight Docker stacks, such as setting up edge proxies like in my guide on How to Configure Traefik with Docker Compose, adding swap space prevents your proxy container from dying when sudden traffic spikes occur.

Step 1: Checking Existing Swap and System Memory Status

Before making any disk modifications, inspect your server’s current RAM and swap usage.

Log in to your server. If you host on a low-cost provider like a Hetzner VPS or a Contabo VPS, you might see zero swap configured by default.

Run the free command with human-readable flags to check physical RAM and current swap space:

free -h

On a fresh 1GB RAM virtual server without swap, the command output looks like this:

               total        used        free      shared  buff/cache   available
Mem:           981Mi       210Mi       412Mi       2.0Mi       358Mi       630Mi
Swap:             0B          0B          0B

You can also double-check whether any active swap devices or swap files are recognized by the kernel using swapon:

sudo swapon --show

If this command yields no output, no swap device is active.

Next, check available storage space using df. A swap file consumes standard disk space on your root filesystem, so you must verify you have enough disk headroom.

df -h /

The output indicates available space on the root mount point:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        19G  3.4G   15G  19% /

In this example, 15GB of disk space is available. Allocating a 2GB swap file is well within safety parameters.

💡 Fast-Track Your Project: Don’t want to configure this yourself? I build custom n8n pipelines and bots. Message me with code SYS3-HUGO.

Step 2: Creating and Allocating a Swap File

To create a swap file, allocate the desired file size on your filesystem. I recommend allocating a swap file equal to your total RAM size for VPS instances with up to 2GB RAM. For servers with more than 2GB RAM, allocating 2GB of swap is typically enough to absorb temporary spikes.

We can allocate disk space using fallocate or dd. The fallocate utility creates a pre-allocated file instantaneously.

Run the following command to create a 2GB file named /swapfile:

sudo fallocate -l 2G /swapfile

If fallocate is unsupported on your filesystem, such as certain XFS setups, use the dd command as a fallback:

sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress

Verify that the raw file was created with the correct size:

ls -lh /swapfile

The output should confirm the file size:

-rw-r--r-- 1 root root 2.0G Oct 24 10:00 /swapfile

Securing Swap File Permissions

By default, files created by root are readable by standard non-privileged users. Because swap memory holds raw runtime data, including private keys, application secrets, and environment variables, you must restrict file access permissions strictly to root.

Run chmod to set permissions to 600 (read and write access restricted strictly to root):

sudo chmod 600 /swapfile

Verify the permission changes:

ls -lh /swapfile

The permission string must display -rw-------:

-rw------- 1 root root 2.0G Oct 24 10:01 /swapfile

Formatting and Enabling the Swap File

Format the newly secured file so the Linux kernel recognizes it as swap space:

sudo mkswap /swapfile

The output confirms successful formatting:

Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=a1b2c3d4-e5f6-7890-abcd-1234567890ab

Now enable the swap file so the Linux kernel can begin utilizing it:

sudo swapon /swapfile

Verify that swap space is actively managed by running:

sudo swapon --show

The system will report your active swap storage:

NAME      TYPE BASE SIZE USED PRIO
/swapfile file       2G   0B   -2

Re-run free -h to verify total memory availability:

free -h

The summary will display your active swap space:

               total        used        free      shared  buff/cache   available
Mem:           981Mi       215Mi       150Mi       2.0Mi       616Mi       625Mi
Swap:          2.0Gi          0B       2.0Gi

This safety buffer ensures your server won’t crash when receiving heavy web traffic. For example, if you are Securing Inbound Webhooks Using Token Bucket Rate Limiting, high request bursts can cause momentary RAM spikes before requests are rate-limited. The swap file provides the necessary memory margin during those spikes.

Step 3: Making Swap Permanent and Tuning Kernel Parameters

By default, swap space enabled via swapon only lasts until the next system reboot. To make this swap file permanent across server restarts, edit /etc/fstab.

Persisting Swap in fstab

Back up your /etc/fstab file before editing:

sudo cp /etc/fstab /etc/fstab.bak

Append the /swapfile configuration to the end of /etc/fstab using tee:

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Verify that the line was correctly appended:

cat /etc/fstab

The file will now contain the persistent entry:

# /etc/fstab: static file system information.
UUID=11111111-2222-3333-4444-555555555555 / ext4 errors=remount-ro 0 1
/swapfile none swap sw 0 0

Tuning Kernel Swappiness and Cache Pressure

The default Linux kernel settings are tuned for desktop systems or high-performance bare-metal hardware, not low-resource Virtual Private Servers. To maximize performance, tune two kernel parameters: vm.swappiness and vm.vfs_cache_pressure.

  1. vm.swappiness: Controls how aggressively the kernel moves memory pages from physical RAM to swap storage. Values range from 0 to 100. The default value is 60. On an SSD/NVMe VPS, setting swappiness to 10 or 20 forces the kernel to favor active RAM, resorting to swap only when physical memory is nearly exhausted.

  2. vm.vfs_cache_pressure: Controls how aggressively the kernel reclaims directory and inode object caches relative to application memory. The default value is 100. Reducing this value to 50 helps retain directory structures in cache, improving disk performance without exhausting physical RAM.

Check your current system settings:

cat /proc/sys/vm/swappiness
cat /proc/sys/vm/vfs_cache_pressure

Set optimal values for immediate use:

sudo sysctl vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=50

To make these kernel parameters persistent across system reboots, append them to /etc/sysctl.conf:

echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.conf
echo "vm.vfs_cache_pressure=50" | sudo tee -a /etc/sysctl.conf

Apply the updated configuration using sysctl -p:

sudo sysctl -p

The command returns your applied settings:

vm.swappiness = 10
vm.vfs_cache_pressure = 50

Step 4: Monitoring Swap Usage with Python

To monitor system memory metrics continuously, set up a simple Python script to log physical RAM and swap utilization. If usage crosses defined thresholds, the script can send a webhook notification or trigger log alerts.

If you want to automate this check on a recurring basis, you can read my guide on How to Schedule Python Tasks using APScheduler to build robust, automated background tasks.

First, create a dedicated directory for your system monitoring tools:

sudo mkdir -p /opt/sysmon
sudo chown -R $USER:$USER /opt/sysmon
cd /opt/sysmon

Create a file named monitor_memory.py:

import sys
import logging
import urllib.request
import json
import psutil

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("/var/log/sysmon_memory.log"),
        logging.StreamHandler(sys.stdout)
    ]
)

RAM_THRESHOLD_PERCENT = 85.0
SWAP_THRESHOLD_PERCENT = 50.0

WEBHOOK_URL = ""

def send_alert(message):
    logging.warning(f"ALERT TRIGGERED: {message}")
    if not WEBHOOK_URL:
        logging.info("No webhook URL configured. Skipping remote notification.")
        return
    
    payload = json.dumps({"text": message}).encode("utf-8")
    req = urllib.request.Request(
        WEBHOOK_URL,
        data=payload,
        headers={"Content-Type": "application/json"}
    )
    try:
        with urllib.request.urlopen(req, timeout=5) as response:
            logging.info(f"Webhook notification sent successfully. Response code: {response.status}")
    except Exception as e:
        logging.error(f"Failed to send webhook notification: {e}")

def check_memory():
    ram = psutil.virtual_memory()
    swap = psutil.swap_memory()

    logging.info(f"RAM Usage: {ram.percent}% (Used: {ram.used // (1024*1024)}MB / Total: {ram.total // (1024*1024)}MB)")
    logging.info(f"Swap Usage: {swap.percent}% (Used: {swap.used // (1024*1024)}MB / Total: {swap.total // (1024*1024)}MB)")

    if ram.percent >= RAM_THRESHOLD_PERCENT:
        send_alert(f"High RAM usage detected: {ram.percent}% used on host.")

    if swap.percent >= SWAP_THRESHOLD_PERCENT:
        send_alert(f"High Swap usage detected: {swap.percent}% used on host.")

if __name__ == "__main__":
    check_memory()

Install psutil system-wide via apt or virtual environment:

sudo apt-get update
sudo apt-get install -y python3-psutil

Execute the script manually to confirm functionality:

python3 /opt/sysmon/monitor_memory.py

The script produces clean output in stdout and logs directly to /var/log/sysmon_memory.log:

2024-10-24 10:15:30,102 [INFO] RAM Usage: 22.4% (Used: 220MB / Total: 981MB)
2024-10-24 10:15:30,103 [INFO] Swap Usage: 0.0% (Used: 0MB / Total: 2048MB)

Automating the Script with Systemd

To run this monitor on a set schedule without relying on cron, create a systemd service and timer.

Create the service file /etc/systemd/system/sysmon-memory.service:

[Unit]
Description=System Memory and Swap Utilization Monitor
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /opt/sysmon/monitor_memory.py

[Install]
WantedBy=multi-user.target

Create the corresponding timer file /etc/systemd/system/sysmon-memory.timer:

[Unit]
Description=Run System Memory Monitor every 5 minutes

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min
Unit=sysmon-memory.service

[Install]
WantedBy=timers.target

Reload systemd to detect the new configuration, then enable and start the timer:

sudo systemctl daemon-reload
sudo systemctl enable --now sysmon-memory.timer

Verify the active timer status using systemctl:

sudo systemctl list-timers sysmon-memory.timer

The command output confirms the upcoming execution schedule:

NEXT                        LEFT    LAST PASSED UNIT                 ACTIVATES
Thu 2024-10-24 10:20:00 UTC 4min 15s n/a  n/a    sysmon-memory.timer sysmon-memory.service

Now, your Linux VPS has an optimized swap file to catch temporary memory spikes, kernel settings tuned specifically for cloud infrastructure, and automated system monitoring to track memory metrics over time.

Getting Started

Deploying swap space is the single most cost-effective performance upgrade you can apply to low-resource virtual private servers. You can deploy reliable, cost-effective infrastructure using modern cloud providers:

  • Spin up affordable virtual servers directly on a Hetzner VPS or a Contabo VPS.
  • Use DigitalOcean if you prefer quick Droplet setups with simple pricing options.
  • If you run managed cloud tasks, consider using n8n Cloud to offload heavy background automation tasks completely.

Outsource Your Automation

Don’t have time? I build production n8n workflows, WhatsApp bots, and fully automated YouTube Shorts pipelines. Hire me on Fiverr, mention SYS3-HUGO for priority. Or DM at chasebot.online.

Want to automate this yourself?

Start with n8n Cloud (free tier available) or self-host on a Hetzner VPS for full control.

Want this engine running on your own VPS?

This blog publishes itself — daily, unattended, on free API tiers. The full engine, Hugo theme, and setup guide are available as System 3.

Get System 3
system online