DEV Community

Cover image for Configuring Swap Space on Low Memory VPS
Raizan
Raizan

Posted on Originally published at chasebot.online

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

sudo swapon --show
Enter fullscreen mode Exit fullscreen mode

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 /
Enter fullscreen mode Exit fullscreen mode

The output indicates available space on the root mount point:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        19G  3.4G   15G  19% /
Enter fullscreen mode Exit fullscreen mode

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-DEVTO.

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

ls -lh /swapfile
Enter fullscreen mode Exit fullscreen mode

The output should confirm the file size:

-rw-r--r-- 1 root root 2.0G Oct 24 10:00 /swapfile
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Verify the permission changes:

ls -lh /swapfile
Enter fullscreen mode Exit fullscreen mode

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

-rw------- 1 root root 2.0G Oct 24 10:01 /swapfile
Enter fullscreen mode Exit fullscreen mode

Formatting and Enabling the Swap File

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

sudo mkswap /swapfile
Enter fullscreen mode Exit fullscreen mode

The output confirms successful formatting:

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

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

sudo swapon /swapfile
Enter fullscreen mode Exit fullscreen mode

Verify that swap space is actively managed by running:

sudo swapon --show
Enter fullscreen mode Exit fullscreen mode

The system will report your active swap storage:

NAME      TYPE BASE SIZE USED PRIO
/swapfile file       2G   0B   -2
Enter fullscreen mode Exit fullscreen mode

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

free -h
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Enter fullscreen mode Exit fullscreen mode

Verify that the line was correctly appended:

cat /etc/fstab
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Set optimal values for immediate use:

sudo sysctl vm.swappiness=10
sudo sysctl vm.vfs_cache_pressure=50
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Apply the updated configuration using sysctl -p:

sudo sysctl -p
Enter fullscreen mode Exit fullscreen mode

The command returns your applied settings:

vm.swappiness = 10
vm.vfs_cache_pressure = 50
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

Install psutil system-wide via apt or virtual environment:

sudo apt-get update
sudo apt-get install -y python3-psutil
Enter fullscreen mode Exit fullscreen mode

Execute the script manually to confirm functionality:

python3 /opt/sysmon/monitor_memory.py
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

sudo systemctl daemon-reload
sudo systemctl enable --now sysmon-memory.timer
Enter fullscreen mode Exit fullscreen mode

Verify the active timer status using systemctl:

sudo systemctl list-timers sysmon-memory.timer
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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-DEVTO for priority. Or DM at chasebot.online.


Originally published on Automation Insider.

Top comments (0)