My NixOS Desktop Flow
christine.website
christine.website
I don't know. Not much about all this setup feels appealing. The apparent learning curve for nix looks...steep. I've been using linux for a pretty long time (I think kernel 2.1 was fresh when I started). I've done the slackwares and debians and redhats and arches and gentoos etc. And I have zero desire to put such effort into having a working system.
I realize the post is prefaced with a warning that it's over-engineered. I guess my question is- can I use nix without going so hard down the rabbit hole? I don't think I have the time to invest like my gentoo (read: teenage) years.
I'm pretty satisfied with doing a minimal install of fedora, setting up i3 and firefox and calling it a day. Maybe I'm just older and more crotchety than I thought.
We use NixOS on three machines around the house, but I use Nix + home-manager on my MacBook, and various Ubuntu servers at work. It's nice that I can largely use the same configuration across all machines. Just a home-manager switch and I am in my native environment.
last time i checked the install-instructions on Catalina, you had to create an unencrypted volume to store the nix-things, which i'd prefer not to do (i understand those files are probably non-personal, so no need to encrypt them, but i don't want to have to remember that half of my hard-drive is unencrypted)
is that still required or is there a simpler approach now?
Ideally the Nix store would be in some non-root location. But that requires a completely new binary cache among other things (since /nix store paths are hardcoded in binaries, scripts, etc).
Also making /nix a symlink doesn't really work in some cases, since realpath reports the actual path and that may break builds/applications.
It used to work so nicely out of the box :(, but I can also understand why Apple wants to enforce read-only system volumes, since it blocks nastier rootkits, etc.
Honestly, I think they should just relocate it to a different location that can be persisted and rebuild the packages. I don't think people care about the location as long as they don't have to recompile every single thing. This could also be useful to catch all bugs where /nix was assumed.
I'd recommend giving it a try if you have some time on your hands to get used to it, but you shouldn't be expecting a quick switch.
Additionally I'm a heavy Emacs user, and couldn't type a single line of elisp. I get that I'd be better in Emacs if I knew elsip, but that doesn't stop me configuring my text editor by borrowing code from others.
And thats just the first time you use nix. Next time you just reuse that thumbdrive, or redownload it, and get your config from a git repo you are tracking your config in.
I have a git repo that has configuration for three types of devices I run in my personal setup (desktop, nas, webserver). They all inherit from my base configuration which has stuff like the user configuration and maybe my vim how I like it. The server adds docker and runs the docker containers that it should. The nas mounts the raid array etc.
If I want to know how I configured my nas three years ago, all I have to do is read the nix file I checked onto github. Thats powerful.
You forget the step "find out what to write in the nix config file". Might take anywhere from less than a minute to forever, depending on experience, google-fu, and documentation.
From OS point of view you no longer need:
- Kickstart
- Ansible, Saltstack et.al.
- Custom package repo for custom packages (if you need to customize something)
There are other areas too:
- create common developent environment, makes sure every developer has exactly the same tools installed with exactly same versions, so no more "it doesn't work on my machine"
- build system
- CI/CD
- packaging (as mentioned, you no longer need artifactory, instead you can have nix cache)
- there is also potential to use it for IaC, there's NixOps, but currently this is maybe the weakest part of Nix, it only covers deploying a box, but if you want to do something more complex, like autoscaled service it gets in the way. It is great for developing a new image though. There are terraform integrations, I didn't try them yet, might work better.
- you can configure local developer machine to use build system for local builds as well. If caching is configured, then once code is deployed it will already cache good build so it doesn't need to redo it
- for personal use with things like home-manager it can replace dot files as do more, you can have the same environment each time. Let say you change job and get a new laptop you can have it quickly set up the way you want it
Maybe if I was a sysadmin managing a herd of boxen I would like this, but for a guy with only two Linux systems (plus my mac, plus my windows boxes, plus my openbsd pcengines etc.), it seems like a lot of fuckery with text files for little to no actual improvement in my UX.
You put in there what packages you want installed, what users, what SSH keys, what services systemd manages.
Then, you run `nixos-rebuild` and then you switch your system to that configuration. The old state of your system stays around until you run garbage collect. So you can rollback to it, if you want.
Seems like it comes much easier to most people to issue series of (often nondeterministic) commands that mutate state rather than learning a new language that allows describing dependencies and have it figure out steps needed.
The issue to me is that it's mostly a regression and that when showed nix/guix people would squint saying it's horrible.. when in fact docker way is horrible, it's just nicer to them.
Alas, such is society.
If all you do is apt-get install docker, that doesn't feel like a very complete set up to me.
I can already do that with Kickstart for rpm distros, though.
How often are people doing this, though? I get a machine set up pretty quickly (install list of packages, systemctl enable <foo bar baz>, reboot), and I'm set for several years.
I'm quite new to NixOS and recently tried home manager, which basically manages your home, primarily all dot files, but goes as far as preinstalling favorite extensions on Firefox for example.
When you're solo there's no such restrictions, you can just use the nicest tech that's out there. I've been amateur-adminning debian/arch/ubuntu machines for 15 years now, NixOS is such a relief to be rid of that mess.
In what way? Why are functionally-declarative system configs good? What does the increased workload gain me over my usual list-of-packages-to-apt-get?
... at least that's my experience.
I am sorry but that is fanfiction that nix people want to believe. There are numerous reasons not to use nix, a few: - Incredibly smaller community - Incredibly smaller support from community and enterprise - Yet another programming language - that is difficult to grok
Those alone can kill any technically sound project, but there are lots of others. Such as slow installs, storage requirements etc.
I had a machine that I let run with an old (private) certificate for years because I didn't remember the how and the what of renewing that specific certificate.
I had another machine that had a hardware failure, and I spent an enormous amount of time recreating it.
Have you had to deal with breaking changes in the config language? (Does this ever happen? Are there versions/specs of the language that can be pinned?)
Basically you pin to a version of NixOS, and opting into the next version is fully optional. So if you change your NixOS version, and you run nixos-rebuild, and stuff doesn't work, then you can just undo your change. NixOS even keeps a backup of itself ready, so say for some reason you update but your new version doesn't boot, you can simply boot into your previous working version.
With an OS there is a problem, because most of the time you don't want to do that, you want to get security patches and erratas. For this purpose channels are used. They promise to not break anything within release channels. This is very similar to how other OSes, you need to trust them to not break thighs. There is also option to subscribe to a rolling release, so similarly to other OSes there are more opportunities for things to break (living on the edge and all), but the stuff below still applies.
On top of that there is also variable in your configuration.nix it is set to the version of NixOS that you first installed. That version is version of the configuration file and supposed to guarantee compatibility. The compatibility they mentions are things like for example default version of PostgreSQL that they use if you choose default one you don't want on system upgrade to automatically force you to upgrade your database. Another obvious change is change of defaults, perhaps they decided that service that was previously enabled by default should be now disabled etc.
You can bump the version in that file, but then you have to go through changelog and adapt your config to these changes.
I am relatively new NixOS user, but just did uphrade from 19.09 to 20.03 and it went smooth as if it was just update within the same release.
The NixOS configuration language is a unifying layer of abstraction and allows people to more easily re-use the work of others (compare with pasting commands from a how-to blog post).
I use custom install and configuration scripts for various Linux distros and Windows installs, this is not a feature unique to NixOS, just a different implementation. I use a shell script for Linux and a PowerShell script for Windows.
NixOS is great for:
* shortening the divide between the user and upstream: not just release lag, but also the ability to contribute to upstream. NixOS makes it trivial to write a patch and deploy it your system, something I wouldn't usually bother with Debian, for example, because the same process was so frictionful.
* configuring services
* packaging ad-hoc code/scripts
I really disagree with this. NixOS is also great for simple use cases like this because it's robust. I know a lot of people who switched to Linux, need to get something to work, follow some online tutorial/directions blindly, and just break shit pretty badly.
This isn't contrived: even seemingly-inoculous commands like "pacman -Sy" on Manjaro/Arch can fuck your shit up (it basically amounts to a partial upgrade).
NixOS doesn't let you break shit like this. (Literally, upgrades are atomic and packages can never have missing dependencies.) And, even if somehow you did, you then have a nice configuration.nix to quickly get back up to speed.
Fedora nowadays has btrfs-level rollbacks, which although this doesn't interact well with cfgmgmt (unlike NixOS's excellent rollback support), it's perfectly fine for an end user.
I tried to setup a simple NixOS machine this week. From this experience I couldn't manage to install any GNOME extensions via the browser plugin because of some Firefox manifest location that conflicts with the way the NixOS store handles it - there is some workaround in some tickets, but it made me wonder how many other applications are in need for specific workarounds. I then enabled flatpak via the OS configuration, but the first installed app couldn't launch because of some obscure error with gstreamer. I changed to fedora and could setup anything without any of those issues.
I really want to like NixOS (I still do), but I now consider it more for a server environment than a casual desktop environment.
I just gave up using Flatpaks with NixOS and install GNOME extensions through Nix.
Let's say your patch doesn't get in in time for Terminator 0.96 (following the same example), or it's not relevant for upstreaming. Now you need to go through the same process again to upgrade. So much for `apt-get upgrade`. And it gets even worse if your change breaks binary compatibility: now you need to find and rebuild all packages that depend on it too!
The beauty of NixOS here is that you patch the "repository" instead, so will get applied on top of the current version as long as the patch applies cleanly. And all of Nix's usual logic applies for rebuilding dependendees as required.
* how do you roll that dpkg out to your fleet? Now you need a deb archive?
* "For Debian the tool is called reportbug". Note that reportbug is a CLI tool to send an email to Debian's bug tracker, whose status/tags are then also controlled by control emails. It has a notoriously difficult learning curve.
* Many Debian packages expect patches via email, rather than the more familiar git-based approaches. Some Debian packages do accept patches via git, I'm aware. Hopefully the package you're filing a patch against does.
* The blog post also misses out the work the Debian package maintainer has to do: use their own approach (and there are multiple) for doing a package release/signing. NixOS? It's a PR that's built by CI. Like how we usually handle software systems.
* You've patched a single version. What happens when a new package is released but your patch didn't make it in?
IME, after years of using Debian I made a few but barely any patches against Debian because of the frictions involved. The frictionless experience of NixOS has made me more active.
That said, are we really reading the same post? What's presented here is...really simple, and you should be pretty much familiar with most of it if you actually set up Gentoo and Arch in the past; pretty much everything directly translates that requires user interaction in this, and the package format is pretty similar to write & read, too.
It's not unreasonable at all. It all depends who is claiming that. Consider Mac OS and compare it to any Linux in terms of the learning curve. Can my mother say that Linux is unappealing because it's to hard to learn it? Of course.
Even among engineers there are people to prefer just getting the stuff done without spending hours or weeks on configuring their environment (even if it could pay off).
The domain still waiting for Desktop Linux to happen.
Not much about all this setup feels appealing.
The good features about, say, OS X, are not made less appealing because of the rest of OS X. They're still appealing properties.
If you have the person you're speaking to go through the same process, you might find you've assigned points differently. And the net sum might be closer to zero for them. That's what makes going through the entire process unappealing for them.
I'm honestly curious why you dislike it
* Poorly-implemented versions of theoretically-interesting ideas
* Poor implementations, technically
* Lacking merit compared to its best competitor (insofar as free software has competitors)
* Lacking merit compared to its main competitor
* Deep philosophical and moral disagreements
* Toxic and obnoxious community
This isn't to say it's bad, of course. It's just something I dislike; I seek no wider war.
Why is it poorly implemented, what are the problems?
Who is the competitor, and why is it better? (Guix?)
What are the philosophical issues?
How is the community toxic and obnoxius?
Personally there are a few things that annoy me about Nix, mostly implementation and documentation wise. Also, the language is pretty odd and the CLI UX is somewhat messy.
But the community (IRC / Discourse) has been pretty helpful for me thus far.
However, I will note that I listed two competitors, not one, and while I think both have more merit, I only think the best is worth using out of all three. I'll point out that it's not Guix, and that it's older than Nix, but I don't think advertising alternatives is a particularly nice thing to do in a thread about any given piece of free software.
Please substantiate - I'm not involved in the Nix community much but whenever I've been in the #nixos IRC channel, they've been super helpful.
It's a little too late for that. Complaining in a vague way across several comments and then not elaborating further is, I think, definitely more rude than making some concrete complaint (like the original comment's complaint about learning something new)
I said I didn't like something as a way of making it clear that I'm not trying to brigade for Nix and don't really have any incentive to defend it, and I gave an argument on why I believe the initial comment was being unfairly negative to Nix.
I was then asked why I disliked Nix. I made no complaints, I just listed my opinions. When I was asked to go into actual complaints implying fact rather than personal opinions, I said I'd prefer not to.
I don't think throwing unsubstantiated claims around is a particularly nice thing to do. I don't mind you having these opinions. But if you're not ready to properly argue them, it's probably better to just abstain from the discussion entirely. That's how I handle my own opinions as well.
I'd be perfectly happy to argue for them, but I don't think this is the right place to do it. Frankly, I don't care about how you handle your own opinions. When I am asked about my own, I'll tell them. I won't try and sell them as factual to anyone else, though, which is what going into more detail would require me doing in this particular instance.
- It can't be GoboLinux, because that post-dates Nix (by a small amount)
- I've never heard anyone suggest environment modules have more technical merit than Nix, though they do predate Nix
- Could it be portage, which has some of the same features as Nix? Nix explicitly cited portage as a predecessor, and IMO it surpasses it, so that would be surprising...
I really don't know anything other than Nix or Guix that follows Nix's philosophy. I'm really interested to know what you're referring to!
It looks like so, indeed the manual is fairly extensive yet it probably lacks a hands-on approach. That's what I'm aiming to solve by writing a couple of articles explaining pragmatically how to use Nix (not NixOS, I'm not quite there yet), starting as a Homebrew replacement.
And really, at the end of the day the new language is not really harder than having to learn Ruby and the Formula DSL, or ABS idioms and its shell idiosyncrasies in PKGBUILDs.
My recipes: https://github.com/pauldotknopf/darch-recipes
I have the same exact images, bit-for-bit, running on 3 different machines. I have a zshrc alias that allows me to sync my current machine with my work image that I have stored on Docker Hub.
Is this a non-issue?
See my recipes repo for an example.
My scenario is similar. The current version is 100%. However, I'm going to be refactoring a bit, moving some pieces around, to support some new features. The only breaking changes that user's will notice is that ```darch recipes build``` will be moving to ```docker build .```. I've already converted my personal recipes to use it.
Looking at the recipes this seems to be non-deterministic/reproducible. E.g.
add-apt-repository -y ppa:longsleep/golang-backports && apt-get update
From: https://github.com/pauldotknopf/darch-recipes/blob/502fb3d66...There is no guarantee that you will get exactly the same Go version when rebuilding an image. And all the scripts seem like that: ad-hoc wget and apt command, where package versions, how they are built, etc. can change between runs.
This is only a very weak notion of reproducibility: if the scripts run, you will get an image with the same packages. Nix/Guix guarantee that you get exactly the same versions, built in exactly the same way, from your own package down to transitive dependencies such as glibc or zlib.
(I am not criticizing the project, it may be great, but it is just not reproducible/deterministic.)
1. Temporary boots. You can "sudo rm -rf /", reboot, and all is well. You can play around with "apt-get install" without having to commit to your changes being persistent.
2. Checkpoints. Each "bash script that you call on first boot" is versioned and you can easily revert back to any image at any point, as simple as running either "docker run ubuntu:bionic" or "docker run ubuntu:focal".
3. Store your builds in Docker Hub (https://hub.docker.com/repository/docker/pauldotknopf/darch-...) so that the same resulting image can be run on any of your machines via "darch images pull your-image && darch stage upload your-image".
Your bash-script approach to building a fresh machine would be a lot more involved than:
1. Make changes to your script.
2. Check in a push to repo.
3. Wait for CI build to push to Docker Hub.
4. "darch images pull my-new-image && darch stage upload my-new-image"
5. Reboot.
6. Enjoy.
I find something like this[1] far more useful, because it actually has some applications.
> what darch does can be done by chroot, namespaces etc and is not that complicated.
Exactly my point.
[1]: https://r13y.com/
You don't really hear people complain about the reproducibility of "docker pull ubuntu:bionic".
I’m not arguing for Nix (had a look and it seemed more complex than I can bear at the moment), just that new tech in general needs time before it can be properly compared.
How is that not a good thing? I enjoy nothing more than learning a lot in a short amount of time.
* A workstation machine where you do everything from development to watching netflix
* A server (whether VM, Metal, Container)
The former wants convenience and flexibility. I agree with you - I also use Fedora because (particularly with Lenovo hardware), you install it and you're done. Everything works. I don't want to have to go and write nix expressions because I want to run a not-very-obscure thing that isn't packaged. It's ok for me that my workstation is a 'pet' and I blow it away every 6 months to a year.
The latter case is more interesting and has some specific requirements on it. We all know about configuration drift. The idea of getting completely deterministic setups, and unifying how you do that across VMs, native and containers is great.
This NixOS stuff is very interesting, feels like living in the future. Turning it into Windows10 is exactly what would repel me from enjoying it.
To some extent my chromebook is completely deterministic in that there is no setup other than my wifi credentials and google login. Its weird and fun to compare.
Nix can certainly be limiting in some ways. But everything can--we just habituate.
It's possible to find interesting tools that aren't at all cross-platform, or that require hours of DIY spelunking to get compiling, or that are only in some other repository. It's possible to find something you want to use that either isn't packaged for or is broken in every package manager.
I use Nix (on macOS and NixOS) for roughly the same reasons: convenience and flexibility. But from a different angle, I guess. It is freeing to know that everything I need to make forward progress on all of my personal and professional projects is specified. I have the flexibility to resume work on the projects I care about with almost no friction beyond securing new hardware.
You can use it to set up a per-project nix-shell that gives you an experience a little like docker (in terms of speed), but more convenient because your normal machine is available on the PATH (or not, if you run --pure).
I can then use that same Nix config in my CI - just use the base Nix docker image and then apply the nix-env as a pre-script.
For me the fact that I can replicate my machines with a couple of config files is the major driver. That and the ability to install a package in a shell, use it, then exit the shell and not have it installed globally is amazing.
Of course, you can use the nix package manager on any Linux distro and even macOS if you want a gentler introduction.
I can't even count the number of packages I have installed because I needed them once. I have an entire Node.js ecosystem installed because I needed to run a frontend from another team for 20 minutes. Could I have done all that in a single shell, then had it automatically cleaned up when I was done? My current solution is to spin up a container, but that becomes a pain and I end up getting lazy and just globally installing everything again.
Yes, that is a pretty standard workflow for most nix users. You either set up a shell.nix for your project with all of its dependencies, or if you need a certain tool once you just write for example: ‘nix shell -p iotop’ to enter a shell where iotop is in the path.
When I first started using NixOS I had a huge list of globally installed packages, but that has become smaller and smaller over time. For instance, my main browser is Firefox, which is installed globally, but if I need to use Chrome, then it gets fired up in a temporary shell.
Yah, the more I think about it this is the biggest selling point to me.
>> Of course, you can use the nix package manager on any Linux distro and even macOS if you want a gentler introduction.
I actually never thought deeply into nix NOT on nixos (I've probably been conflating the two). As an infra/devops-y person I can think of a lot of cool use cases off the bat in the server-space (theoretically anyways, I've a feeling the details would be quite the devil). But, except for the case of developing for such a system, I'm struggling to see a use case that warrants it in the desktop realm. (I need to meditate on this one..!)
There is small learning curve for getting to know rpm-ostree and toolbox tends to be a hindrance if you want IDE integration. Also you have to reboot after installing packages to the core OS, that's mainly why they recommend using flatpaks, but it's optional.
Note that it's still beta but pretty reliable as you can always downgrade and wait till they fix stuff that may be broken after an upgrade.
When it comes to actual setup needed it's not much different than a regular distro. No language to learn, no additional setup required.
Initially I played around with toolbox, wrote a 30 line bash script for initial setup for it and eventually ditched using it.
You can still use RPM Fusion and install regular .rpm's.
One thing to note is that they recommend to use the default partition layout as custom ones can (and do) break.
For example, on other *Nixes, you install and uninstall packages, maybe configure them, but you're not BUILDING packages. All of the complexity of this article is in the superset of what you'd normally do.
For the most part, just add things to systemPackages in configuration and `nix-rebuild switch` or install via `nix-env -i` if you want user scoped installs.
services = {
acpid.enable = true;
openssh.enable = true;
tlp.enable = true;
xserver = {
enable = true;
layout = "us";
libinput.enable = true;
displayManager.sddm.enable = true;
desktopManager.plasma5.enable = true;
desktopManager.enlightenment.enable = true;
};
};
and then after the OS is install firefox to your local user profile: nix-env -iA nixos.firefox-bin
You will also need to partition your harddrive, but the install/live USB includes the KDE partition manager, so you don't even need to use the commnd-line for that.Once you get familiar, you can see how you can make a reproducible dev environment, the author has a blog how to do it for rust[3] but many things still apply, I for example did a template for python [4], I eventually plan to put a less trivial app with unit tests once I get some free time.
[2] https://nixos.org/nixos/nix-pills/index.html
[3] https://christine.website/blog/how-i-start-nix-2020-03-08
Exactly. While reading the post all I could think of were flashbacks of dependency hell and not one thing I was reading appeared to be helpful in eliminating it. But now I have to put up with the crazy cryptic language that I've never seen before.
Thanks, but no thanks.
I really like the general idea of nix, I think it’s going in the right direction and I am very grateful for all the people doing amazing work there and I wanted to give it a try for a long time, now.
But my recent experience with nix on MacOs has mostly just been incredibly frustrating. I started using nix one or two weeks ago, because I needed it for a project with haskell-miso (which I very much like, by the way).
As long as I just stuck to using the default.nix provided by Miso, everything worked fine, more or less, but as soon as I tried to go beyond that to customize things for the needs of my own project, the problems started to accumulate.
I needed to google for and apply manual fixes for some very basic things, because nix did not play well with neither macOS Catalina (nix needs access to /nix) nor with fish.
Some haskell packages I need like constructible were broken in the default channel and I had no idea how to fix those packages. In the end I ended up switching to a “stable” version. I do not understand why nixpgs-unstable is the default channel, by the way.
Sometimes things seem easy in some guides and I thought I understood them, but then when I tried them they just won’t work. For example I was hoping that
nix-shell -p 'haskell.packages.ghcjs.ghcWithPackages (pkgs: with pkgs; [ miso ])’
would give me a shell with the ghcjs compiler and the package miso, but that resulted in an error (after waiting for the result for quite some time and a lot of text scrolling by).I tried following guides and didn’t try to do anything especially crazy, but somehow I ended up fucking up my haskell build environment so much, that I couldn’t do anything Haskell-related anymore. Still don’t how I managed to do that.
I tried rolling things back through
nix-env -G 1
but that didn’t work. Somehow the only think that helped me was deleting everything nix-related and trying again. I then switched away from the unstable channel in the very beginning and now things seem to somewhat work, more or less.When I was 15 years younger I really enjoyed playing around with the configuration of my computer, trying different window managers and editors etc., but nowadays I have work I care about and limited time and I want my computer to just work and not get in the way. Nix really, really got in the way. It’s been incredibly frustrating the last few days, when I wanted to work on my project, but spent several days fighting with nix instead.
Sorry for the rant, again, I very much like the project and I really hope it succeeds, I just wanted to share my own experience with it, as a beginner.
But unfortunately *nix programs are not written to support this, so you see lots of hacks in Nix to get things to work.
Since GCC isn't really meant to work with headers spread across a varying set of directories, you end up with this wrapper for every GCC invocation: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-supp...
And this just doesn't sit well with me: https://github.com/NixOS/nixpkgs/blob/master/pkgs/top-level/...
However, I think several aspects of the Nix concept are highly novel and worth pursuing, and there’s no way to get there without large intermediary steps.
NixOS and GuixSD represent, to me, some of the most exciting OS research not aimed squarely at security. It’s difficult to fully appreciate until you’ve really exploited it well.
The hacks that are needed today, indeed, are a bit of a turn off, but I do still find a remarkable amount of stuff ends up working well in the model. As a personal example, NixOS not managing dotfiles feels like it would be a huge deal, but actually it isn’t as big of a deal because you can just manage system level configs; for example, my SwayWM config is stored at /etc/sway/config and so forth, and I can neatly provide Nix store paths in my config files through substitution, allowing me to keep my global namespace cleaner. (Various approaches for per user config can then be applied as needed, such as referencing global configs from dotfiles, or wrapper scripts that have logic.)
My opinion is that it’s unlikely NixOS or Nix are the stable, hermetic utopia we’re looking for, but they or a successor may very well become it, and the exploration done today is an important part of the necessary research. I’m already excited by things you can do today that are not well documented, like cross compiling to other platforms almost seamlessly (for example, MinGW has worked quite well in my experience.)
As a contributor to NixOS, I have barely noticed this. That said, I mostly apply contributions to applications, not to toolchains.
Hopefully one day Nix's approach will be popular enough that GCC or Clang will be changed so that the hacks aren't needed.
I agree that adoption would probably be larger if the language was not Nix or Scheme (Guix).
Guix System partly answers this by using Scheme, but ultimately Scheme is unpopular too.
A NixOS built on a no-side-effects JS/Python (e.g. Skylark, used in Bazel) would be possible.
The build output, a derivation, is just a data type (~ JSON object), and so interoperability between NixOS and something else is possible.
Replacing it with a general-purpose language is almost guaranteed to increase the cognitive load required to write a simple package or configure NixOS. This complain sounds a lot like "Why didn't you pick <my language>, which I already know?", to me. Nim, besides being newer than Nix (~2003), has support for metaprogramming, parellism features, OOP... which is all nice but it's far too much for a language intended for writing packages and configuration.
I agree that the documentation is a major problem when learning Nix/NixOS but the situation is improving. My recommendation is to start by reading the Nix pills[1], which are a great introduction to Nix but also develop into a detailed explanation of the inner machineries of Nix and Nixpkgs.
I think what the problem is is not the Nix language but its stdlib - nixpkgs. It is rapidly changing (as they figure out better ways of doing things) often breaks backward compatibility (for example not long ago they removed fetchGitPrivate and the built-in is not a drop in replacement), large parts of it aren't well documented, or even not at all (people often add great features, but forget to update manual and it still gets merged).
Initially this was the hardest part for me about Nix, and I guess it still is, but once I understood the structure of nixpkgs it no longer takes effort to find what I'm looking for (unfortunately many times I still have to look at the code, but now I can find it easily).
The thing is that this problem wouldn't been solved with different language like scheme or even Python. The language won't help much with learning the structure of nixpkgs and the conventions used. While Nix Pills cover some parts of it, there's so much more it could talk about.
BTW for those who are struggling with this. There is also very useful command to immediately find the derivation: nix edit <derivation> which should be emphasized more.
You might have said the same thing about the Reproducible Builds project [1] early on. It was a project inside Debian, that required a modified toolchain (gcc, autotools, etc.) on top of Debian Unstable; and many individual Debian packages needed patches as well.
Years later, these toolchain changes are now merged not only in main Debian, but also in other distributions and in upstream software.
The build that F-Droid executes comes in two phases: one to obtain source code, which then gets packaged, the second phase to execute the build. Note however that the build execution phase does have network access and many builds actually do use the network to download dependencies, so its certainly not as advanced as Debian. I'd put what F-Droid is doing to somewhere between Nix OS (which doesn't have source packages at all) and Debian (whose source packages are complete so that no internet is needed).
For F-Droid, one could maybe think about running build twice: first with internet enabled but a recording proxy in between, and second with internet disabled but that proxy replaying the recorded file. That file is then published with the sources. There are formats for this, e.g. warc. It would be a partial improvement although it might still download binaries etc instead of source code and patching the source code would be also hard (tools would have to be developed to do this), hurting the FLOSS spirit.
I also think that believing you have the source code to an app but being unable to build it because of missing, possibly proprietary dependencies is far more damaging to the FLOSS spirit than any amount of format difficulty.
I think it's pretty common that stuff is being downloaded during the build phase, mostly from java package hosts like mvn, jitpack, etc. There are checks in f-droid to ensure those hosts are on a whitelist of FLOSS-policy repos but the checks don't prevent any custom build logic of downloading stuff via http, cloning git repos, etc. Also while maven central does not, some of these hosts also allow takedowns of published artifacts, at least jitpack allows it and it's on the whitelist (also jitpack's policy isn't FLOSS only, only requiring that the package is on public github, which still allows for nonfree "source available" software AND jitpack doesn't have any policy about downloaded binaries during its build).
This is a problem on F-droid, as the app you're installing will not get updates, and are out-of-sync with upstream. I was pretty sure F-droid archived the source tarball, but i can't find it now.
Disappearing sources are also an issue, as it has every disadvantage proprietary software has, with none of the upsides. It's much harder to patch in case it is needed, for instance. And hard to tell if someone tampered with the binary archives, I guess? (IIRC, the hash in Nix is based on the configuration, not the resulting binary).
This is also something that bothers me. Even Gentoo (!) gives up on building some applications and just redistributes upstream binaries (eg. Cassandra or Kafka), because it's too hard to actually build them.
I mentioned this on the #nixos IRC channel, and they seem open to having a configuration variable to disable packages not built from source (like they currently do for non-free licenses [1]), there is just no one currently working on it.
[1] https://nixos.org/nixpkgs/manual/#sec-allow-unfree
> but really haven't considered to how to deal with the "disapearing sources" problem, including vanishing git repositories
Guix does [2], and Nix is working on it in a similar way.
[2] https://guix.gnu.org/blog/2019/connecting-reproducible-deplo...
Oh lord, but thanks for the info, would probably not have found it otherwise
I now use it for python, scala, emacs and basically wherever else I can get away with not using Homebrew. I share the config [1] between my work and personal machine. This works really well: it's just a git pull, and a `nix-env -iA nixpkgs.devEnv` and my environment is updated (and I can easily roll back to the previous state if something goes wrong). It does take a lot of up-front investment, learning a new language and paradigm, but once things are working they tend to stay working.
[1]: https://github.com/mjhoy/dotfiles/blob/master/nix/nixpkgs/co...
1) Package availability: this is by far the largest reason. I frequently need to use software or specific versions that are just not available and while I did create some packages myself it is just too much work when I need to get something done.
2) Language Documentation.
3) I still need to use cargo and pip anyway.
4) Even when packages were available they often lacked the configuration options I needed and I would have to fork and edit them anyway.
I do think Nix is a lot better than current systems though.
With direnv + lorri when you enter the directory, it is as if you enter virtualenv, your code behaves as if it is installed with pip -e, if you call nix build it takes care of all dependencies and the command created in bin/ behave like binaries, have all dependencies needed.
I plan to update nixpkgs code that processes setup.cfg and make this less trivial example when I find some time.
The Nix language didn't have good tutorials and I couldn't use any of my NPM skills with the Nix package manager.
I saw talk from one guy who wanted to make the Nix package manager use commands that were more like in other package managers.
Did any of this happen?
I really think NixOS and GuixSD are the next generation Linux distributions and want to use it.
I'm guessing this is about `nix` and `nix-env` having poor interfaces and lacking e.g `nix install` – those aren't _really_ meant to do package management, because it's an imperative approach akin to Apt. I haven't touched `nix-env` for actual package management in over a year now.
You should instead be writing your system-level package dependencies and services in your configuration.nix, your user-level package dependencies and services in home-manager's home.nix, and if you just need to use a package quickly, you should use `nix run nixpkgs.hello -c hello` or `nix-shell -p hello`, and if you're trying to set up a dev env for a project you should be using direnv or lorri. nix-env pollutes your environment and causes headaches when/if you add the same packages you have installed there to your declarative files.
>I couldn't use any of my NPM skills with the Nix package manager.
You can – look into direnv and lorri, they let you handle system-level dependencies while NPM handles its own libraries, on a per-project basis. This is IMO the best contemporary way to do a developer environment.
Yep, that happened, at least somewhat. Most things that you would want to do that used to be argument soup with `nix-env` now uses a program just called `nix`. For example, searching is now just `nix search <query>` instead of whatever the `nix-env` incantation was
I was in a similar boat for a long time and finally started dipping my toes in. FWIW, #guix on freenode is one of the best experiences I've had with friendly online communitities. The channel is fully of friendly and knowledgeable people.
The `info` docs for guix are also pretty darn good for getting you up to speed; however, if you start wanting you write your own packages, I've found that you really do need to consult the sources.
FWIW, I got a Guix System running as a Google Cloud instance. As far as I am aware, it's the first time this has been done. Feel free to email me if you want some details; I don't mind helping you set up an instance for you to play around with.
Getting started with Nix is easy but getting the hang of the Nix language isn't so much (despite having a reference manual.)
My best advice to get you started with the Nix language is looking at what's already available in <nixpkgs>[1].
Going fast-forward, my Docker image got a lot of unnecessary files in it (include headers, configuration files, /etc/passwd, /etc/group, etc.) I have to come back to it and see how I can improve this.
P.S. On the other hand, I succeeded creating a minimal Docker image using magicpak[2].
[1]: https://github.com/NixOS/nixpkgs/tree/master/pkgs/developmen... [2]: https://github.com/coord-e/magicpak
I think a winning approach would be to manage the OS using nix, but let the user do more imperative stuff in his home directory.
Here is an illustration of how one is supposed to use a package manager for a programming language (in this example npm) in Nixos: https://unix.stackexchange.com/a/381797
And here is an article about the hoops needed to run Steam games: https://nixos.wiki/wiki/Steam
The home-manager as far as I know is not official component, but a lot of people add it because they love the idea.
I think anyone who is interested in Nix should start with Nix Pills[1] they are concentrating on just nix and nixpkgs, but I think it is minimum getting started. Once you are familiar how to build nix derivations, adding custom components is not that hard.
While you could use nix-shell, it is IMO a dated and very manual way, preferably you'd use direnv or lorri to automatically load a default.nix or shell.nix from your project root directory where libraries have been specified in `buildInputs`.
I see on your “new site” blogpost you mention “This content is markdown rendered by Purescript.”
..have you considered doing a write up with more detailed information as to how your site is generated or a howto? I think many might be interested.
Thanks!
The SATA SSD is for Windows.
Do you not have your own specific requirements and use cases? It is better you do some research on your own end and learn to pick the parts that will best work for you.
Ryzen CPUs run hot, the stock cooler is garbage.
The tower is not silenced, and with the stock cooler you will have a lot of fan noise both from the CPU fan and chassis fans.
Ryzen 3900 is a much better choice than the 3600, especially for CPU intensive work like compilation.
The M2 disk is on the slow end.
The motherboard supports 128 GB RAM, but now all 4 DIMM sockets are used for 64 GB. You should go with 2x32 GB, in case you have a need for more RAM later on.
There are more issues here, but those are the worst.
BTW: Death metal is a particular genre, and Doom's soundtrack is not it. This crap is death metal: https://youtu.be/482tDopNzoc?t=69
Assuming the 2013 Mac Pro came out in 2013 I'd say that's at most 7 years.
By then you can see why when I gave them the choice of either upgrading to the latest version of macOS + H/W upgrade or just installing either Ubuntu/Fedora/etc on a second partition in which both are long winded processes the decision was obvious and clear to them.
They didn't care about either solution and rejected both suggestions to carry on with the status quo with great reason: 'If it ain't broke, don't fix it.' So until their favourite app requires a higher version and kills their productiviy, it is enough of a reason for them to upgrade it. A full blown switch to any Linux distro would be the worst decision for my friend, especially NixOS since even with this blogpost it gives little reason why they should bother switching.
Also great post and great blog <3
Same for the script parameters. I have absolutely no idea what this does
{ pkgs ? import <nixpkgs> { } }:
Why not: function main(pkgs: Package = nixpkgs) {
}
Or something like that.My second issue is that the files clearly aren't machine-editable. There's no sensible way to make a GUI that can edit your hostname if the hostname is defined in some Turing complete functional program.
But it definitely beats the design of any other package manager.
I don't disagree with the overall argument you are making however on this point alone, they aren't meant to be machine-editable. They are functions, they take arguments. So you can make your module or system configuration or whatever, have unassigned variables and then have your function take them as parameters. Your GUI can invoke this function with arguments from the user input.
As for not being machine-editable, the nix language has a module system and it's easy to format a file with something that's whatever shape you want and have that machine-editable. Or use any other format and fromJSON etc. functions.
function main(pkgs: Map String Package = (import(sys.path("nixpkgs"))({}))){ }
I'm not sure if it's better at this point...
https://github.com/NixOS/nixpkgs/blob/2cd8c35c1fdfdb773df7ec...
I am pretty sure that instantiating a derivation probably requires more attributes. But in the end they are just attribute sets (which is one of the types in Nix besides strings, lists, etc.).
It being so simple is why the whole system works.
What do you mean by this? Nix is a Turing-complete language.
It's not really weird when you know a functional language like Haskell or OCaml. My experience was actually the opposite: being a functional language, Nix's syntax was so simple that it took me only a few minutes to grasp most of it.
But if you don't have some FP experience under your belt, both the syntax and commonly-used concepts are strange (e.g. fixed points).
For me the learning curve was knowing what extra functions/functionality is provided by nixpkgs, which lacks quite a lot of documentation and discoverability. I found out about a lot of handy functions and techniques while reading derivations.
I should have kept track of the issues while I was learning Nix/nixpkgs. But at that point I was still determining "do I want this?"
For the times I need to do this, I define the values in a JSON file, which can be parsed by Nix's builtins.fromJSON into a Nix datatype.
{
"url": "https://github.com/nixos/nixpkgs-channels.git",
"rev": "ea553d8c67c6a718448da50826ff5b6916dc9c59",
"date": "2020-02-02T15:39:15+01:00",
"sha256": "0g9smv36sk42rfyzi8wyq2wl11c5l0qaldij1zjdj60s57cl3wgj",
"fetchSubmodules": false
}
Then, in nixpkgs.nix have let
bootstrap = import <nixpkgs> { };
nixpkgs-pin = builtins.fromJSON (builtins.readFile ./nixpkgs.json);
nixpkgs = bootstrap.fetchFromGitHub {
owner = "NixOS";
repo = "nixpkgs";
inherit (nixpkgs-pin) rev sha256;
};
in
import nixpkgsThis program has a CLI mode for setting up keys and buckets, which I run locally, and it writes to backup-metadata.json .
So my workflow for adding a new directory to my system is:
1. Run CLI tool to create a new bucket, new API key with access to the bucket (with just the permissions it needs), and new encryption key. This writes to my backup-metadata.json file locally.
2. write some NixOS along the lines of:
let
metadata = (builtins.fromJSON "../backup-metadata.json").git;
in {
backup = {
git = {
path = "/var/lib/git-repositories";
frequency = "hourly";
bucket = metadata.bucket;
key = metadata.key;
apiKey = metadata.apiKey;
};
};
}
3. Hit deploy. This starts the backups, and some monitoring to check the cloud storage is being regularly written to.The implementation of "backup" is private, but reuses parts of upstream NixOS (systemd.timer, Prometheus, ...)
> the Nix language is just so damn weird... Why didn't they use a [familiar] syntax ...
You wouldn't have to parse data from some other representation if Nix lang was less weird, eh?
I was replying to OP's second point about Nix language not being machine-editable.
Even if Nix was written in Python rather than Nix language, it still wouldn't be machine editable.
The solution in both cases is to use a simple format that is machine editable, e.g. JSON.
But you also don't need to!
NixOS has a module system, with override/priority mechanics; so your GUI tool could just generate its own Nix file with its own settings, totally ignoring the system-wide settings, and then all you need to do is apply that generated configuration file in your imports; the module priority system does the rest.
Any other changes are not recommend, unless it is home directory and you don't use home-manager.
At that point you would correctly wonder why would you use ansible it is like running ansible to run saltstack.
NixOS essentially makes these tools redundant. It is also more powerful. Imagine that you wanted to for example use libressl instead of openssl with python, because it is more secure, or maybe introduce your custom patch put use different configure option. With other tools like ansible, you would start with building custom package(s), then place that package in repo like artifactory. Then write your ansible definitions, you would add artifactory to the OS uninstall the old package install a new one (also worry that replacing your Python package with a custom version could break other stuff, you might end up installing your Python under a different path). If you want to revert it, removing these steps is not enough, you would need to write steps that would revert it.
In Nix, you make change to the disk that is being installed. If nix won't find precompiled package in its repo it will automatically pull compiler and compile it. If you configure caching after finishing it it would populate the cache so other machines no longer would need to compile it. And if something else is using old Python version it won't be affected at all, it will continue using what it was using. If you remove your change nix will restore back the previous state, no need writing rules about restoring it.
Another killer feature is that nix will never leave your packages in half state, everything is atomic. So if you incorporate many changes you either get all or nothing. It also guarantees that all machines using particular configuration are identical, I often seen rules working on one machine and not working in another (different OS version, maybe previous state was not applied everywhere or somebody made changes by hand).
I suppose one could use Nix to configure computers that are not running NixOS? Switching all of my Ansible playbooks to the Nix package manager is non-trivial, but perhaps less effort than changing every OS at the same time?
But can you use Nix to interact with the cloud? I currently use Ansible to spin up virtual servers on Linode using their web API, for example, and I expect to have to interact with AWS or Google Cloud in the near future.
NixOS was fine. Standard systemd (bleah!) commands to enable and then start sshd. (Because "enabling" and "starting" are two different things, yeah?)
Guix required editing a file and rebuilding the OS. This wasn't well documented, and they had forgotten to include the file in the VM image. (The manual says edit /etc/config.scm (IIRC) but it's not there. There's a bug open for it.) I had to find a copy of the VM config and hack it up to work, but after that everything went smoothly. (Can you taste the irony on that last sentence? I am being sardonic. The experience was hugely demotivating.)
Anyhoo, FWIW, Nix seems great but I don't like the language (and I don't like systemd, and no, I don't want to talk about it.) Guix seems like it will approach being a new kind of Lisp Machine, Guile lisp is fine, and integrated into other parts of the OS. (Shepard seems fine.) But having to edit a file and rebuild the OS to get ssh access was gnarly.
All in all, something like NixOS or Guix seems to me to be the way of the future. Other build/package managers seem just stupid and dangerous in comparison (like operating a chainsaw without kevlar chaps. I have two legs thanks to kevlar chaps. Always wear your chaps kids!)
> * Nix goes a step further by disallowing package* > * builds to access the internet. This allows Nix* > * packages to be a lot more reproducible;*
and
> * The src attribute tells Nix where the source * > * code of the package is stored. Sometimes this* > * can be a URL to a compressed archive on the* > * internet,
The second paragraph talks about fetching sources which nix does before build starts, each source is required to be provided with hash, this ensures that it is an identical file that author of the derivation used.
The biggest problem on my version I think is that links aren't obvious enough in dark mode, but I like the links used here so I'll look into that.
[1]: https://noahloomans.com/tutorials/makefile/ (The contents of this page is intended for the other students at my college and probably doesn't make a lot of sense standalone)
Because of some config files in /etc influencing it indirectly.
So pograms in nixos influence each other via global configs, they are not isolated.
I was unabne to fix that.
So a simple apt get install package is all I need.
This looks like having to write packages again and that’s the very reason I use a Debian based distribution is for apt
NixOS also has package maintainers, which the author of this blog post relies on (see "nixos.graphviz").
Traditional distributions also allow you to package your own software.
The difference between a traditional distribution and NixOS is that NixOS makes packaging your own software (and config) easily and safely enough to treat as first-class citizens along with the distro's own packages. So much so that I don't think of NixOS packages as "packages". Rather, I just see them as config/code.
Compare my super-optimised dockerfile results:
$ docker images | grep xena xena/christinewebsite latest eb8c27a1a5d2 12 seconds ago 121MB
To the naiive nix results:
$ docker images | grep xena xena/christinewebsite latest b087ad7fb924 50 years ago 102MB
This image ends up only including my blog (statically compiled), ca certificates (because of the patreon integration), time zone data files (because of the go time package), iana port numbers (something to do with the go net package) and mailcap (for some reason). It's puny!
couldn't you simply do a multi-stage docker-image (in the not-nix situation),where you just copy over the go binary into the final docker-image, and add the needed files?
In theory I could do the multi-stage docker approach to get an as-tiny-as-possible setup (and I actually do this: https://github.com/Xe/site/blob/master/Dockerfile) but that won't cover ca-certificates generically.
I’m running Linux and pacman/yay are great but if something is screwed up I miss being able to run brew doctor to figure out what’s wrong or add a tap for some weird thing here or there.
I know I’ll get crucified for saying it but usability counts for a lot and apt, dpkg, yum, dnf, and yes, even nix suck. All the correctness and perfection don’t matter if nobody uses or wants to use your software.
I've had innocuous-seeming brew commands foul up my working environment. I don't think Nix would do that in the same way.
Specifically, updating a package in Homebrew can have unexpected knock-on effects due to updating dependencies. Left my working environment badly hosed at one point last year.
Nix's design should ensure that all such updates leave everything else stable, as I understand it.
I've been tempted to try it or Guix for years - I was delighted when I discovered Nix existed.
I'd been thinking about the problems with existing package managers for years, and both Nix and Guix have most of what I felt was missing from the existing tools, along with some other really cool attributes I hadn't thought of at all.
It does take you a while to understand everything about it but that's always the case with power tools. You'll likely not need to dive into the guts of your package manager on day one anyways.
Oh and you can of course use "man" to read the manual pages for most apt programs if you want more in-depth info.
/nix/store/c99n4ixraigf4jb0jfjxbkzicd79scpj-gruvbox-css.drv
should be
/nix/store/gruvbox-css-c99n4ixraigf4jb0jfjxbkzicd79scpj.drv
$ docker run --rm --name temp -it nixos/nix
c343661ad923:/# nix search graphviz
warning: using cached results; pass '-u' to update the cache
error: no results for the given search term(s)!
c343661ad923:/# nix search -u graphviz
error: no results for the given search term(s)!
Well... that's not off to a good start. I don't mind learning something new, but nix just seems super convoluted.In many other distros the package manager makes it pretty easy to get a graphical environment running or even to install and configure software. Not nix.
Nix is far from easy to use or install https://invidio.us/watch?v=QujRHErFG4w
The top complaints I've seen in this comment section so far are about the Nix expression language. It's not appealing, hard to learn, weird, etc. Okay, good. If learning a single simple DSL is completely off-putting, then we should probably keep the DSL for a while, since it seems to be effective at weeding out folks who aren't interested in learning about the theory of package management, while allowing the rest of us to get things done.
The next top complaints I've seen are about how nixpkgs is hacky, lacking, or doesn't well-support traditional UNIX tools. Well, to the extent that we can force traditional UNIX tools to respect package-capability discipline, we're doing quite well. According to Repology [0][1], nixpkgs is amongst the top 5 repositories for number of packages, number of maintainers, number of fresh packages, and percentage of up-to-date packages.
Seriously, before you downvote or reply, stop and look at [1]. Look at how nixpkgs is literally off the charts compared to almost any other distro. The only close contender is AUR, which doesn't have the reproducibility or less-insecure build model of Nix.