HN Theater @HNTheaterMonth

The best talks and videos of Hacker News.

Hacker News Comments on
Purely Functional Linux with NixOS

begriffs.com · 169 HN points · 0 HN comments
HN Theater has aggregated all Hacker News stories and comments that mention begriffs.com's video "Purely Functional Linux with NixOS".
Watch on begriffs.com [↗]
begriffs.com Summary
How it works and how it helps
HN Theater Rankings

Hacker News Stories and Comments

All the comments and stories posted to Hacker News that reference this video.
Aug 08, 2016 · 169 points, 142 comments · submitted by begriffs
qwertyuiop924
Am I the only one who thought Guix did this better? Maybe it's just my freakish and unnatural love of parenthesis. Or my hatred of learning new configuration syntaxes (I just want to install packges, dammit! Yes, I enjoy learning new languages, but I need to get this machine up and running, and I don't want to learn your new programming language to do that)
ambrop7
- I think the issue is partly made moot by that not many people know Guile/Scheme in the first place, so they'd need to learn one language anyway.

- Guix refuses to integrate proprietary software so its usability is diminished compared to Nix (and Guix has less software packaged than Nix in the first place, AFAIK).

- Nix is a pretty good language for the task.

davexunit
>I think the issue is partly made moot by that not many people know Guile/Scheme in the first place, so they'd need to learn one language anyway.

But this language is not a DSL, but a general purpose language that has pattern matchers, HTTP libraries, XML parsers, data structure implementations, etc.

>Guix refuses to integrate proprietary software so its usability is diminished compared to Nix (and Guix has less software packaged than Nix in the first place, AFAIK).

Guix is younger, thus has less software packaged, but the number of new packages introduced with each Guix release continues to increase. I have all the packages most important to me and have been using GuixSD exclusively for at least a year now.

>Nix is a pretty good language for the task.

The problem with any DSL is that is not very extensible and developers must spend time maintaining parsers, compilers, etc. for a one-off language. Guix is achieving its velocity in good part thanks to using an existing general purpose language that new languages can be embedded within.

muraiki
> But this language is not a DSL, but a general purpose language that has pattern matchers, HTTP libraries, XML parsers, data structure implementations, etc.

I'm not expressing this as a criticism that I have, but for some people what you described is not a feature but a bug. :)

rdtsc
I understand that Guix is newer and has less packages so far (but number is growing).

I don't know, I rather like Nix's language, maybe I am just not a Lisp person.

Ericson2314
I greatly respect scheme, and yet I like the nix expression language too. Scheme's claim is you shouldn't be using x more bloated language than it, but the nix expression language is smaller and simpler than Scheme; it beats it at its own game!

More practically, I can't think of anything that I wanted that Scheme offers but the nix expression language doesn't.

qwertyuiop924
>the nix expression language is smaller and simpler than Scheme; it beats it at its own game!

It may have a smaller stdlib than scheme (but I doubt it). But it's very hard to be simpler than scheme semantically.

As for what I want from scheme that nix doesn't provide, a simple, regular, syntax that I already know is what I want. I understand that that doesn't apply to everybody.

Ericson2314
> It may have a smaller stdlib than scheme (but I doubt it). But it's very hard to be simpler than scheme semantically.

Yes, I mean the semantics of the language. Scheme is indisputably more complex. There isn't really much a standard library for the Nix Expression Language either.

> As for what I want from scheme that nix doesn't provide, a simple, regular, syntax that I already know is what I want. I understand that that doesn't apply to everybody.

off the top of my head:

  Scheme-Simplified ::= <Item>*
  Items ::= (define (<Id>*) <Expr>)
         |  (define <Id> <Expr>)
  Expr ::= (<Expr> <Expr>*)
        |  (set! <Id> <Expr>)
        |  (lambda (<Id>*) <Expr>)

  Nix-Expr ::= <Pattern> : <Nix-Expr>
            |  with <Nix-Expr>; <Nix-Expr>
            |  { <Nix-Item>* }
            |  let <Nix-Item>* in <Expr>
            |  <Expr> <ArithOp> <Expr>
            |  <Expr>.<Id>
            |  <Expr>.<String-Lit>
            |  <Expr> ? <Id>
            |  <Expr> ? <Id> or <Nix-Expr>

  Nix-Item ::= <Id> = <Nix-Expr>;
            |  <StringLit> = <Nix-Expr>;
            |  inherit <Expr>;
            |  inherit (<Nix-Expr>) <Nix-Expr>;
qwertyuiop924
Yeah, that scheme syntax looks much simpler. And it is far more regular than Nix's. Of course, scheme is regular enough that the output of the readtables match this:

  Scheme ::= <Expr>*
  Expr ::= <Atom> 
         | (<Expr>*)
  Atom ::= <String>
         | <Symbol>
         | <Number>
And IIRC, that's close to what r5rs requires, although without the '`, syntactic sugar, which a readtable would handle in schemes that have them, and would be added to the above for schemes that don't. I may be wrong, though.

The semantics are also simple:

A function's arguments are evaluated, bound to arguments and passed to it. A special form or macro have their arguments passed to them unevaled. In the case of a macro, the output of the macro is evaled instead. Scope is lexical.

There's about 95% of the semantics right there. The only things I left out, to my knowledge, are dynamic variables, which weren't standardized until recently.

The entire thing may be larger than Nix (I don't think it is), but more regular? I doubt it.

Ericson2314
Note that's a dumbed down scheme, where nothing can be accomplished, I should take a look at the guix APIs to craft a bigger subset. I realized as I wrote it, my argument does look undercut, but didn't want to spend more time just yet, so posted that anyways.

Besides dynamic variables, there is also plain old variable mutation. Scheme macros are much more complex than what you described, because of hygiene. For the sake of making Scheme look better, I left macros out of my grammar. The Nix expression language has none of these things.

> but more regular? I doubt it.

Nix's lack of a top level (the <Items>* in Scheme) is a big boon for simplicity, especially concerning imports from other files which I forgot to include.

qwertyuiop924
>Besides dynamic variables, there is also plain old variable mutation. Scheme macros are much more complex than what you described, because of hygiene. For the sake of making Scheme look better, I left macros out of my grammar. The Nix expression language has none of these things.

Fair enough, but:

>I should take a look at the guix APIs to craft a bigger subset.

What? No.

Those don't add any complexity to the language. You don't add every function to your BNF syntax, do you? This is what I meant about regularity: The sexpr and atoms are the only syntactic elements (except quote and friends, which are syntactic sugar for sexprs).

Most of the things you included in your scheme BNF syntax aren't syntax, they're special forms. Special forms are not syntactically distinct, they are semantically distinct. So while define, if, and lambda are part of the semantics, they aren't part of the syntax.

Macros, too, have no syntactic differentiation: You actually CAN'T add macros to the BNF of the syntax, because there is no syntax to add.

If that's not regular, I don't know what is.

>Nix's lack of a top level (the <Items>* in Scheme) is a big boon for simplicity, especially concerning imports from other files which I forgot to include.

How? What's so complex about having multiple forms at toplevel?

Ericson2314
> What? No. Those don't add any complexity to the language

Oh, believe me, I'm all about the separation between language and library. I mean the smallest subset of Scheme necessary to use the api. For example, it might use string maps instead of association lists.

> Most of the things you included in your scheme BNF syntax aren't syntax, they're special forms.

This is just terminology. We have a hierarchy of languages here:

  1. All terminating Scheme programs are Scheme programs
  2. All Scheme programs are valid s-exprs
  3. All s-exprs are plain text
  4. All plain text is valid bytestring.
  ...
> Macros, too, have no syntactic differentiation: You actually CAN'T add macros to the BNF of the syntax, because there is no syntax to add.

I was doing a grammar for scheme programs, not anything else on that list. Macros invocation requires its own non-terminals because its arguments are arbitrary sexprs, not merely unevaluated expressions.

> How? What's so complex about having multiple forms at toplevel?

Imports. file=expression makes Nix's `import <some-path>` dead simple. Scheme's is necessarily more complicated.

qwertyuiop924
>Oh, believe me, I'm all about the separation between language and library. I mean the smallest subset of Scheme necessary to use the api. For example, it might use string maps instead of association lists.

Look, first off, in a scheme system, there's no reason to use string maps. Symbols or strings can be used for alist lookup, and alists are plenty fast for these purposes.

Secondly, this is how a scheme experession is run, AFAIK.

  (define foo (map odd? '(1 2 3 4)))
First off, in a scheme that has it, the readtable is run, transforming shortcuts like '<expr> into (quote <expr>). Then the expression is parsed into a memory representation of a sexpr. This could be a series of cons cells, but a lot of schemes use something else. What happens next is pretty implementation dependant, but in an interpreter, the resultant expression is evaluated. The evaluator sees the define - note this, in your model, the parser would catch this - dectects that it is a special form, and passes the expr to the code handing define. That code then evaluates the cddr of the expr, and binds the result to the symbol in the cadr. In some implementations, the cadr can be a list, but this isn't standard.

Note that all the parser did was translate some syntactic sugar, and give the interpreter the datastructure representing the sexpr. Because that, AFAIK, is all the parser does.

I could be wrong, but tell me if I am, don't just go on as if I'd said nothing.

>I was doing a grammar for scheme programs, not anything else on that list. Macros invocation requires its own non-terminals because its arguments are arbitrary sexprs, not merely unevaluated expressions.

...An unevaled expression IS an arbitrary sexpr. What else can it be?

corysama
Like everything else with Gnu, the main difference seems to be philosophical. Guix is fundamentally opposed to pre-compiled binaries. Nix has no issue with them.
qwertyuiop924
Which is why, if anything, I'd do what Andy did. (https://wingolog.org/archives/2015/08/04/developing-v8-with-...)
davexunit
>Guix is fundamentally opposed to pre-compiled binaries. Nix has no issue with them.

Using pre-compiled binaries means that builds aren't reproducible, a goal of both Nix and Guix.

rdtsc
Not knowing the practicalities and details of how either one works, and talking in general, I don't see how binaries would make things not-reproducible. One can take a hash of firmware blob just as well as a hash of a source file.
davexunit
"Reproducible builds are a set of software development practices which create a verifiable path from human readable source code to the binary code used by computers."

https://reproducible-builds.org/

tener
How so? You can see the build as a pure function. It consumes a binary blob but it doesn't make it any less deterministic?
davexunit
The build is a source to binary function. How does one reproduce the binary blob? How does one know that binary hasn't been tampered with?
corysama
How does one reproduce a .c file? By copying the file. Either way, you know the bits of both the .c and the .so have not been tampered with because you can verify their hashes. Again, it's a philosophical distinction, not a technical one.
davexunit
It is both a technical and social problem. Please read: https://reproducible-builds.org/
corysama
The title of that project is "Reproducible Builds". But, that is only a step towards their goal of "Verifiable Builds". Thus we end up in this frustrating semantic mismatch between the two of us. Guix demands source-verifiable builds. Nix does not. Both enable reproducible builds equally well.
fizzbatter
Can't trust the source either, if you're worried about it being tampered with right? At some point you have to trust something, likely from a central location.. either a checksum, blob, source, or etc.
qwertyuiop924
Checksums!
davexunit
You're missing the point.
qwertyuiop924
Well, yes, but I read some newer comments, and I get what you mean. I don't necesarily agree with your decision, but I understand it.

  M-x passive-agressive-mode
And now, I'll go upgrade my NVIDIA drivers, and load up Psychonauts on Steam.
tener
And how do you know the source code hasn't been tampered with?

The same way: cryptographic signatures and checksums.

chriswarbo
Yes, using binaries is a different issue to software freedom.

For example, the Haskell toolchain in nixpkgs downloads pre-compiled binaries of old GHC versions (7.0.4 and 7.4.2) which it uses to bootstrap the newer versions.

The binaries are checksummed to ensure reproducibility.

dbcurtis
So, Nix refers to every blob that gets built using an MD5. I should think it would be pretty easy to tell if you have the same binary that somebody else does. And if you can walk a tree of MD5's, you should be able to assert that system A is configured the same as system B.
SwellJoe
That doesn't make sense. A reproducible build means that a build done in two different places results in the same binary. It has nothing to do with whether the vendor distributes binaries (with optional source) or source alone. The binary is what matters. i.g., if I build this package myself, will it result in the exact same binary that I download from the vendor?

Binaries can be signed to prove that the chain of trust is unbroken between the vendor (who maybe you trust enough to run their software on your systems) and you. In the case of a system with reproducible builds, that signature also says, "if you were to build this yourself, you'd end up with the same binary I am sending you."

Edit: I am beginning to realize that when davexunit says "pre-compiled binaries" they are not talking about an OS vendor (like Guix) distributing a binary package (with source available). They are talking about binary blobs provided by third parties, and in a form that is not reproducible, such as an nvidia driver kernel blob. This has led to me assuming davexunit is nuts, but apparently it is just that neither of us has been speaking very clearly to each other, and thus we've seemingly been talking past each other.

davexunit
The intent of reproducible builds, as defined by the reproducible builds project[0], is to have the entire dependency tree built from the complete, corresponding source code of the many projects in that tree, starting from a minimal set of "bootstrap binaries"[1]. Using precompiled binaries, without a doubt, invalidates that goal. Reproducible builds are an ongoing, unsolved problem. In Guix, some things are reproducible, some things aren't, but our goal remains to maximize reproducibility.

[0] https://reproducible-builds.org/

[1] https://www.gnu.org/software/guix/manual/html_node/Bootstrap...

SwellJoe
That's just wrong-headed.

Every binary in the chain can be signed and reproducible (theoretically; we aren't quite there, realistically speaking, and the bootstrap, as you note, is tricky). Forcing every user to build everything from source every time is just a mess, and provides little benefit over signed (reproducible) binaries for the vast majority of users.

It sounds like you (and the guix project) are conflating two orthogonal concepts and making "reproducible builds" into a concept that won't work in widespread use, and maybe even has negative value. We want reproducible builds so that we can be certain that the binary a vendor ships us is built exactly the way they say it was. We don't want it so that everyone is forced to build everything from scratch every time.

Reproducible builds means we can build an identical binary from source to prove that it is what we think it is. It should not mean we must build an identical binary from source every time we install a thing.

davexunit
>Forcing every user to build everything from source every time

>We don't want it so that everyone is forced to build everything from scratch every time.

I believe it is you who is confused. I never suggested this is what reproducible builds are about.

https://www.gnu.org/software/guix/manual/html_node/Substitut...

SwellJoe
I believe several people were confused by your statement. So, at least I'm not alone.

I interpreted your statement of "Using pre-compiled binaries means that builds aren't reproducible, a goal of both Nix and Guix" to mean, "Guix does not distribute pre-compiled binaries, because they can't be reproduced". That still seems an entirely reasonable interpretation of that sentence, to me, as someone with no familiarity with Guix.

But, I now see that your intended meaning was that Guix does not distribute stuff like nvidia blobs, or Flash player, which is a perfectly reasonable choice for them, and nothing less than I would expect of a GNU project (and Fedora, my current favorite desktop distro, has the same policy, so I don't have a problem with it).

corysama
When two programmers argue and both think the other sounds crazy, it's usually because they are saying the same words but meaning different things.

SwellJoe: Go back and substitute "source verifiable" every time davexunit says "reproducible" and everything he says makes sense.

davexunit: Read everyone else's comments from the POV where "reproducible" mean "reliable bitwise replication" without consideration of scientifically reproducible experiments or source verification, and everything they say makes sense.

lfam
> We don't want it so that everyone is forced to build everything from scratch every time.

We don't want this either :) Let's not boil the oceans.

Nix and Guix are both a hybrid of build-from-source and binary package management systems. The package recipes and management tools describe how to build some software from source, and then transparently provide binaries for those recipes when the binary is available from a user-approved provider of the binaries.

But, by providing the full build recipes, all the way down to the bootstrap, users can easily rebuild binaries from source to check that their selected binary provider is honest, or to find reproducibility bugs.

In the case of a package recipe for some software that does not have source code available (a binary "blob"), the recipe would just download the blob from somewhere. We don't package those things in Guix, whereas Nix does. Although, it's not hard to make custom recipes that would do that, if you wanted to.

SwellJoe
Ah! Then guix is not wrong-headed, at all. Carry on then.

I have no problem with Guix being ideologically pure. Only with the notion that you can't have a reproducible build without forcing everyone to build it it themselves, which it seems is not the case with Guix. Cool.

edude03
I'm pretty sure the goal of reproducible builds is to be able to get the same binary as made somewhere from the source code. Arguably binaries are a form of memoizing / caching if you look at compilation as a pure functional problem. For example, if I have build system that says "with file a hash = 1234 and file b with hash = 4321 I should get a binary with hash = 9876 you can save time compelling that package to check its hash by simply asking the binary repo for a package with hash 9876.
sorpaas
What I really worry about is my nonfree wireless driver and Nvidia driver, which doesn't seem to be available on Guix.
Slackwise
Well, you can specify extra packages using $GUIX_PACKAGE_PATH, and I've seen a few custom repos, such as this:

https://github.com/genenetwork/guix-bioinformatics

and

https://github.com/Ecogenomics/ace-guix

I'm not sure how easy it is to maintain a system with extra packages like this, but it'd be nice to be able to use an "overlay" repo as you can in Gentoo for personal/custom packages.

Would love to ping davexunit to see if he can elaborate, because I don't see any specific way to add repositories from the documentation.

davexunit
There's no such thing as a repository in Guix. Using GUIX_PACKAGE_PATH is the closest thing, conceptually.
Slackwise
Ahh, well, then it appears I have to manage a directory of packages myself, as well as any dependencies outside of the Guix store, right? Would be nice to just have a secondary source, as I do with MELPA for Emacs, or overlays for Gentoo.

Is something similar/comparable planned to be added?

Orrr should someone step forward and volunteer to add it as a feature...?

pavlov
When I hear the words "elegant DSL", I reach for my pistol.

(Don't worry, it's just a tiny toy gun.)

qwertyuiop924
Well then, you must hate Guix and Nix equally.
pavlov
Joking, mostly...

Although I do think that programmers often tend to try to solve problems with the kind of tools that they like to make, rather than ones that would be appropriate for the user -- and that's why the *nix open source world has so many incompatible programming languages and configuration formats, and so few good GUIs.

qwertyuiop924
Well, the programming languages are nicer than the guis. It's the incompatable part I can't stand.

Use TOML, JSON, or YAML. If you need something general purpose, use Scheme. It works well embedded.

willtim
IMHO, Nix needs a static type checker far more than it needs parenthesis or syntactic abstraction. The syntax of Nix is a non-issue.
qwertyuiop924
I understand, but guix works well enough, and I don't want to learn another PL just to do package managemnt. Then again, I guess that's why people use nix instead of guix.
dbcurtis
After a quick look at Nix syntax, it seems to me that it is almost JSON but different enough to required all new parsers. Maybe I'm wrong about that. But... why not just use JSON?
davexunit
JSON isn't a programming language.
dbcurtis
True enough. Maybe I've not seen enough of what is in a Nix packaging script.
Ericson2314
Nix is isomorphic to JSON + lambda + let-rec, made lazy.
chriswarbo
You can use `builtins.toJSON` and `builtins.fromJSON` to inter-operate with JSON.

They don't handle functions or infinite datastructures though.

vertex-four
Nix is actually a purely function programming language - you can embed function calls in it. This is used to great effect in various parts of nixpkgs - the entire thing is actually a program which returns the Nix package tree (but is not fully evaluated unless you explicitly ask for it).
dbcurtis
OK, I replace my naive question above with a different naive question: "Why not just use Haskell?"
vertex-four
Haskell is honestly a larger language, and is a pain in the butt to write. If you're just writing configuration or a very simple package, Nix is basically "JSON with colons, multiline strings, and function calls". Haskell doesn't have a reasonable built-in syntax for dictionaries/maps/whatever you want to call them, which is 95% of Nix.
seagreen
Well, you would use records, but records are a weak point of the Haskell language. I've discussed "why not Haskell" with some Nix people and they specifically mentioned the lack of row polymorphism.
codygman
Purescript?
benley
Can I just point out that pretty much all of these options, including guix, are things that were invented well _after_ nix was established as its own thing?

(aside from Haskell and Scheme themselves, of course)

seagreen
I don't think you need to worry, I'm sure that who's familiar with PureScript also knows it's more recent than Nix.

Those PureScript records tho...

willtim
Purescript cannot type a record merge or join. Haskell with type families can, but the syntax would not be very pretty.
vertex-four
You couldn't reasonably create a record for the NixOS configuration - the amount of options (fields) is massive. The all-packages.nix file is an untyped dictionary mapping strings to derivations as well.
qwertyuiop924
A third naïve question: why not just use a functional subset of Scheme? It's got a well-defined syntax for key/value mappings, which is fast enough, funcalls, and you can use lazy evaluation if you use a pure subset of the language.

And in any rnrs complient Scheme, it's fairly trivial to make a strict functional dialect. And in Guile or Racket, it's even easier.

Unfortunately, Guix doesn't do this. Which meant Guix can't guarantee referential transparency. Although if the packager is an ANY WAY competant, it will be maintained.

vertex-four
A purely functional subset of Scheme, honestly, is different enough from most lisps that it's a new language on its own. If you're learning a new language, a new syntax isn't very hard. And there's not a terrible amount of people who think S-expressions are an inherently good syntax.
qwertyuiop924
>A purely functional subset of Scheme, honestly, is different enough from most lisps that it's a new language on its own.

No, it's not. It's a cut-down Scheme: Most of your scheme knowledge would apply directly, or indirectly.

Besides, even if it was a different language, it's a pre-existing one: DSSSL is pretty much this.

>If you're learning a new language, a new syntax isn't very hard.

Yes, but for me, the choice is learning a new language that has no other applications, save package managment, and using a subset of a language I already know.

>And there's not a terrible amount of people who think S-expressions are an inherently good syntax

I said from my perspective. I'm a schemer, so I'm already on board with sexprs.

vertex-four
> No, it's not. It's a cut-down Scheme: Most of your scheme knowledge would apply directly, or indirectly.

Only if you regularly write code using purely functional scheme in the first place. The difficulty of writing in a new language is very rarely figuring out what function calls to make, at least for me - it's about thinking in terms of the language.

qwertyuiop924
Do you know what % of scheme is fairly functional? Most of it. There are ~19 functions in r5rs that mutate state, if you count IO related functions. I have used maybe half of them, and mostly the IO ones. The rest were for mutating variables, lists, vectors, and strings. Many of those are rarely used. I mean, really, when was the last time you used set-car! or set-string!?
willtim
Scheme has little to offer out-of-the-box as a basis for Nix. It has no convenient syntax or suitable implementation for extensible records, which is the core data type of Nix.
qwertyuiop924

  '((extensible-records . being-key-value-maps?))
Alists are fast enough for this, and they ARE k/v maps. And support for them is in rnrs.
vertex-four
They kind of suck syntax-wise though. There's no visual difference between them and any other list.
qwertyuiop924

  '(this is a list)
  '((this . is) (an . alist))
Looks pretty distinct to me.
vertex-four

    '((this . is) (a . list) (of . cons))
    '((this . is) (an . alist))
Hey look, my list of cons looks incredibly like an alist... funny that.
qwertyuiop924
So an alist looks like an alist. I'm shocked.

and alist is a list of pairs. That's what it is. Semantically, there isn't really another reason to use the format.

k__
I think NixOS is the future, but there needs to be more time put into UX.

Distros like Ubuntu are still much easier to get running and this scares many people away :/

zzzcpan
And it's unusable on small VMs, it takes like almost a gig of ram to install something and lots of time to figure out how to edit some config if it doesn't have an option for your needs. So, yeah, if they want users - they need to work on that.
SwellJoe
That's interesting, and not something I'd noticed (I have a 2GB NixOS VM for tinkering with it). That makes NixOS far less attractive for the things I was think it would be a natural for: containers. Because containers need to be reproducible, and because the current crop of container management and deployment tools are really messy, NixOS seems like a natural fit for building containers (maybe for hosting them, too, eventually).

But, if it's not possible to custom build tiny containers on demand without needing a ton of memory, the power of it becomes less fun. I'm visualizing a system whereby you spin up custom environments based on need (with exactly and only the packages and config you need for the specific task, at hand), on demand, in a distributed environment. That'd be harder if the resources to spin up are very high.

apt and yum both can consume a lot of memory when installing large lists of packages, but 1GB is pretty far out, and you can work around it by installing a small number of packages at a time. Which slows it down, but allows installation to work on even very small systems (like 128MB, or even smaller, if you've got a little swap).

Ericson2314
https://github.com/cleverca22/not-os is an experiment for a "pre-fab nixos"--i.e. a stateless images that do not themselves contain nix. I'd like to see this sort of functionality implemented in NixOS proper.
chriswarbo
> NixOS seems like a natural fit for building containers (maybe for hosting them, too, eventually)

NixOS has support for hosting containers, which share the Nix store with the host, so they're presumably pretty lightweight.

I've tried running NixOS in VMs, using Nix on Ubuntu, orchestrating things with NixOps, etc. and found that it's much more painful than just installing NixOS on the bare metal and managing everything via /etc/nixos/configuration.nix

mlieberman85
Agreed. Also in general the amount of bugs in Nix packages that go unfixed for months at a time is tough as well.
corysama
My Linux experience so far has been limited to ls, cd and vi. From the outside, package management has always seemed to me like a huge mess. But, I've been starting to learn Nix recently and I really like it. I can add, remove, test, screw up, change my mind, whatever without stress.
pmahoney
"I can add, remove, test, screw up, change my mind, whatever without stress"

I love Nix and completely agree with that, and I do have lots of experience with several package managers (deb, rpm, rubygems, ...)

overcast
In my opinion, everyone should learn the basics of package management, and be able to get a full stack operational. Valuable, especially if you're doing side projects.
SwellJoe
"From the outside, package management has always seemed to me like a huge mess."

Compared to what?! There's no OS that has historically had better (or even close to as good) package management as Linux, either in the form of apt-get/dpkg or yum/RPM. Nix is probably better, on a couple of dimensions, but to suggest it was a mess before...well, I just wonder what you could be comparing to that would be better?

_bpo
It doesn't need to be compared to anything to be called a mess. dpkg/rpm have been widely useful, but package and dependency management is still a PITA.
Ericson2314
As a huge Nix fan, I think it's perfectly acceptable to say non-linux package management is an abomination, linux package management is a mess, and nix is not (yet :)) ideal.

Engineers shouldn't assume something is done well because nobody is doing any better. Some things suck and there's nothing to blame but other priorities or sheer laziness.

SSLy
Um, IPS, BSD ports and pkgsrc are a thing.
SwellJoe
IPS and ports, really?

pkgsrc isn't bad at all, but definitely not better than yum or apt. One might prefer pkgsrc, but one couldn't reasonably say yum or apt are a "mess" compared to pkgsrc.

j_s
Perhaps https://ninite.com/ ?? :)
Artlav
Perhaps it's about expecting to have program locality?

I.e. you download a zip file, you unpack it into a directory, and here is your entire program. Right there, in that directory, not splattered around the filesystem by the package manager.

That's the way it's done on Windows, anyway.

icebraining
No, Windows has %ProgramFiles%, %CommonProgramFiles% and the registry as officially supported places to put application data.
SwellJoe
Huh. I didn't even consider that. I guess it's been a very long time since I've used systems where that was a thing that happened (and Windows isn't such a system, realistically speaking; Program Files, registry, etc.). But, I do remember coming from Amiga back in 1995, or so, and thinking UNIX/Linux was crazy with things spread all over the place. Amiga did work that way, generally speaking (though it looked a little UNIX-y at the system layer, too). How was I supposed to find anything?

But, the package manager knows where everything is so I don't have to (and there's consistency across systems...system python/perl/ruby/bash is always in /usr/bin).

If that's why "it's a mess", then I have to argue that it only looks like a mess, until you get to know it a little better. Package management is the single biggest reason I have never been able to seriously use any other desktop OS over the past 20 years, or so (I have a Windows partition for games and audio, and I've had a Hackintosh a couple of times for tinkering with iOS dev, but Linux is where I get work done).

chriswarbo
Last time I used Windows very little would work unless it was a) installed and b) installed to "C:\Program Files" (some software, can't remember which, would let you choose a different location, but wouldn't work).

It crushed my dreams of a small Windows partition + a large data/programs partition :(

johncolanduoni
Perhaps for the newer Windows platforms (e.g. UWP) but Win32 installers have definitely been known to put things all over your system.
Artlav
Yeah, that's the reason why i have a "got installer? not worth using" pre-filter for Windows software.

Not sure how things are these days, but i'm talking about the Win 9x to Win 7 days.

RaleyField
I'd have opposite filter. Did you correct permissions for folder where you unzipped/placed executables so that it couldn't overwrite itself? Correctly installed software in program files folder would be protected from being overwritten without administrator privileges.
yiyus
But that is not a packaging system. You can put binaries in zip files in Linux systems too.

And I don't understand what kind of software you used with that pre-filter. You cannot even install drivers then.

Artlav
"Pre filter" is kind of like a rule of thumb. There are exceptions for stuff like drivers and for big corporate programs that just don't come in other ways.

But a lot of smaller programs are available in the zip form, or have alternatives that are.

In short, i prefer portable programs - https://en.wikipedia.org/wiki/Portable_application

fizzbatter
I love the idea of NixOS, but overall i think i need to wait for it to be a bit more user friendly. The number of times i was completely perplexed when i tried to use this as my home server was.. well, numerous.

Awesome idea, and the rollbacks were great, but i kept having to write my own packages and it was all a bit too confusing to do that constantly.

themartorana
Anyone using NixOS as a server in production? We're on FreeBSD now but I think Linux in our stack is inevitable (many servers, like Aerospike, are Linux only). There's always Ubuntu, but this looks lovely. I've had my eye on it for a personal Linux workstation but haven't heard anything about it as a server.
teh
We run a fleet. Happy to answer questions here or shoot us a mail at [email protected] if it's sensitive.
tikhonj
Do you have a blog post about it or something? I don't have specific questions, I'd just love to see how Nix looks in production.
teh
No high level overview, just a fairly specific (and sadly slightly out of date) one here: https://blog.wearewizards.io/how-to-use-nixops-in-a-team

It's still Linux but a lot of common problems go away. E.g. if you remove a user from your config then it's removed on the server (as opposed to Ansible).

Or: Because you have a dependency DAG all services that need restarting after a change are known (no more Chef notifies :restart).

Or: No more apt-get dist-upgrade. You can have a single package depend on an entirely new version of your OS and keep the old OS in place (except for the kernel version of course).

viraptor
How's the binary security on NixOS these days? The official information I find are... worrying. Specifically: a) security updates are the same as all the other updates and may take days to get to you, do runtime replacements manually yourself (https://nixos.org/wiki/Security_Updates) and b) next to no hardening during compilation (https://nixos.org/wiki/Hardened_NixOS)
teh
Both good points. In practice a) hasn't been an issue but for b) we had to apply a fair amount of patches ourselves.

Luckily b is almost fixed, and if combined with e.g. grsecurity I think nix has a good story.

frio
Good news! Hardened NixOS isn't far: https://github.com/NixOS/nixpkgs/pull/12895 :). I've been watching/waiting for that for a while myself, and the progress on that ticket has been encouraging enough that I've started building out NixOS stuff in anticipation of it landing by 16.09. Now I'm somewhat slavering for it because I've come to like NixOS a lot more than I thought I would...
drvdevd
I've used it as a server before and it's quite nice, it just requires getting used to the nix language a bit and possibly dealing with customization work when something you need isn't exposed already in /etc/nixos/configuration.nix. For example, imagine you needed some weird iptables functionality - you might end up writing some shell-ish rules using 'networking.firewall.extraCommands' [https://github.com/NixOS/nixos/blob/master/modules/services/...]. Of course other admins on your team might have to be on board with this learning curve too.
drvdevd
I should add that there are the obvious benefits to these 'constraints' -- if you can stick with mostly what's exposed already in the default nix packages your configuration will be very clean and your system will be built in a reproducible way from the start.
rb808
If you're a non-trivial shop you'll need to harden it, you're better off with CentOS/RHEL than Ubuntu.
icebraining
Why?
joseph
Probably because mainstream distros like RHEL have third party tools available to verify that instances meet standards such as CIS. NixOS might be a great design, but that isn't going to matter to $InfoSecDepartment when they lack the ability to audit.

Edit: Just noticed the parent was comparing RHEL to Ubuntu, not NixOS, so now I'm not sure :).

ramblenode
NixOS recently got a big update to its Grsecurity module and will probably merge a large set of patches in the next month or so for compiler hardening. There is a lot of work being done on this front.
jallmann
I'm using a NixOS server in prod for an application. Works very nicely, makes deployment a breeze. I went from never using NixOS to having a production-ready deployment, including writing a nixpkg for Nignx configuration and my application, all in about a day. I love how an entire server can be configured with a single Nix file (configuration.nix) along with any custom packages, which are again flat-files.

NixOS works best when you're 'all-in' with Nix, including using nixkpkgs over language package managers (or having such package managers be nix-aware). This is not something that's easily done right now, and precludes having a 'pure' Nix experience, especially when using it for dev purposes.

In my case though, where the main application is a binary written in OCaml (which uses the opam package manager), NixOS makes it straightforward to build and distribute binary packages that are patched to the correct library paths on the system. Once that was set up, everything else was a breeze. Server maintenance is almost effortless.

transfire
It's very cool what Nix has managed to accomplish. Unfortunately, after studying it I've started to think the solution is overwrought and might be more trouble than the problem is solves, or as I like to say, "with solutions like that who needs problems?"

I think it boils down to these points from the summary:

> Thus the same package can coexist on the system with multiple configurations.

That we have to worry about multiple static compilations of a package hits a deeper problem that Nix can't fix. Namely that there really shouldn't be any need for static install configurations. So the only static differentiation that should be necessary is version.

> The derivation is a string in key-value format which will ultimately be hashed and which can refer to objects in the Nix store

So why create a whole new "expression" language just to generate these? Developers work with key-value formats all the time (e.g. YAML, JSON). The whole functional language thing seems almost like a slight of hand when you realize this is the end result.

sdegutis
> where multiple versions of the same library or application can live in harmony

How does NixOS solve the diamond dependency problem?

smallnamespace
It's largely mitigated by allowing multiple versions.

Imagine A depends on B and C, which both depend on D. The diamond dependency usually pops up when B and C need different versions of D.

But in this case, Nix allows you to simply install another version of B or C such that they can share D.

This doesn't help you if there's no set of A ... D that are jointly consistent, but then you would've been SOL anyway.

corysama
If you are asking about a single application depending on conflicting libraries such that it can't be built at all, I don't think NixOS can solve that. What it can do is have multiple conflicting libraries installed simultaneously and individual applications can choose which completely-defined environment they want to run in.
geofft
I think in practice, I have far less trouble with the actual diamond dependency problem - binary A requires libraries B and C, which depend on two different versions of D - than the boring version - system A runs binaries B and C, which depend on two different versions of D. NixOS solves the latter.
ambrop7
Normally you end up only a single version of a library needed in the scope of one application. E.g. application A depends on libraries B and C and both of these depend on the same version of library D. And there is no problem as long as this is the case, the exact same library will be used.

If for some reason B and C depend on different versions of a library, then things may go wrong, e.g. one package may end up inadvertently using an incorrect version of a dependency. Nix cannot solve this problem because it originates from the OS/compiler design (same sonames, same symbol names). Consider that with respect to libraries, Nix mostly just wraps the compiler to add needed -L flags and also sets RPATH in shared libs and executables so that needed shared libs are found at runtime. If an application effectively depends on different versions of one library with the same soname, the dynamic linker will still use just one of the available ones.

What Nix does allow you to do is to isolate packages from one another. You can have one application using only one version of library D, and another application using only a different version of library D.

I should note that it's somehow hard to get to this situation, because the Nix packages collection (nixpkgs) doesn't keep too many versions of packages. Typically for minor upgrades the library is just bumped, and when you rebuild the final application all references to that library will be up to date. You can only realistically get issues if the application ends up depending on different major versions which are both maintained in nixpkgs but are not designed to work together in the same application.

nine_k
I suspect that the same binary cannot realistically depend on two different versions of a library.

I can imagine that package A may have two binaries, one depending on a library B version 1.1, and another, on B 1.2

Does NixOS allow to have both B-1.1 and B-1.2 installed, and A's different binaries to load the correct different versions of the library from B-1.1 and B-1.2?

ambrop7
Well yes strictly speaking, the same binary. But in practice with Nix's default library resolution logic (the mentioned compiler wrapping) you will probably also have problems trying to build binaries in one package using version of a library (see note [1]). That is, I think you'd have to do some "hacking" to fix the issue, or separate the binaries into different packages (and maybe create a new package that "assembles" all the binaries by creating symlinks to them).

> Does NixOS allow to have both B-1.1 and B-1.2 installed, and A's different binaries to load the correct different versions of the library from B-1.1 and B-1.2?

Yes, well actually, the thing is that typically you only "install" (into a user environment) final applications (A) that you need not libraries, so the libraries (B) can be considered to not really be installed, just available (somewhere in /nix/store) and referenced correctly (e.g. by RPATH).

[1] When you declare a dependency in a package specification by putting it into buildInputs, the compiler wrapper will automatically add an -L<store_path>/lib so that linking with just -l will find the library. With multiple versions of a library in buildInputs, that becomes a problem.

dbcurtis
As I understand it, Nixos runs their own patched versions of ld and the dynamic loading system calls in libc. The normal lib.so search mechanism is replaced wholesale with "thou shalt link against this dll and no other" on a per-execuatble basis. Multiple versions of .so's don't cause problems, because no executable is depending on a search mechanism it doesn't control.
ambrop7
I think that they don't do too drastic changes. There are certainly checks in the compilation process to not accidentally link to /usr/lib/ libraries, but I think the main problem of finding libraries works with a simple compiler wrapper adding needed -Lflags (for finding libs at compile time) and RPATH entries to binaries (for finding libs at run time). There of course may be "hacks" made to gcc/libc but I don't see a reason they would be essential for functioning.

One notable thing Nix does is hardcode a path to a specific dynamic linker (e.g. /nix/store/HASH-glibc-2.23/lib/ld-linux-x86-64.so.2). All other dynamic libraries should be referenced through soname+RPATH.

dbcurtis
I agree that the changes are likely not extremely invasive, and I would hesitate to call them "hacks". OTOH, it does make Nixos fundamentally different from other (u)nix systems. They are basically saying it's time to hard-fork the (u)nix philosophy about how dynamic linking is done. They might be right.

It's a very interesting approach, and I want to understand it in detail. I haven't had the time to bring up a Nixos system yet, though.

vertex-four
Actually, I think they use the standard ld.so... it's just that for every executable, the RPATH in the header of the executable is set to a list of directories where the libraries it was built against can be found. ld.so uses the RPATH to find libraries by default.
ambrop7
No they definitely use a nonstandard ld.so path. What I showed above is actual output of ldd except there's an actual HASH.

If you think about it makes sense, glibc is still "just" a dependency so it needs to be references from dependant packages by a concrete /nix/store path. You wouldn't want to have a single global libc.so, because you want to be able to upgrade one application using different/newer OS components including libc without possibly breaking existing applications.

The ld.so path is basically the first thing you need to fix when packaging prebuilt software (using patchelf); the second thing are RPATH for other library dependencies.

EDIT: Yes the ld.so probably isn't patched, I failed to completely read your comment. If you want to know really you'd have to look into nixpkgs of course.

vertex-four
They use a nonstandard ld.so path so that if you build a given binary with a given version of gcc, it uses that gcc's ld.so - but the ld.so isn't patched.
awqrre
In a CAD world, that would be like parametric drafting?
SSLy
Yeah, more or less.
agumonkey
does that imply live/realtime recomputing ?
Ericson2314
I'm going to take a wild guess: yes :)
dominotw
so could this replace docker as distribution format? cgroups and namespaces can be use independently of docker.
benley
Not exactly ... but you can certainly use Nix to build docker images, which is very convenient.
davexunit
See also GNU Guix.

https://www.gnu.org/software/guix/

inquisitiveio
Which is also worth mentioning, builds part of its package management on top of nix https://www.gnu.org/software/guix/about/
wanda
In a similar vein is Intel's Clear Linux[0]

https://clearlinux.org/

codemac
Clear Linux is much more focused on the "containers as VMs" direction than nix or guix are (Use the $PATH instead of containers, no virtualization of network cards etc).
paxcoder
Would be nice if someone could update the previous NixOS vs GuixSD discussion: https://news.ycombinator.com/item?id=8246338
paxcoder
GNU/Linux distribution with revertible package management.

EDIT: I believe that my description is more accurate and if I am wrong I would like to be corrected. But I'd appreciate if you didn't downvote me simply because I use the term "GNU/Linux". I don't downvote you if you use the kernel's name for the entire OS. Thanks.

qwerty12653
I really want to like NixOS, but there's a serious lack of examples of how to deploy common web infrastructure with it, and that's bitten me the few times I've tried to play with it.

For example, our stack is nginx, uwsgi, django, elasticsearch, and postgres. Installing most of the pieces seemed relatively straightforward(though required a fair bit of searching through the nixpkgs source), but it's honestly pretty unclear how to install our actual django app.

Currently we just clone the repo to the server and point uwsgi to the relevant uwsgi.py file, but it doesn't seem like there's a good way to do that in NixOS.

I'd love to hear that I'm wrong here, but again, the lack of decent example documentation is really the single biggest issue I have with NixOS. The rest of the documentation seems to be improving slowly but steadily.

thinkmoore
You might be interested in checking out Habitat from Chef, which uses many similar ideas: habitat.sh
rokgarbas
as nixos user i looked at habitat and the thing that i will never switch to habitat is that environments are not (build) reproducible. basically habitat is more like docker where it snapshots "successful" build and you use that input for further building.

what i loved about habitat is the supervisor part. i there is a way to use habitat's supervisor with nix. then you get best of both tools.

until then i'll just have to stick to python's supervisord.

HN Theater is an independent project and is not operated by Y Combinator or any of the video hosting platforms linked to on this site.
~ yaj@
;laksdfhjdhksalkfj more things
yahnd.com ~ Privacy Policy ~
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.