My first home server was a 4 GB Raspberry Pi 4 on a shelf above my desk. It ran Pi-hole, Home Assistant, Vaultwarden, and a small Jellyfin library for about eighteen months without complaint. Then I installed Immich to get my phone photos off Google, kicked off the initial import of about 30,000 pictures, and went to bed.
In the morning, Pi-hole was down, which meant DNS was down, which meant the whole house thought the internet was broken. Home Assistant had restarted twice overnight. The Pi was still technically on, but it was so deep in swap on the SD card that SSH took almost a minute to give me a prompt. The Linux out-of-memory killer had been working through my containers like a nightclub bouncer at closing time.
I moved everything to a used mini PC with 16 GB a few weeks later. Then, a month after that, I logged in, ran free -h, saw “used: 14 GB,” and nearly ordered another 16 GB stick. That second panic was the more useful lesson, and I’ll get to it. First, the question in the title.
The short answer
For most people starting a home server in 2026:
- 4 GB handles a handful of light services: DNS filtering, a password manager, a small Home Assistant, a file sync tool. Nothing heavy, no databases doing real work.
- 8 GB is the comfortable floor for a general Docker box running ten to fifteen typical self-hosted apps, including one or two with a database.
- 16 GB is where you stop thinking about it for a mixed stack that includes a photo library with machine learning, a media server, Nextcloud or Paperless, and the usual small stuff.
- 32 GB and up is for virtual machines, ZFS with a large pool, several heavy databases, or local AI models.
That’s the answer most forum threads give. But it’s not very useful on its own, because “typical self-hosted apps” range from 30 MB to 4 GB each. The better approach is to add up what you actually plan to run, then read your own server’s numbers correctly. That second part is where almost everyone goes wrong.

What common services actually use
These are rough numbers from my own boxes and a few friends’ setups, measured as steady-state memory after a day or two of normal use. Your mileage will vary with library size, user count, and configuration, but they’re in the right ballpark.
Tiny (under 200 MB each): Pi-hole or AdGuard Home, Vaultwarden, Uptime Kuma, Syncthing, a reverse proxy like Caddy or Traefik, ntfy, Homepage-style dashboards. You can stack a dozen of these on a 4 GB machine and barely notice.
Medium (300 MB to 1 GB each): Home Assistant, which grows with the number of integrations and how much history you keep. Jellyfin or Plex at idle. Gitea or Forgejo. A Postgres or MariaDB instance backing one app. Most of these sit comfortably in the lower half of the range and spike during specific jobs.
Heavy (1 GB and up, with spikes):
- Immich, especially its machine learning container, which loads face-recognition and search models into memory. Steady state can be modest, but during an initial import it can happily take several gigabytes. This is what killed my Pi.
- Nextcloud with its database, Redis, and background jobs. Around 1 GB is common for a small household, more with lots of apps enabled.
- Paperless-ngx, mostly during OCR. Idle is fine; processing a stack of scanned PDFs is not.
- Jellyfin or Plex while transcoding, particularly software transcoding or generating thumbnails for a large library.
- Anything Java-based, like some game servers or search tools, which often grab a fixed heap up front.
Two hidden costs catch people out. First, every app that ships its own database runs its own copy of that database. If Immich, Nextcloud, Paperless, and Gitea each bring a Postgres container, that’s four Postgres instances, each with its own caches. Second, the spikes matter more than the averages. You don’t run out of memory on a normal Tuesday. You run out when three background jobs happen to line up at 3 a.m.
Reading your server’s memory without panicking
Here’s the second lesson. When I ran free -h on the new 16 GB mini PC and saw 14 GB “used,” I assumed I was nearly out. I wasn’t even close.
Linux uses spare RAM as a disk cache. Every file your containers read, including media files, database pages, and container images, gets kept in memory in case it’s needed again. That’s good: unused RAM is wasted RAM. When an application needs more memory, the kernel drops cache instantly to make room. But some tools count that cache as “used,” and the number looks scary.
The column that matters is available, not used or free. On my mini PC, free -h said about 14 GB used, 400 MB free, and over 10 GB available. The containers were actually using around 5 GB. The rest was cache that would vanish the moment anything asked for it.
For per-container numbers, docker stats gives a live view. It’s a snapshot, so run it a few times across a day, including during backups or scheduled jobs. If you want history, a lightweight monitoring stack like Netdata or Beszel will graph memory over time, which is the only way to catch those 3 a.m. spikes.
The real warning signs are different from a big “used” number:
- “Available” drops close to zero during normal use.
- Swap usage keeps climbing and doesn’t come back down.
- OOM killer messages in
dmesgorjournalctl -k, or containers restarting with exit code 137. - Everything becomes sluggish, especially SSH and web interfaces, while the CPU isn’t busy.
If none of those are happening, you have enough RAM, whatever the “used” number says.

The things that eat RAM you didn’t budget for
ZFS
If you use ZFS, whether through TrueNAS, Proxmox, or plain Linux, it keeps its own cache called the ARC. On Linux, by default, it’s allowed to grow up to half of your RAM. Like the page cache, it shrinks under pressure, but not always as gracefully, and some monitoring tools show it as used memory. On a 16 GB box, it’s normal to see 8 GB going to ARC. You can cap it if your containers need the room.
The old “1 GB of RAM per terabyte of storage” rule for ZFS is mostly folklore for home use. It applied to deduplication, which you almost certainly shouldn’t turn on. A home NAS with 20 TB runs fine on 16 GB.
Virtual machines
Containers share the host’s memory and only use what they need. Virtual machines are different: when you give a VM 4 GB in Proxmox, it generally reserves close to that amount whether it’s using it or not. Three VMs with 4 GB each on a 16 GB host leaves you with very little. If you want to run VMs, budget for their full allocations plus the host, and look at 32 GB.
Local AI
Running a language model locally is its own category entirely. The model’s weights have to fit in memory, and even small useful models need several gigabytes before they answer a single question. If that’s on your list, size it separately from the rest of the stack rather than hoping it’ll squeeze in; how much RAM a local LLM actually needs is a different calculation from the one in this article.
Swap, zram, and memory limits
A little swap is a good safety net. It gives the kernel somewhere to put rarely touched memory, and it turns a sudden crash into a slow-down you can notice. On an SSD or NVMe drive, a few gigabytes of swap is fine. On an SD card, like my old Pi, heavy swapping is both painfully slow and hard on the card. On small boards, zram, which is compressed swap stored in RAM, is usually a better choice.
The single most useful thing I did after the Pi incident was add memory limits to the heavy containers. In Docker Compose, a mem_limit on a service caps how much it can use. When Immich’s machine learning container hits its limit during an import, only that container gets killed and restarted. Pi-hole, Home Assistant, and everything else keep running. Without limits, the kernel’s OOM killer picks whichever process looks biggest, and that’s often a database you really didn’t want interrupted.
I set limits on anything in the heavy list above and leave the tiny services alone. It took twenty minutes and it’s the reason my DNS hasn’t gone down since.
How I’d size a new box
If I were buying today, here’s the process I’d follow:
- List every service you plan to run in the next year, not just today. Be honest about the photo library and the media server.
- Put each one in the tiny, medium, or heavy bucket and add up rough numbers. Count every bundled database separately.
- Add at least 2 GB for the operating system and cache, more if you use ZFS.
- Add the full allocation of any VMs.
- Multiply by about 1.5 for spikes and future additions.
- Round up to the next common size, and prefer a machine with socketed RAM so you can upgrade instead of replacing.
For my current stack, which is fifteen or so containers including Immich, Jellyfin, Home Assistant, Nextcloud, and Paperless, that math lands at about 11 GB. I run 16 GB, and “available” hasn’t dropped below 6 GB in months, even during imports.
The Pi still exists, by the way. It runs a second Pi-hole and nothing else, using about 300 MB of its 4 GB. It’s the most reliable machine in the house. Enough RAM isn’t about having the most. It’s about knowing what each thing needs and making sure the important ones don’t lose a fight to the greedy ones.