Introduction

If you've got a Proxmox VE node running four or five Ubuntu VMs and you check free -h on the host, you might notice the total memory used is lower than you'd expect given what you assigned to each guest. That's not a bug. There's a good chance a kernel feature called KSM is quietly merging identical memory pages across those VMs in the background, and it's been doing it since the moment you installed Proxmox.

Most people never touch this setting. It just runs. But once you understand what it's doing, you'll want to know how to check it, tune it, and — in a couple of specific situations — turn it off.

What You Will Learn

By the end of this guide you'll know what KSM actually does at the memory level, why Proxmox enables it by default, and how to check whether it's saving you any real RAM right now on your own node. You'll also walk through disabling it node-wide, disabling it for a single VM without touching the rest of your cluster, and adjusting the tuning file that controls how aggressively it scans. Along the way we'll cover the handful of errors people run into and the one security tradeoff you genuinely need to think about before leaving it on for certain workloads.

What Is This Feature?

KSM stands for Kernel Samepage Merging. It's a feature built into the Linux kernel itself, not something Proxmox bolted on, and it ships enabled by default on every Proxmox VE install.

Here's the idea in plain terms: when you run several VMs on the same host, especially VMs using the same guest operating system, a huge chunk of what's sitting in each VM's RAM is identical. Think about it — five Debian 13 VMs each have their own copy of the kernel, the C library, systemd, and dozens of other shared libraries loaded into memory. Without KSM, that's five separate physical copies of essentially the same bytes.

A background kernel thread called ksmd scans through memory pages that have been marked as shareable, hashes their contents, and looks for matches. When it finds two pages with identical content, it maps both virtual addresses to a single physical page and frees the duplicate. The moment either VM tries to write to that page, the kernel splits it back into a private copy first — this is called copy-on-write, and it's the same mechanism that keeps `fork()` cheap on any Linux system. Nothing about this is visible to the guest OS; from inside the VM, memory behaves exactly like normal RAM.

On Proxmox, the actual scanning and tuning is handled by a small daemon called ksmtuned, which watches how much memory pressure the host is under and adjusts how hard the kernel's KSM thread works. You can see it as a systemd service, and it's what most of this guide is about controlling.

Why Would You Use It?

The honest answer for most homelab setups: you don't have to do anything, because it's already running and already helping. The question is really whether you should leave it on, and for which VMs.

KSM pays off most when you're running several VMs of the same or similar guest OS on one host — a handful of Ubuntu Server VMs, a stack of identical Debian containers-that-are-actually-VMs for testing, or a lab full of near-identical Windows Server instances. The more duplication there is between guests, the more physical RAM you get back. On a node with six similar Linux VMs, it's not unusual to see several hundred megabytes to a couple of gigabytes reclaimed, depending on how much of each VM's memory is idle library and kernel pages versus active application data.

Where it doesn't help much: a single VM, or a node running wildly different guest OSes with little in common (one Windows VM, one FreeBSD VM, one Alpine container). There's just nothing to deduplicate.

And there's a real reason to turn it off that has nothing to do with performance. Because KSM merges pages across VM boundaries, researchers have shown it can be used as a side channel — one VM can, under the right conditions, infer information about what another VM on the same host is doing by timing how long writes take to pages that may or may not be shared. If you're running a multi-tenant host where VMs belong to different customers or different trust boundaries, that's a real consideration, and it's worth checking whether your industry or region has compliance rules that address it directly. For a homelab where every VM is yours, it's a non-issue.

Prerequisites

You'll need a working Proxmox VE 8.x or 9.x installation with at least one VM already created — ideally two or three similar ones, so you can actually see KSM doing something. You'll also need root shell access to the host, either through the web-based Shell in the Proxmox GUI or over SSH. None of the commands here require anything installed beyond what ships on a default Proxmox node.

A quick note before you start: everything in the tutorial section operates at the host level or through qm, Proxmox's VM management command. There's no equivalent GUI toggle for KSM the way there is for ballooning — this is one of the few settings you'll only find on the command line.

Step-by-Step Tutorial

Start by checking whether KSM is even running on your node. Open a shell on the host and run:

systemctl status ksmtuned

On a default install you'll see it listed as active (running). If it says inactive or disabled, someone (maybe a previous version of your install, maybe you) turned it off already.

Next, check whether it's actually finding anything to merge. The kernel exposes live statistics under /sys/kernel/mm/ksm/:

cat /sys/kernel/mm/ksm/pages_shared
cat /sys/kernel/mm/ksm/pages_sharing

pages_shared is the number of unique physical pages currently being used as the "master copy" for a merge. pages_sharing is how many additional virtual pages are pointing at those shared pages instead of holding their own private copy — this second number is roughly what you've saved. Each page is 4 KB, so if pages_sharing reads 150000, that's about 585 MB of RAM you're not using twice. On a freshly booted node these numbers will be low or zero; give it ten to fifteen minutes with a few similar VMs running and check again.

To disable KSM across the entire node — every VM, all at once:

systemctl disable --now ksmtuned
echo 2 > /sys/kernel/mm/ksm/run

The first command stops the tuning daemon and keeps it from starting on the next boot. The second tells the kernel's KSM thread to unmerge every page it's currently sharing and split them back into private copies. Skip that second line and the pages that are already merged will stay merged even though nothing new gets scanned going forward.

To bring it back:

systemctl enable --now ksmtuned

If you only want to exempt one VM — say, a database VM where you'd rather not have its memory pages touched by a background scanner — you can turn it off per guest instead of node-wide:

qm set 105 --allow-ksm 0

Replace 105 with your actual VMID. This flag defaults to enabled on every new VM, and setting it to 0 opts that specific VM's memory out of scanning while everything else on the node keeps sharing normally. You can confirm the change stuck by running qm config 105 and looking for the ksm line.

Finally, if you want to adjust how aggressively KSM scans rather than turning it off entirely, edit its tuning file:

nano /etc/ksmtuned.conf

The two settings you'll actually touch are KSM_MONITOR_INTERVAL, which controls how often (in seconds) ksmtuned re-checks memory pressure and adjusts scanning speed, and KSM_THRES_COEF, which sets the free-memory threshold (as a percentage) below which ksmtuned ramps scanning up. Both ship with sane defaults, and honestly, most homelab users never need to touch this file at all. Save your changes and restart the daemon for them to take effect:

systemctl restart ksmtuned

Commands Explained

CommandWhat it does
systemctl status ksmtunedShows whether the KSM tuning daemon is currently active on this node.
cat /sys/kernel/mm/ksm/pages_sharingReads the live count of memory pages currently deduplicated by KSM.
systemctl disable --now ksmtunedStops the daemon immediately and prevents it from starting again at boot.
echo 2 > /sys/kernel/mm/ksm/runTells the kernel to unmerge all currently shared pages and split them back into private copies.
qm set <vmid> --allow-ksm 0Excludes a single VM's memory from KSM scanning without affecting other guests.
qm config <vmid>Prints a VM's current configuration, useful for confirming the ksm setting took effect.
systemctl restart ksmtunedReloads /etc/ksmtuned.conf after you've edited the tuning thresholds.

Common Errors

"Unit ksmtuned.service could not be found." This usually means you're on a minimal or non-standard install where the package didn't get pulled in. Check with dpkg -l | grep ksmtuned first — if it's genuinely missing, something unusual happened during setup, and reinstalling the base Proxmox packages is a safer fix than trying to hand-install just the one daemon.

qm set: unable to parse value of 'ksm' — you'll hit this if you pass anything other than 0 or 1 to --allow-ksm. It's a boolean flag, not a percentage or a scanning rate.

Permission denied writing to /sys/kernel/mm/ksm/run means you're not running the command as root. Proxmox shells default to root, but if you've SSH'd in as a regular user with sudo, remember that a plain sudo echo 2 > /sys/... won't actually work the way you'd expect — the redirect happens in your unprivileged shell, not sudo's. Use echo 2 | sudo tee /sys/kernel/mm/ksm/run instead.

Troubleshooting

pages_sharing stays at zero no matter how long you wait. This almost always means your VMs don't actually have much in common at the memory level — different OSes, different kernel versions, or VMs that are mostly running unique application data rather than shared library pages. It's not broken; there's simply nothing to merge. It can also happen if every VM you're running has --allow-ksm 0 set individually, so double-check with qm config on each one.

Host CPU usage climbs after you enable KSM on a busy node. The scanning itself costs CPU time, and ksmtuned will scan more aggressively the more memory pressure it detects. If a node is already CPU-bound rather than memory-bound, KSM can end up costing you more in scan overhead than it saves in RAM. This is one of the cases where turning it off — either for the whole node or just for your heaviest VMs — is the right call, not a workaround for something broken.

You disabled KSM but memory usage didn't drop. Stopping ksmtuned alone doesn't unmerge existing pages — it just stops scanning for new ones. You need the echo 2 > /sys/kernel/mm/ksm/run step too, and even then, give the kernel a minute to actually split the pages back apart before you check free -h again.

Best Practices

Leave KSM on for homelabs and single-tenant clusters where every VM is yours. There's no real downside, and the RAM savings on a node running several similar Linux VMs are genuinely worth having.

Turn it off — node-wide or per-VM — for anything that's memory-latency sensitive, like a production database VM, or anything where predictable performance matters more than saving a few hundred megabytes. I'd also skip it on any host where VMs belong to different people or organizations; the side-channel risk isn't theoretical, and it's not worth the tradeoff for the amount of RAM you'll typically reclaim.

Don't bother hand-tuning ksmtuned.conf unless you've actually measured a problem. The defaults are conservative on purpose, and cranking KSM_THRES_COEF up to scan more aggressively mostly just burns CPU cycles for marginal extra savings.

Check pages_sharing periodically rather than assuming it's working. It's easy to enable something once, forget about it, and never actually confirm it's doing anything on your specific workload.

Frequently Asked Questions

Does KSM work with LXC containers, or only VMs?

KSM operates at the kernel memory level on the host, so it can merge pages regardless of whether they belong to a QEMU VM or an LXC container. That said, unprivileged LXC containers already share the host kernel and many pages by nature, so the practical savings from KSM are usually smaller there than across full VMs running separate guest kernels.

Will KSM slow down my VMs?

Not noticeably for most homelab workloads. The scanning thread runs at a low priority and the copy-on-write split, when it happens, is a single page fault — fast enough that you won't feel it in normal use. The one place you might notice anything is on a host that's already CPU-constrained.

Is KSM the same thing as memory ballooning?

No, and it's a common mix-up. Ballooning changes how much memory a guest is allowed to hold by actually reclaiming pages from it. KSM runs on the host and deduplicates identical pages across different VMs without changing what any single VM thinks it has. They solve different problems and work fine together.

How much RAM will I actually save?

It depends entirely on how similar your VMs are. A handful of freshly installed VMs running the same distro can show savings in the hundreds of megabytes to low gigabytes. A node with one VM of each OS you can think of won't show much at all.

Can I re-enable KSM after disabling it without rebooting?

Yes. systemctl enable --now ksmtuned starts it back up immediately, no reboot required.

Conclusion

KSM is one of those features that does its job quietly enough that most Proxmox users never think about it until they read something like this. For a typical homelab running a stack of similar VMs, there's rarely a reason to touch it — it's already reclaiming RAM you'd otherwise be wasting on duplicate library pages. The two things worth remembering are the per-VM override for anything latency-sensitive, and the security tradeoff if you're ever hosting VMs that aren't all yours. Outside of those two cases, the best move is usually just to leave it running and check in on pages_sharing every once in a while to see it actually doing something.