I run dnstools.ws which lets you perform DNS lookups, pings, traceroutes, etc. from 25 locations around the world. Each location is powered by a VPS running Debian, running a C# service that’s compiled to native code ahead-of-time using Native AOT. It uses ~60MB RAM.
Six of the the locations are powered by tiny “NAT VPSes” (native IPv6 with shared NAT IPv4) that only cost a few dollars a year, sponsored by various server providers. These usually have 256 MB RAM and 4-5 GB disk space.
This is great with OpenVZ and LXC. Since they’re containers that share the kernel with the host, kernel memory doesn’t count towards the container’s memory limit. I’m using ~75 MB RAM on those systems: ~60MB for the DNSTools worker and ~15MB for everything else (sshd, systemd, cron, rsyslogd, and unattended-upgrades). Plenty of room left.
I also have a few KVM systems with 256 MB RAM. These are what I’m struggling with.
Debian 13 (Trixie) increased the minimum hardware requirements from 256 MB to 512 MB RAM. It seems like this is a hard requirement - When running on a system using 256 MB RAM, the installer complains about having too little RAM, and OOMs during the installation. Even with a successful installation (e.g. upgrading from bookworm to trixie), it kernel panics on boot: “System is deadlocked on memory”.
I could try debootstrap to bootstrap a basic system, or Clonezilla to clone a working disk image over the network, but I think I’d hit the memory deadlock too.
Does Debian have smaller kernel images for VM environments, that use less RAM? Or should I just give up on Debian for this use case?
Does anyone have a recommendation for another distro I should use? I’ve been considering trying Alpine. C# does support compiling to use musl instead of glibc, so that’s not an issue. I’m also not tightly-coupled to systemd and can get rid of it.
I can mount a custom ISO on the systems, so booting from an ISO isn’t an issue.
Thanks!
Edit: Alpine looks very promising - no issue installing it and running my app on a 256MB VM. This is probably what I’ll end up using.
Alpine in container is typically considered the smallest one can conveniently use (not going through LinuxFromScratch or writing your own OS). I did some tinkering a while back ending up with 14.29MiB memory footprint.
In my case it needs to be a VM rather than a container (because that’s what the hosting company offers), but Alpine is looking promising so far. No issues with booting from the ISO and installing it on a system with 256MB.
I got my app running on Alpine too. Now I just need to update my Ansible playbook to handle Alpine, and do more thorough testing. Will look into it later in the week.
tui installer on netinst iso (13.4) says 320mb is required:
This system does not have enough memory to be supported by this program. At least 320 megabytes of memory are required. If you continue, unpredictable and broken behavior will likely result. You should reboot now and add memory or find some other program to use.
it does allow you to continue anyway, which switches to ‘low memory’ expert mode install. 320mb also gives this error. 384mb does not, but still enters the special install mode, where i was able to load enough installer components to set up networking to start an install. it did lose part of the display font partway through but it did finish and reboot ok (with ~104mb used). dropped the ram in virt-man to 256mb and it still booted.

edit: i just installed dietpi on this, which basically shreds debian down to the kernel and not much else, and rebuilds it as dietpi. went on without any issues, not even a complaint with 256mb. htop says 65mb used (this, before adding any server ‘apps’, mind you)… but i might just be able to upgrade a couple dietpi boxes i have that do only have 256mb ram.
Interesting! I wonder why I was hitting the memory deadlock on boot, but yours booted OK.
I might run a local VM, use dietpi, then clone the resulting VM to the hosting provider using Clonezilla.
why I was hitting the memory deadlock on boot, but yours booted OK
i dunno. was your debian-installer running in lowmem mode? did it add extra stuff because of the detected vm environment (i did notice at least one extra thing here for qemu plus the network drivers needed).
this trixie-based dietpi here boots at 192mb allocated to the vm, but panics at 160mb.
the dietpi x64 ‘installer’ iso don’t use the debian-installer. they are clonezilla-based, preconfigured to use an included dietpi image, which does a first-run setup after it’s ‘restored’.
I was using debian-installer in lowmem mode, but it OOMd during the install. I haven’t tried adding swap yet though.
The Trixie system that I did manage to setup was an upgrade from Bookworm. That’s the one that’s hitting the memory deadlock on boot.
maybe see if the providers can bump the ram up a bit to get through the trixie installer? 384mb was enough here (i didn’t try to install with less), perhaps 512mb in your hosts’ environments will be enough.
You can get creative with Linux.
- Install on 512mb, remove and trim system services, and lower the memory. Running KVM is by itself likely not going to let you do that, I suspect.
- Use Alpine as you say.I run many alpine containers on between 25MB and 60MB, I give them 256MB, but it’s way overkill.
Regarding alpine, be prepared to find differences from glibc and systemd distros in places you don’t expect. PHP (god forbid you should need it) is a right mess on alpine. Mongodb will not work on alpine. Stuff like that.
I may take some challenge on this, but the tcpip stack seems faster on alpine than in debian, at least in my use cases.
PHP (god forbid you should need it) is a right mess on alpine. Mongodb will not work on alpine.
Thankfully all I need is my app, Certbot, and a few standard utilities (ping, traceroute, mtr), and my app works fine with musl. Not a complex setup at all.
The entire setup for the worker app is in this Ansible role: https://github.com/Daniel15/dnstools/blob/master/ansible/roles/dnstools-worker/tasks/main.yml
The grub command line options at the beginning of this article might help get your system booted without the memory deadlock, and then you can make further adjustments as needed: https://tierhive.com/blog/tierhive-howto/debian-13-minimal-guide-reduce-ram-to-38mb-and-disk-to-275mb
Alpine is great for exactly this kind of thing, though, and I use it often in embedded environments where resources are at a premium. Just do some good reading up on it beforehand, since can be very different if you’re used to debian and systemd.
Thanks for the link!
I’m trying Alpine locally in a VM with 256MB RAM, and so far so good. I got my app successfully cross-compiled using
musl-gcc, rsync’d it over, and it starts on the VM with no issues. Now I just need to figure out all the stuff around it (like certbot) and do some more thorough testing. I use an Ansible playbook to deploy to the Debian servers, so I’ve got to update it to handle Alpine too.
I wonder how much smaller you could get it by just cross-compiling to WASM and using some of the edge hosts out there
That’s an interesting idea that I didn’t consider. .NET does seem to have some support for WebAssembly.
Many of the current systems were provided by various hosts for free though, which is how I expanded to so many locations. The 256MB RAM systems are only a few dollars per year, so those hosts were happy to provide a few for free.
Yeah I run an application on fly.io and they don’t even bother charging me anything because my WASM app takes so few resources
I mean you could just compile your own kernel from the Debian source build and use the build menu to pull out everything you don’t need to get the memory requirements down. Then bootstrap with your kernel.
The ongoing maintenance for this would be a bit of a pain, since you’d need to recompile every update on a separate machine with enough memory to do so, package it up into a .deb, and distribute and install it everywhere.
I do this on a little raspberry pi cluster and it works, but it’s work.
I’ve considered this, it just might be a pain to keep up to date with kernel updates. I guess I could create an appropriate config and then automate the builds.
I also forgot that Debian has a cloud-specific kernel (
linux-image-cloud-amd64) which excludes a bunch of drivers. I’ll try that out too.The other thing on my list to try is
mmdebstrapwith a basic Debian install, using runit or openrc instead of systemd.
Seems like you could use swap if this is just running out during parts of the install.
Even if I avoid the installer (e.g. by cloning an existing system, or by installing an older version of Debian then upgrading it), and have swap space, the kernel hits a memory deadlock on boot. I suspect it’s deadlocking before swap is initialized.

@dan @RIotingPacifist A “normal” debian starts by unpacking the initrd, which is into ram, so you’d need enough to cover that, plus initial runtime. Most likely you will need to tailor your initrd; i.e. go non-standard.
That’s what I was thinking. I might try the cloud kernel (
linux-image-cloud-amd64). It only has drivers required for VM platforms, so maybe the initramfs might be smaller? Otherwise I could build a custom one with just the things I need (only ext4 and swap, only drivers for KVM, etc).I’m trying Alpine as well, which looks promising.
Tinycore is a 23mb Linux desktop that runs in 46mb of ram. Microcore is the headless version that runs in 28mb of ram.
Does it support a server installation (no GUI)?
Yes, TinyCore-Core comes without a GUI (like the commenter above said, headless). When they say 28 MB RAM, that might even be overestimating it a bit. All of TinyCore-Core fits into just 17 MB. Of course that goes up if you need to install things, and I don’t know if it comes with an ssh-Server out-of-the-box. So for a proper server setup, 28 MB sounds pretty reasonable.
It blows my mind, that there is an entire Linux Distro, that fits into a modern processor’s cache. Who needs RAM anyways? (unfortunately, because of how cache works, we can’t actually use it without RAM)
I’m currently trying Alpine, but I’ll try this out too!
I don’t know enough to help, but I’m commenting in the hopes it reaches someone who does.
Another thought: is it required for your service to physically run in 25 locations? Couldn’t you have one (more powerful) main instance which accesses the other servers via SSH to execute whatever command is required?
The 25 locations are a bare minimum Debian installation with just my app, SSH (for management), Certbot (for TLS certs), and a few other utilities (ping, traceroute, mtr) added. The app uses ~60MB RAM so it’s not an issue.
The site accesses each location using gRPC over a persistent connection.
The code is open-source if you’re curious: https://github.com/Daniel15/dnstools
Those are customized installs to use the most minimal disk and memory footprint possible. You sure they run a MODERN release of Debian?
I’ve installed Debian Buster, Bullseye and Bookworm on these systems from the netinst ISO, with no tweaking needed. Trixie is the first release where I’ve been unable to do this, and even upgrading the system doesn’t work (hits a memory deadlock on boot).
I don’t even know where you can get a VPS with that little memory anymore. I think this is just the nature of the kernel progressing and growing in features and size.
Maybe have a look at something like : https://github.com/trisweb/buildkern
Some are from https://hosting.gullo.me/. They even still offer 128 MB for $3.50/year, or around $2/year during Black Friday :). These are OpenVZ so they’re not an issue though.
Some are from https://natvps.net/ but it looks like they no longer offer them for sale - their lowest is 512MB RAM now.



