Illustration of a RAM module, a swap file on disk and a synchronized clock on a Linux VPS
Linux

Add a Swap File on Ubuntu and Fix Time Sync on Your VPS

A fresh Linux VPS boots in seconds and feels fast, right up to the night a backup job, a burst of PHP workers and a heavy database query all want memory at the same moment. The kernel runs out of RAM, picks a victim and kills it, very often MySQL. A week later something different breaks: a certificate renewal fails, 2FA codes get rejected, and the timestamps in your logs do not match what actually happened. Both problems come from two small things most server images leave half-done: there is no swap, and nobody checked the clock. In this guide we fix both properly, with a swap file that survives reboots, a sane swappiness value, the right timezone and working NTP synchronization, and we explain every command as we go.

Everything below works on Debian 13 and Ubuntu 24.04, on a KVM VPS, logged in as a regular user with sudo rights. Where the two distributions behave differently, we say so explicitly. If your VPS is an LXC container, read the note in Step 1 first, because some of these settings belong to the host there, not to you.

What you need

  • A Linux VPS running Debian 13 or Ubuntu 24.04 (a DreamServer VPS works out of the box).
  • SSH access as a user that can run sudo.
  • About 2-4 GB of free disk space for the swap file.
  • Ten to fifteen minutes. No reboot is required; we only do one at the end to prove the settings stick.

What swap is, and why a small VPS needs it

RAM is the fast working memory where every running program keeps its data. It is limited: a 1 GB or 2 GB VPS fills up quicker than people expect, because the web server, the database, a PHP pool and the operating system itself all live there at the same time.

Swap is a reserved area on disk that the kernel can use as overflow. When RAM gets tight, the kernel moves memory pages that nobody has touched in a while (an idle worker, the start-up code of a daemon, a cache nobody reads) out to swap, and frees the RAM for things that are actually active. Disk is much slower than RAM, so swap is not “extra RAM” you can live on permanently. It is a safety buffer.

Without any swap, when RAM runs out the kernel has only one tool left: the OOM killer (Out Of Memory killer). It chooses a process, usually the one using the most memory, and terminates it on the spot. On a typical server that is the database. With a modest amount of swap, the same spike makes the server a bit slower for a minute instead of taking a service down.

Swap can live on a dedicated disk partition or in an ordinary file. On a VPS a swap file is the better choice: you do not need to repartition anything, you can resize or delete it in a minute, and on modern kernels its performance is equivalent to a partition. Most VPS images, including the Ubuntu cloud images, ship with no swap at all, which is why this is worth doing on day one.

Why the clock matters more than you think

Every server keeps a system clock, internally in UTC (Coordinated Universal Time, the global reference time with no daylight saving). The timezone is only a display setting on top of it: it decides how that UTC moment is shown in logs, which hour “3 AM” means for cron, and what your applications print.

The clock itself drifts. The timer a virtual machine relies on is never perfect, and pausing, migrating or restoring a VM from a snapshot can make it jump. NTP (Network Time Protocol) solves this: a small background service regularly asks public time servers what time it is and gently corrects the local clock.

A wrong clock breaks more than you would expect:

  • TLS certificates have a “not before” and a “not after” date. If your clock is behind, a brand new certificate looks “not yet valid”; if it is ahead, a valid one looks expired. Let’s Encrypt renewals, apt over HTTPS and outgoing API calls can all fail.
  • 2FA codes (TOTP, the six digits from an authenticator app) are valid for roughly 30 seconds, sometimes with one extra step of tolerance. A server that is a minute off rejects correct codes.
  • Logs from different machines cannot be correlated if their clocks disagree, which hurts exactly when you investigate an incident.
  • Cron jobs run at the wrong local hour if the timezone is not what you think it is.
Memory path and time path on a VPSMEMORY: what happens when RAM fills upApplicationsweb, DB, PHPRAMfast, limitedwith swapno swapSwap fileslower, but still runningOOM killera process is killedTIME: how the clock stays correctNTP serverspool.ntp.orgUDP 123timesyncdor chronyadjustsSystem clockkept in UTCtimezone only changes displayLogsCron jobsTLS and 2FA
Swap catches memory overflow before the OOM killer has to act; NTP keeps the UTC system clock right, and the timezone only changes how it is displayed.

The plan: add a swap file on Ubuntu or Debian, then fix the clock

The 7 steps in this guide1234567Checkfree, dfCreatefallocateEnableswapon, fstabTuneswappinessTimezonetimedatectlNTP synctimesyncdVerifyreboot testSwap (1-4)Time (5-6)Verify (7)
Steps 1 to 4 create and tune the swap file, steps 5 and 6 fix timezone and NTP, step 7 proves everything survives a reboot.

Steps 1 to 4 build and tune the swap file, steps 5 and 6 fix the time, and step 7 proves that everything survives a reboot. The two halves are independent, so you can stop after Step 4 and come back for the clock later.

Step 1: Check memory, disk and existing swap

Before creating anything, let us see what we have. First, find out what kind of virtualization the VPS uses:

systemd-detect-virt

On a KVM VPS this prints kvm. If it prints lxc, you are inside a container that shares the kernel with the host. In an unprivileged LXC container you cannot create or enable swap (swapon fails with “Operation not permitted”), you cannot change vm.swappiness, and you cannot set the clock, because memory limits, swap and time are controlled by the host. You can still set the timezone (Step 5). If you are on LXC and need more memory headroom, ask your provider to raise the memory or swap limit of the container.

Now check memory and current swap:

free -h
swapon --show

free -h shows memory in human-readable units. On a fresh 2 GB VPS it looks roughly like this:

               total        used        free      shared  buff/cache   available
Mem:           1.9Gi       610Mi       880Mi       1.0Mi       600Mi       1.3Gi
Swap:             0B          0B          0B

The columns to watch are total and available (how much memory programs can still get without swapping). The Swap: line shows zeros and swapon --show prints nothing at all: there is no swap yet. If swapon --show already lists a device or file, your image ships with swap and you can jump to Step 4.

Finally, check free disk space and the filesystem type of the root partition:

df -h /
findmnt -no FSTYPE /

You need enough free space for the swap file plus a comfortable margin; never fill a disk to 100%. On Debian and Ubuntu VPS images the filesystem is almost always ext4, which is what the next step assumes. If you see btrfs, read the note in Step 2.

Step 2: Create the swap file

How big should the swap file be?

Old rules like “twice the RAM” come from desktops with hibernation and very little memory. A VPS never hibernates, and a huge swap file only lets a runaway process thrash the disk for longer before it fails anyway. A sensible starting point:

VPS RAMSuggested swapReasonable range
1 GB2 GB1-2 GB
2 GB2 GB1-2 GB
4 GB2 GB2-4 GB
8 GB4 GB2-4 GB
16 GB or more4 GB2-4 GB
Suggested swap size by VPS RAM (approx.)012345Suggested swap (GB)2 GB2 GB2 GB4 GB4 GB1 GB RAM2 GB RAM4 GB RAM8 GB RAM16 GB RAMVPS RAM size (bars are a starting point, not a hard rule)
Approximate starting values: on small plans swap can match or exceed RAM, on larger plans 2-4 GB of swap is plenty.

We use 2 GB in the examples below. If you picked a different size, replace 2G with your value.

Allocate the file

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
ls -lh /swapfile

fallocate reserves 2 GB of disk space for the file instantly, without writing data. chmod 600 makes the file readable and writable only by root, which is essential: swap can contain fragments of anything that was ever in memory, including passwords and private keys. The ls output should look like this:

-rw------- 1 root root 2.0G Nov 10 08:00 /swapfile

If fallocate is not supported on your filesystem, or later swapon complains that the file “has holes”, create it the slower but always safe way, by writing real zeros:

sudo rm -f /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
sudo chmod 600 /swapfile

2048 blocks of 1 MiB give exactly 2 GiB; adjust count for other sizes. On btrfs, an ordinary file cannot be used as swap unless copy-on-write is disabled for it; use sudo btrfs filesystem mkswapfile --size 2g /swapfile instead, which takes care of that for you.

Format it as swap

sudo mkswap /swapfile

mkswap writes a small header that marks the file as swap space. Expected output:

Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
no label, UUID=3f1c2a9e-7b1d-4c55-9a0e-2d6b8f4e1a77

The UUID will be different on your server, that is normal.

Step 3: Enable swap and make it permanent

Turn the swap file on:

sudo swapon /swapfile
swapon --show

You should see:

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

Swap is active right now, but it would disappear after a reboot. To make it permanent we add a line to /etc/fstab, the file that tells the system which disks and swap areas to activate at boot. A broken fstab can stop a server from booting cleanly, so we make a backup first:

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

The line reads: the device is /swapfile, it has no mount point (none), its type is swap, use default swap options (sw), and the two zeros disable dump and filesystem checks. tee -a appends the line with root rights and echoes it back to the terminal. A plain sudo echo ... >> /etc/fstab would fail, because the >> redirection runs as your normal user, not as root.

Now test the fstab entry without rebooting, by turning swap off and asking the system to enable everything listed in fstab:

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

If /swapfile shows up again, the fstab line works. If swapon -a prints an error, open the file with sudo nano /etc/fstab and fix the line, or restore the backup with sudo cp /etc/fstab.bak /etc/fstab. Also check that you did not run the tee -a command twice, which would leave a duplicate line.

Step 4: Tune swappiness

Swappiness is a kernel setting, from 0 to 200 on current kernels, that tells Linux how eagerly to move application memory to swap compared to dropping file cache. The default is 60, a value tuned for desktops. On a server we want the kernel to keep application memory in RAM as long as possible and swap only under real pressure, so a value around 10 works well. Do not use 0: it does not disable swap, but it makes the kernel avoid swap until the very last moment, which brings back much of the OOM risk we are trying to remove.

Check the current value and change it for the running system:

cat /proc/sys/vm/swappiness
sudo sysctl vm.swappiness=10

The second command confirms with vm.swappiness = 10. To keep the value after a reboot, put it in its own file under /etc/sysctl.d/ and reload all sysctl settings:

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

sysctl --system lists every configuration file it reads; you should see /etc/sysctl.d/99-swappiness.conf among them, followed by vm.swappiness = 10.

A Debian versus Ubuntu note: many older guides tell you to edit /etc/sysctl.conf. On Ubuntu 24.04 that file still exists and is read at boot, but on Debian 13 it is no longer shipped and no longer read at boot, so a setting placed there is silently ignored after a restart. A file in /etc/sysctl.d/ works on both, which is why we use it. You may also see advice to set vm.vfs_cache_pressure=50; the default of 100 is fine for most servers, so leave it alone unless you have measured a reason to change it.

Step 5: Set the timezone

Let us look at the current time configuration:

timedatectl

On a fresh VPS the output usually looks like this:

               Local time: Tue 2026-11-10 06:00:12 UTC
           Universal time: Tue 2026-11-10 06:00:12 UTC
                 RTC time: Tue 2026-11-10 06:00:12
                Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

Time zone is the display setting. System clock synchronized and NTP service tell us whether time synchronization works, which we handle in Step 6. RTC in local TZ: no means the virtual hardware clock is kept in UTC, which is correct on Linux; leave it like that.

UTC or local time?

Both are valid; what matters is choosing on purpose. UTC never changes with daylight saving, so there is never a missing or doubled hour in your logs, and servers in different countries line up directly. Many teams keep every server on UTC. Local time is friendlier when the server serves one country and you read logs and schedule jobs in local hours. For a business in Romania, Europe/Bucharest is the natural choice. Find the exact name and set it:

timedatectl list-timezones | grep -i bucharest
sudo timedatectl set-timezone Europe/Bucharest
timedatectl

The Time zone line now shows Europe/Bucharest (EET, +0200) in winter and EEST, +0300 in summer. The underlying system clock did not change at all, only the way it is displayed.

Cron reads the timezone when it starts, so restart it to make scheduled jobs follow the new zone. The service is called cron on both Debian and Ubuntu (some other distributions call it crond):

sudo systemctl restart cron

If this says the unit does not exist, cron is simply not installed, which happens on minimal Debian installs; there is nothing to restart. Keep in mind that some software keeps its own timezone setting: PHP has date.timezone, MySQL and PostgreSQL have their own time zone variables, and Docker containers run in UTC unless you pass a TZ variable or mount /etc/localtime into them.

Step 6: Turn on NTP time sync

Two NTP clients are common on Debian and Ubuntu: systemd-timesyncd, a lightweight client that is perfect for a single VPS, and chrony, a full NTP implementation with more features. You need exactly one of them. Check which one is running:

systemctl is-active systemd-timesyncd chrony

The command prints one line per service, active or inactive. On Ubuntu 24.04 you will normally see timesyncd active, configured to use ntp.ubuntu.com. On Debian 13 it depends on the image: many use timesyncd with the debian.pool.ntp.org servers, some cloud images ship chrony, and minimal installs may have neither. If both lines say inactive, install timesyncd:

sudo apt update
sudo apt install systemd-timesyncd

The two packages conflict on purpose: installing one removes the other, so you never end up with two daemons fighting over the clock.

How far an unsynced clock drifts (approx., 20 ppm)After 1 day~2 sAfter 1 week~12 sAfter 1 month~52 sAfter 3 months~156 s30 s: typical 2FA code window04080120160Clock error without NTP (seconds)Snapshot restores or long VM pauses can cause much larger jumps
Approximate drift of an uncorrected clock at 20 ppm: within a month it is already outside the window 2FA codes tolerate.

Configure timesyncd

The defaults work, but we prefer nearby servers from the public NTP pool. Instead of editing the main config file, we add a drop-in file, which survives package upgrades untouched:

sudo mkdir -p /etc/systemd/timesyncd.conf.d
sudo tee /etc/systemd/timesyncd.conf.d/10-servers.conf > /dev/null <<'EOF'
[Time]
NTP=0.ro.pool.ntp.org 1.ro.pool.ntp.org 2.ro.pool.ntp.org
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org
EOF
sudo systemctl restart systemd-timesyncd
sudo timedatectl set-ntp true

NTP= lists the servers we want, here the Romanian zone of the pool; outside Romania use your country zone or simply pool.ntp.org. FallbackNTP= is used only if none of the primary servers answer. set-ntp true makes sure synchronization is switched on. Now check the status:

timedatectl timesync-status
       Server: 192.0.2.10 (0.ro.pool.ntp.org)
Poll interval: 34min 8s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 2
    Reference: C035676C
    Precision: 1us (-24)
Root distance: 1.035ms (max: 5s)
       Offset: -312us
        Delay: 4.812ms
       Jitter: 410us
 Packet count: 6
    Frequency: +11.204ppm

The lines that matter: Server shows which machine answered, Stratum how many hops it is from a reference clock (2 is great), and Offset how far our clock was from it, here 0.3 milliseconds. Right after a restart the poll interval is short and it grows as the clock stabilizes. Running timedatectl again should now show System clock synchronized: yes.

If your system uses chrony

Skip the timesyncd configuration and check chrony instead:

chronyc tracking
chronyc sources -v

tracking shows the current offset in the System time line, and sources lists the servers; the one marked with * is the one in use. On both Debian and Ubuntu the main config is /etc/chrony/chrony.conf, which also reads extra files from /etc/chrony/sources.d/. To use pool servers of your choice, create /etc/chrony/sources.d/ro-pool.sources containing the single line pool ro.pool.ntp.org iburst, then run sudo chronyc reload sources.

Firewall

An NTP client sends requests from your server to UDP port 123 on the time servers and receives their replies. With ufw in its default mode (deny incoming, allow outgoing) this already works, and you should not open port 123 inbound: your VPS is a client, not a time server. Only if you changed the outgoing policy to deny do you need sudo ufw allow out 123/udp.

Step 7: Verify everything after a reboot

None of the changes above needs a reboot, they are all active already. We reboot once only to prove they come back on their own:

sudo reboot

Log back in after a minute and run:

swapon --show
cat /proc/sys/vm/swappiness
timedatectl

Expect /swapfile listed with its size, 10 for swappiness, your chosen timezone, and System clock synchronized: yes (right after boot it can take a few seconds to turn to yes).

While we are talking about reboots, a Debian versus Ubuntu difference: Ubuntu creates the file /var/run/reboot-required when installed updates need a restart, so ls /var/run/reboot-required is a quick check there. Debian does not reliably create that file; install the needrestart package to find out what needs restarting. Nothing in this guide creates that file on either system.

Keeping an eye on swap

Some swap usage is perfectly normal: idle pages parked on disk cost you nothing. What you want to avoid is constant traffic in and out of swap. Check it with:

vmstat 5 5

This prints five samples, five seconds apart. Look at the si (swap in) and so (swap out) columns. Occasional non-zero values are fine; large values in every sample mean the server is swapping all the time. That is a sign it is short on RAM, and the fix is to reduce memory usage or move to a larger plan, not to make the swap file bigger.

Troubleshooting and common mistakes

  • swapon: /swapfile: swapon failed: Operation not permitted: you are almost certainly inside an LXC container (check systemd-detect-virt). Swap is managed by the host there.
  • swapon: /swapfile: insecure permissions 0644, 0600 suggested: you skipped sudo chmod 600 /swapfile. Run it and try again.
  • swapon: /swapfile: swapfile has holes or Invalid argument: the filesystem does not accept a preallocated file. Recreate it with the dd command from Step 2, then mkswap again.
  • Swap is gone after a reboot: the fstab line is missing or contains a typo. Check grep swap /etc/fstab and systemctl status swapfile.swap, the unit systemd generates automatically for /swapfile.
  • sysctl: setting key "vm.swappiness": Read-only file system: again a container; the host decides this value.
  • Swappiness back to 60 after a reboot on Debian 13: you probably put it in /etc/sysctl.conf. Move it to /etc/sysctl.d/99-swappiness.conf.
  • System clock synchronized: no: check that a client runs (systemctl status systemd-timesyncd), read its log with journalctl -u systemd-timesyncd -n 30, and make sure outbound UDP 123 is not blocked. In a container, timesyncd does not start at all by design, and NTP service shows n/a or inactive: the host clock is used.
  • Cron runs jobs at the old hour: you changed the timezone but did not restart cron.
  • “certificate is not yet valid” or expired-certificate errors from curl or apt: compare date with a correct clock. If it is off, fix NTP first, then retry.
  • The disk filled up: the swap file is too big for a small disk. Shrink it as described in the FAQ below.

Security notes

  • Permissions on the swap file are not optional. Swap holds raw memory pages: session tokens, database passwords, decrypted data. Keep it at 600, owned by root.
  • Swap is not encrypted by default. On a KVM VPS the virtual disk is yours alone, but if your threat model includes someone reading disk images or backups, consider encrypted swap with a random key generated at boot, or avoid swap for processes that hold very sensitive secrets.
  • Do not run an open NTP server. Your VPS only needs to query time servers. Keep UDP 123 closed inbound; badly configured public NTP servers have a long history of being abused for amplification attacks.
  • Correct time is a security control. TLS validation, 2FA, token expiry and forensic timelines all depend on it. Treat “clock not synchronized” as an alert to fix, not a cosmetic warning.
  • Swap does not fix a memory leak. If an application keeps growing, swap only delays the crash. Monitor memory and set limits where you can, for example memory limits on Docker containers.

So, is it worth ten minutes?

Absolutely. A right-sized swap file turns out-of-memory crashes into brief slowdowns, a low swappiness keeps your applications in RAM where they belong, and a synchronized clock with a deliberate timezone keeps certificates, 2FA, cron and logs honest. It is the kind of setup nobody notices when it is done and everybody notices when it is missing.

If you are starting a new project, our VPS plans run on KVM in our own data center in Romania, so everything in this guide works exactly as written. And if you would rather not handle swap, kernel tuning, time sync, updates and monitoring yourself, our server administration team can set up the server and look after it for you.

Frequently asked questions

Will swap make my VPS slower?

Not by itself. Swap is only used when RAM is under pressure, and with swappiness at 10 the kernel moves only memory that is truly idle. Without swap, the same situation ends with a killed process, which is much worse than a short slowdown.

Swap file or swap partition?

On a VPS, a swap file. Performance is equivalent on modern kernels, and a file is far easier to create, resize or remove than a partition.

How do I resize or remove the swap file?

Turn it off with sudo swapoff /swapfile. To resize, run fallocate with the new size, then chmod 600, mkswap and swapon again; the fstab line stays the same. To remove it, delete the line from /etc/fstab and run sudo rm /swapfile. Make sure there is enough free RAM before swapoff, because everything currently in swap has to move back into memory.

Do I still need swap with 16 GB of RAM?

A small swap file of 2-4 GB is still useful as a parking place for idle pages and a buffer for unexpected spikes. It costs only a little disk space.

What about zram?

zram creates a compressed swap device inside RAM. It helps on very small machines and can be combined with a swap file, but it trades CPU time for memory. For most VPS workloads a plain swap file with a sensible swappiness is simpler and good enough.

Should the server use UTC or local time?

If you run servers in several countries or care about correlating logs, use UTC. If everything serves Romania and you prefer reading local hours, Europe/Bucharest is fine. Internally the system clock is UTC either way.

Trusted By & Member Of

We are proud members of leading internet infrastructure organizations.

RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX RIPE NCC MANRS PeeringDB RoTLD DSIX SBIX 4IXP LOCIX Euro-IX