Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I've recently started experimenting with NixOS on my secondary (testbed) laptop at home. (My main home laptop has Windows, while at work we use Ubuntu.) Based on that and posts on this thread, I'd say if you're willing to consider Arch, I'd seriously suggest it might be worth adding NixOS to your list too. In my experience, at some cost, it gives you one particular super-power, that I've never seen anywhere yet. Specifically, breaking down cons vs pros:

- ~CON: It's not as polished experience as Ubuntu on "first install", i.e. "end user first" or "Windows-like". But based on other comments here, I assume if you're willing to try Arch, you agree for some tweaking. Please note I've never used Arch, so I can't more precisely compare the level of tweak-ness required; what I can say for sure that it's certainly easier than what was required in '90s (at least because we have teh internets now; and esp. the ArchWiki + askubuntu...) But again, I started my post with "if you're willing to consider Arch", so in such case I assume this point is a non-really-CON, as you're already agreeing to take this cost.

- CON: you have to learn a new language (Nix). To sweeten the deal, IIUC it's one of the few truly purely functional languages around. No IO monads or whatsit. As a result, you may (um; will have to...) learn some interesting functional tricks you never imagined may exist. Note also, that some advanced usage ideas are spread over a few blogs (see esp. the "Nix pills" series), and also in inline comments in the Nix standard library source code.

- SUPER-PRO: I found out that NixOS is a hacker's dream OS. Nix's core idea is that removing a package from your OS nukes it clean, leaving absolutely no trace it ever existed. As a result, you practically don't fear any changes in even most sophisticated internals of the OS. Want to change a kernel compilation flag? Meh, let's just try this one, bam, compile, reboot! Oh, it hanged during boot? Pfff, reboot again, select previous version in GRUB, and we're back! [Um; I mean, as long as you haven't burnt your hardware ;) you know, Linux is powerful :)] Also, part of this is in the fact, that all of your OS config is described in a single file, so you can control everything from single central position, and VCS it trivially.

I've already sent a couple PRs based on this ease of hacking and tweaking, namely to neovim and systemd-bootchart. I'm also trying to write my own series of blogposts documenting this (while it's still fresh in memory); but, eh, you know, a bit too many side projects... not to mention even some of this weird "real life" thing people are talking about so often...



NixOS gets my vote too. I started on Gentoo back in 04, played with Arch for a year or so, then went to Nix a few years ago. I have never had so much love for an operating system.

The Nix language is cute, very powerful, and as you say, is capable of cool tricks. I personally find it very easy to read too.

For every project I work on, I define a .nix file describing its build environment. It is then just a matter of cloning the repo, typing nix-shell, and then all build dependencies will be downloaded and I'm ready to go. These nix files also specify which emacs I want to use and with which modes: I don't use Emacs' package manager.

I use nix-shell for pretty much everything. My basic environment contains only core utilities. I launch firefox with "nix-shell -p firefox --run firefox" (bound to a shortcut defined in my xmonad config).

Nix is easy to customize. The override infrastructure makes it easy to modify package definitions from your user config file, and I find I am much happier doing this in a programming language rather than a bespoke config file format.

Other pros: you don't need to be root to install stuff. And there isn't much more satisfying than getting a new laptop, git cloning the repo containing your intended system configuration, and being back up with your old OS with one or two commands.

As you say, if Arch turns you off, Nix may horrify. Despite the vote, I'm pretty discriminating about who I recommend it to.


Hm, I didn't intend to convey a message that "Nix is more horrifying than Arch". For me, it's actually the other way round. Never tried Arch; but at some point in the past tried Gentoo for a few seconds, as well as Slackware; compared to those, in NixOS I just feel this huge safety net, with which however* deep I'll dig, I won't be punished for that. And truth said, even in Ubuntu I have to hack the OS occasionally, so in some way NixOS feels safer than Ubuntu.

* -- again, standard disclaimer, any Linux distro can kill your puppy, eat your homework, and burn your laptop; but that's true even of Ubuntu :)

Not sure how to rephrase the original post to better express what I mean. That said, after reading your reply, I agree that I find it hard to push on NixOS to even fellow "regular" devs; I don't have balls yet to install it as my main OS either. Maybe it's that NixOS has somewhat harder initial curve than "your common Linux"; the install phase reminded me somewhat of Slackware of '90s for a sec (though it's still better); again, not sure how it compares to Arch; plus there's the new language (Nix). That said, personally I wouldn't even think about using Arch, knowing how even tweaking Ubuntu is risky. And exactly as you said, I found Nix (the language) truly cute quite quickly. Totally much simpler than Haskell (which I still can't break into, even after some initial successes with SML, OCaml, and growing interest in Idris, which is reportedly Haskell-inspired).


> It's one of the few truly purely functional languages around. No IO monads or whatsit.

The IO monad, as in Haskell, can be viewed as an entirely pure construct. Its implementation is impure purely because of performance reasons. You can write your own completely pure IO type if you want, with unchanged semantics.

A basic example of this would be

    data IOF r = PutStrLn String r
               | GetLine (String -> r) deriving Functor

    type IO = Free IOF

    putStrLn s = liftF (PutStrLn s ())
    getLine = liftF (GetLine id)

    main :: IO ()
    main = do
      putStrLn "Enter your age"
      age <- read <$> getLine
      if age >= 18
      then putStrLn "You can vote!"
      else putStrLn $ unwords ["You can vote in", show (18-age), "years"]
Of course, now you need a way to interpret your IO type in order to make the machine actually do stuff. This can be achieved in two ways: You can modify the GHC RTS to allow it to interpret your IO type, or you can define an interpreter in Haskell to convert it to the IO type that the GHC RTS knows how to interpret

    interpret :: IO a -> Prelude.IO a
    interpret (Free (PutStrLn s r)) = Prelude.putStrLn s >> interpret r
    interpret (Free (GetLine s)) = Prelude.getLine >>= interpret . s


Even though it’s very much out of context for this thread, it’s a little pearl that brought me again a little bit closer to understanding. Thanks!


I believe the parent meant to say "no IO", although my knowledge of Nix is limited.


NixOS has my vote.

On the first ~CON: If the "end user" is a developer that is new to nix and nix expressions, the transparency of nixpkgs and its nix expressions may turn tweaking from a problem into an opportunity. Seeing the details of builds, configs, and installs clearly laid out in a nix expression taught me more about the package that I was blindly depending on. Having the same tools (nix, nix-repl, nix-shell, *.nix) available across projects and vertically within developments has reduced the "special knowledge" that "end users" need to know for both development and operations.

Extra PRO: Have the expression for your configuration just perfect? Need to build on multiple VMs, machines, EC2? Simply add an expression for networking and deploy with Nixops https://nixos.org/nixops/. Now logical and physical configuration is a declarative data file. If a build fails, I check the source. If my cloud fails, I check the source.

For me, the reproducibility and variable independence in NixOS puts the SCIENCE in Computer Science.


> Have the expression for your configuration just perfect? Need to build on multiple VMs, machines, EC2?

+1. Dependency management and deployment is the biggest problem Nix solves and it is the only system that actually does so instead of putting the problem somewhere else and presenting that as a "solution." A lot of people are using Docker for this scenario, which gives the illusion of a solution for new projects because you have convenient pre-built images. The images do not come from thin air, and people will run into exactly the same problems as they did with VM images once their Docker projects age and dependencies will need to be updated. Adding virtualization layers cannot solve the problem of updating software dependencies.

The only solution is a package manager that tracks the complete dependency tree, all the linked libraries down to libc, and prevents different versions of packages from interfering with each other. Nix is the only package manager that does this.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: