I can "unbloat" Systemd?

Hello guys. Since NixOS is locked into Systemd, at least I can “unbloat“ Systemd? What features I can disable to save CPU and RAM usage? (Storage also, but I don’t care so much, priority is the first two.) And how to know if I can disable something without break things? Also apply this to glibc if possible, but it isn’t so much problem, more Systemd.

Guix is a great alternative there, but really I don’t want leave NixOS, if I can’t dispense with Systemd and glib, at least I could try to suppress they. Is a shame there isn’t functional and declarative NixOS/Guix like distros with the systemd-free and musl lightweight set. If you need an idea to create a Linux distro, there’s one.

I like Guix well enough myself but The Shepherd is not a lightweight beast. In a head-to-head comparison (same hardware, same set of services) I expect it will require at least twice as much RAM as systemd.

Rather than worrying about either systemd or glibc, I recommend running a monolithic kernel tailored to your hardware; the stock NixOS kernel is 12MB on disk without the modules, a tailored monolith usually weighs in at 6MB or less.

I’m not looking for custom a kernel for my actual hardware, I’ll wait to have better one for that. I’m focusing into systemd bloat I could disable for now.

My point is that there really isn’t that much and you would be better off looking elsewhere for savings.

The only piece of software shipped by the systemd project that I personally consider unfit for purpose is systemd-timesyncd. Swapping that out for an NTP client maintained by people who take the challenges of time synchronization seriously is as simple as

  services.timesyncd.enable = false;
  services.chrony.enable = true;

  # work around https://github.com/NixOS/nixpkgs/issues/445035
  systemd.tmpfiles.rules = lib.mkAfter [
    "z ${config.services.chrony.directory}/chrony.keys 0640 root chrony - -"
  ];

I do not know whether this is a net win or lose on memory consumption.

Because of https://www.openwall.com/lists/oss-security/2025/12/28/4 I also strongly recommend

  systemd.generators.systemd-ssh-generator = "/dev/null";
  systemd.sockets.sshd-unix-local.enable = lib.mkForce false;
  systemd.sockets.sshd-vsock.enable = lib.mkForce false;

on any system that has sshd enabled, but again, this is not because of memory costs.

6 Likes

Sounds like there’s a story here…what’s the deal?

For the record, the whole thing about “bloat” is a misunderstanding of the arguments about “unix philosophy” - which has no impact on system resource use, but is purely a disagreement about architecture design. These arguments in turn largely stem from a deliberate misrepresentation of how systemd works, and are in practice mostly invalid, so you’re basing your perception of “bloat” on a misunderstanding of a falsehood, rather than anything practical.

NixOS has chosen to use the systemd family of projects for various purposes. There are indeed some where you can choose non-systemd-associated alternatives (e.g. systemd-timesyncd or systemd-networkd), but just choosing an alternative doesn’t have a straightforward impact on resource use as @zwol says; In fact, often services from the systemd family are designed to replace old, and therefore often significantly more “bloated” for historic reasons, services.

Even if there were anything to this “bloat”, on any system that has a browser of any kind installed any realistic savings are so many orders of magnitude removed from opening a website that they are utterly pointless. Unless you’re designing an integrated system with memory in the order of 10s of MB, there’s never a reason to think about this.

You’ll be much better off looking at other places, e.g. ridding yourself of electron, tuning the kernel, etc. You’ll probably find it’s quite difficult to find any objective “bloat” besides unused kernel modules (which only affect disk space), though.

If you really want to experiment with designing for integrated systems, toy around with e.g. liminix in a VM.

22 Likes

To drive this point home, a default nixos system has only five systemd processes running out of the box: PID 1, journald, udevd, oomd, and logind. Collectively, these consume 117K of resident memory (132K virtual) after bootup in my test case. You are not removing bloat by getting rid of these things (not that you realistically could with any of those other than oomd).

12 Likes

I am curious what your gripes with timesyncd are. I have not had issues in my basic usage of it.

1 Like

The chrony docs have an FAQ entry for this. systemd-timesyncd doesn’t implement the full multi-clock sync and various complex algorithms that NTP demands. Opinions on whether this is a problem differ.

Ironically, this is exactly one of those cases where the systemd implementation is going to use marginally fewer system resources, so switching to chrony is the opposite of removing “bloat”; though as @zwol says, this means you’re more likely to run into clock drift (which can have significant security implications).

7 Likes

Well, I can settle with systemd for now. Actually what makes me uncomfortable is the fact there’re lightweight alternatives but I can’t use they, so that implies switch of distro, and I don’t want it, systemd is the only thing I don’t like of NixOS. Is true I’m ignoring why systemd is heavier and how works. I should start from there also.

Opinions are appreciated anyways.

For me systemd “bloat” consists of the number of bundled programs of dubious utility and quality. For example:

  • systemd-hostnamed: I can’t think of any good reason for wanting to change hostname dynamically,

  • systemd-resolved: I leave DNSSEC et al to my recursive resolver,

  • systemd-coredump: I don’t want to store useless coredumps (binaries never include debug symbols by default),

  • systemd-oomd: I just press the magic sysrq key if the OOM killer takes too long,

  • systemd-udev-settle: this should just be killed with fire, thankfully it’s deprecated.

Thankfully with NixOS you can easily disable these with a couple of lines, so it’s fine by me.

If by “bloat” we mean binary size, RAM usage, performances etc. then NixOS is quite hopeless unless you can spend hours building customised packages. Software in Nixpkgs is generally built with dozens of optional plugins/flags by default (just look at ffmpeg) and not optimized for a specific architecture.

6 Likes

That’s helps, I’ll take a look for them. Thanks.

I don’t understand much of what’s being discussed here but maybe you’ll find this relevant for you:

2 Likes

It has been my experience that timesyncd cannot maintain an accurate clock when its source of time is a public NTP pool, because …

… of the limitations described in this FAQ entry. (Thanks for digging that up, @TLATER; I was going to post the same link myself.) Specifically, when you’re using a public NTP pool you really need the feature of continually polling several servers and comparing their idea of the current time, which timesyncd doesn’t do at all; it will select a server to follow and then keep following it indefinitely, even if it’s drifted away from the pool’s consensus time by hours.

chrony also takes over the job of disciplining the RTC, which is handy when you’re using ephemeral / as it means you don’t need to worry about /etc/adjtime at all.

6 Likes

Honestly, I wonder why NixOS defaults to systemd-timesyncd. Maybe chrony wasn’t as mature when the decision was made? Anyway, probably something to discuss elsewhere.

3 Likes

I found myself in a similar dilemma, where i really loved NixOS and its way of doing things, but prior to using NixOS i had been using Void Linux and i ended up really liking Runit as an init system. I couldn’t really make up my mind between the two distributions, so what i ended up doing is making a compromise, by using Void as a base system, and installing as much as possible on top of it with nix + home manager. I symlink the nix drivers to /run/, which is a much better solution than nixGL in my opinion, and this way i also run all my graphical applications and wayland compositors through nix, and i can mix and match it with applications installed through the host distro without issue. This isn’t perfect of course, since there are simply things that have to run at the system level, so you can’t install everything declaratively with nix unless you stick with full NixOS, but this has been a fair compromise for me so far and i’m enjoying this setup.

3 Likes

Share those symlinks you’re using, I’m curious to know what they are.

It involves replicating the way NixOS handles the graphics drivers first. I can’t take credit for it because i got the idea from a github issue thread where someone was doing the same thing. This is my home manager module. Then i symlink it to /run/ with my rc.local, which is here for reference. This works better than nixGL because if you run a program with nixGL, like a terminal emulator or window manager, applications that are started inside that terminal inherit the nixGL stuff, which breaks native host distro applications that need your host drivers. This method solves that issue. There is also this project that automates it for you, but it relies on systemd so it won’t work on distros without it.

1 Like

Beautiful, thanks for that and I’ll be reading for inspiration.

I really like to do something like that with Alpine. But as you say isn’t clean and perfect. A reproducible system definition with musl and not systemd is a considerable option. Doesn’t matters if isn’t functional like Nix.

2 Likes