Kan.bn – An open-source alterative to Trello (github.com)
105 points by henryball 4h ago 71 comments
A new generation of Tailscale access controls (tailscale.com)
211 points by ingve 3d ago 55 comments
How I like to install NixOS (declaratively)
150 secure 122 6/1/2025, 6:23:50 AM michael.stapelberg.ch ↗
I figured what the hell, let's try NixOS and see if I can set it up declaratively. At least that way if it fails, I have documentation about what exactly is failing.
I discovered the audio packages I needed easily enough. But things weren't great, there was occasional noticeable lag on the mic and midi devices. Ok, let's try to compile a realtime linux kernel... Wait there's an entire project dedicated to Nix audio setup! (https://github.com/musnix/musnix) After a few minutes integrating with my config, and about an hour to compile the kernel. Rebooted and bam. It's almost like working with analog in terms of perceivable lag.
I know this says more about Musnix than Nix, but I think it highlights the advantages of configuring your system with a real programming language. All the "audio stuff" was able to fit behind a well-designed abstraction barrier.
Going back to a "do this, now do this" tutorial feels like the dark ages. The only thing keeping me from going all-in on Nix is that it's package management strategy starts bleeding into your software project's dependency management. This is a huge problem IMO, I can't run C/C++ or Python projects the "old way" and no one is willing to upend their build system and lock it into nix. Some languages work great and allow a clean barrier between system<>app. I use Clojure, Rust, Gleam, Go, Lua on nix without any issues, it does seem to be the C/C++ ecosystem and dynamic linked shared libraries that are the problem.
For Python I use uv to download & set up Python binaries outside Nix. To make them work I enabled nix-ld in my Nix config, so there's a default linker & libc they can access. Works well so far.
Musnix looks really interesting. My whole audio setup looks like this in my nixconfig:
This works great for my workflow of using headphones + BT 100% of the time, but weirdly it almost never works for the built-in speakers on my framework. I might try musnix if that ever bothers me, but it's actually kind of a feature for me since my laptop can never just start blaring whatever I was watching / listening to into publicI just have AI do it. Any of the coding assistants with terminal access can write and test flakes for you.
I also went through a phase where I had AI write a lot of simpler flakes, but they turned out surprisingly different from each other, enough so that I wasn't able to learn a pattern as a base to grok what was happening. At some point I'll try again from first principles, but for some reason the AI flakes hindered more than helping
Depending on your individual use case you might find it sufficient to simply work on and compile software inside of Distrobox. It integrates nicely enough with the host system I think.
Personally, I usually do a small bit of hackery to get a good dev environment for C++ projects, using a combination of flakes and envrc. It's not exactly elegant, but you can re-use the Nixpkgs derivation for the actual dev shell. If you need to, you can even reuse the Nix patchPhase from the real derivation to apply NixOS-specific patches to your local tree temporarily.
The fact that it's possible to get a decent experience with not really that much effort kind of signals to me that it probably could be a lot better. On the other hand, maybe in a better Nix world, Nix could become even more integrated into both the dev and build process: with dynamic derivations the build process could be broken up into many smaller derivations and give Bazel-like behavior.
One thing I really enjoy about Nix is how easy it is to have different shells to use for different things without needing to pollute the system with tons of packages you needed for only one thing, but on the other hand the rest of the world doesn't integrate perfectly with this. For example, a lot of GUI text editors manage their own processes, so you can't just start a new window already inside of a shell. For VS Code derivatives the envrc extension kind of works, but it's a bit of a hack. A good improvement would be developer tools explicitly supporting this model, and as Nix seems positioned to continue to be gradually more relevant over time, I am hopeful it will become important enough for tools like VS Code to consider.
I have had a decent time, though. I have a mostly automated approach to getting working clangd and incremental compilation with pretty much any project, with just a little bit of mucking about with boilerplate.
I think it's a testament to Nix's promise. Abstraction with capital A!
Bazel for example builds everything in a well-contained sandbox and it all works, but only for the C/C++ libraries it builds natively. The magic ingredient is RPATH, but most Makefiles do not set it. However, one can add an extra build step with patchelf and inject an RPATH.
Have you considered buying a MacBook and valuing your free time more?
I had been incrementally building this complex workflow using mkosi. At some point I sat down with a pencil and asked myself "ok, what am I building here, what's the ideal endgame?" I sketched out the system I wanted and pondered it for a bit... And then went "wait, have I just described NixOS?" And yeah basically it's exactly what I wanted and more.
Funnily enough, this article is _exactly_ what I need as I haven't exactly figured out the best way to install NixOS on a totally blank machine. (So far I have been muddling through what's described in the "Manual installation" section and, yeah it sucks). The exception is for Raspberry Pi where it's straightforward to just build an SD card image from a flake.
I had _guessed_ that something like the "Building your own installer" section would work, but because of the nature of Nix I never really feel 100% confident that something is gonna work as I hope until I physically try it. Usually it does. But still, this is a very big downside of Nix!
You need to then have a flake which defines a "package" like this: https://github.com/jhvst/nix-config/blob/main/flake.nix#L117...
Now you can run 'nix build .#starlabs' which will create you the files needed for kexec / PXE booting.
You can also write tests that these images actually boot ok: https://discourse.nixos.org/t/nixostest-with-flake-configura...
I started working on this stuff because I needed to somehow reliably update my homeserver. I live abroad 50 weeks a year, so I needed something reliable because I can't assume I have physical access to the computer. Even when the BMC firmware got screwed by ASRock motherboard firmware, I didn't need to sweat.
Now for the shameless plug: my company created a PXE server module which also supports flakes that assumes this ephemeral setup. It's described in here: https://github.com/majbacka-labs/nixos.fi
At $work we have insane platforms that are extremely hostile to platform development but they do support a (obviously annoyingly custom and limited) PXE-like thing and I'm hoping I can boot NixOS via that and just never even touch the disk (which is full of insane custom $work platform bullshit).
I ended up in the same situation too, but discovered relatively quickly that NixOS makes it really easy to build clean VMs from your config that you can run and test against, then when validated, you apply the configuration to the actual hardware.
I'm doing this for all my servers managed with NixOS right now, and managed to prevent multiple issues being deployed, including something that would prevent a clean boot and since the host is headless, would have required me to connect monitor and keyboard in order to recover.
Really glad NixOS is setup the way it is, although you're right the learning curve is rough. At least I can easily re-install my infrastructure really trivially, which helps me sleep at night.
I can write a config, very quickly check it seems correct on a QEMU guest, and then deploy "the same" config to a physical host (slower to boot, harder to debug, annoying to power cycle) and be highly confident it's gonna behave like the VM did. This is incredibly valuable!
But by "hard to know if it's gonna work" I was talking more about architecture-level concerns. Not "is my Nix code correct" but "is this thing I'm envisaging a thing that the ecosystem supports?" I usually just have to sit down and try coding it up, and there's always an element of uncertainty about whether I'll succeed. Whereas if I sit down to get something done in Ansible I don't really have any such doubts. (But the result will be dramatically worse).
This boots directly into the kernel with QEMU's '-kernel' option, and it mounts the host Nix store into the guest via Plan 9 FS. So there is some significant difference vs a full system, e.g. it's not possible to nixos-rebuild the VM. But if you're just testing high-level stuff it's totally fine.
Then there's also a .vmWithBootloader variant which behaves a bit more like a physical machine, IIUC it builds a disk image and boots it via Nixos' actual bootloader.
Should probably just be using a persistent but this is some pretty heterogenous hardware and…it works
One of the most underrated features of Nix imo is the testing story. You absolutely can be confident that something will work!
https://nixcademy.com/posts/nixos-integration-tests/
It's usually pretty easy to try stuff and I really like the way once you have learned something, you can't ever really forget it because everything is code. I know lots of things say "it's config-as-code!" but very few do hermeticity as well as Nix. In that regard it has some of the benefits of monorepo life, without needing an actual monorepo.
Would it be possible to automatically translate all Nix build scripts into a language that is more ergonomic and fun to work with?
This property requires a pure language with no side-effects. Nix was not completely pure (e.g. `currentSystem` and `getEnv` were impure), but Flakes close this gap.
You could of course generate Nix from another language (or .drvs), but you probably want to keep the same guarantees.
Besides that, Nix itself is actually a pretty simple functional programming language. The difficulty is probably for most people knowing/understanding everything that is built on top of it: fixed points, overlays, nixpkgs.lib, stdenv, overriding, hooks, all the programming-language specific builders, etc. It is a pretty big ecosystem and a lot of it is not very well documented.
That said, when I started using nixpkgs/NixOS in 2018, it was the easiest package ecosystem to start contributing too. RPM .spec and Debian rules files are quite archaic, nixpkgs was really a breath of fresh air. It's just that because NixOS is very principled and does not follow HFS, you have to become a packager yourself much sooner than most other distributions to get stuff working. (Though this changed a bit with nix-ld.)
But also the fundamental model of Nix is incompatible with anything that can be translated to a simple Bash script. If you could translate it to Bash I wouldn't wanna use it
But yeah the difficulty is the ecosystem. "Nix" is a lot of things and all of those things are individually extremely flexible. This adds up to a system that can do almost anything and that inevitably makes it kinda hard to break into. The docs are honestly better than I could do but documenting this system just seems unbelievably hard to do well.
See things like Python packaging, how to make ISOs/installers/containers, how to override a scope, how to maintain a dev environment, how to do package testing, how to set up your own CI with caching and binary delivery, etc.
I clone or save every public repo or article or whatnot i find that helps me or seems interesting.
These two examples come to mind: the page that made what the config/options system really is [0], and the post that really drive home to me it’s all just configs! A config language all the way down! [1]
[0] https://nlewo.github.io/nixos-manual-sphinx/development/repl...
[1] https://astrid.tech/2022/11/03/0/overlay-nixpkgs-pr/
After some discussion and iteration with Copilot I had a derivation that pulls the CSI protobuf spec and dumps python code and types into something LARPing as a real python library.
A few hours later I implemented my own CSI driver using these things.
Github crawls nixpkgs and everyone and their aunt have public nixos configs, the LLM is good at Nix.
That all nix build instructions are bash isn't the worst, and I hate bash. You can always create a python script to call in a derivation if you need.
I think it helps to have comments like
# AN AI WROTE THIS BIT, REUSE WITH CAUTION
It's a difficult problem domain that isn't solved with syntax sugar.
Try out building an installer and run it in a VM, it only takes a few minutes!
It's huge. I tried learning and exploring Nix Darwin. Went through at least half a dozen blog posts with "step by step" instructions. All different. All had some fatal error at some point even on a new install of macOS that was from moderate to impossible to find coherent help on.
Then I found NixOS, which is like Ansible, but better, because Ansible only adds information to a system, but NixOS also ensures that anything that is not declared is removed as well.
After three weeks, I realized that the effort to declaratively (or automate an imperstively) install the OS is such a lot of work that does not pay off if you're not going to install multiple systems each week or month.
How many commands does it take to actually install NixOS? You partition the disk which take 3 commands. Then you format it, which takes 3 commands. Then you mount the disks, which takes 3 commands. Then you install it, download your configuration and apply it, which is another 2-3 commands.
It takes 5 minutes vs whatever effort you put into creating a declarative installer and keeping that up to date. I also had to think of the time it would cost me to actually figure out HOW a declarative installation would work and the tools I would require. I reckon that the first 24 system would essentially be free (opposed to the 2 hours or so it would cost me to figure out declarative OS installations).
I decided that for me, it is not worth it, although I am the type of personality that just hates not automating things.
But for setting up appliances, test machines, it's perfect. If I ran cloud VMs I'd also consider it for setting those up.
With declarative, you frontload an enormous amount of effort:
- You have to learn your declarative framework
- Then you have to slowly build your configuration base, or copy someone else's and figure out why they did what.
- Then you have to figure out workarounds for things that aren't natively managed declaratively.
- Then you start writing your own little helper functions and modularize things. At this point, it starts getting very smooth.
From there on, adding another package or another machine is very very easy, basically adding a few lines of code. And now your system is mostly reproducible, putting you far ahead of an imperative configuration.
Compared to that, doing it imperatively you can just sort of do your thing and roll with it. This let's you do whatever you aim to achieve very quickly, but as time goes on you have to juggle so many balls in terms of tracking and remembering what you configured / what state your config is in that it quickly becomes impossible.
Declarative OS management really sticks once you accept that the first few weeks are gonna suck and the first few months are still gonna have friction. But once you get over the hump, the rewards are there to reap.
> You have to learn your declarative framework
Could the framework be simplified so that you don't need to learn all of it but rather just a small part when you're only doing basic stuff?
> Then you have to slowly build your configuration base, or copy someone else's and figure out why they did what.
Couldn't pre-made configurations be made available? For example in docker it's very easy to base your image on another image from an online registry.
> Then you have to figure out workarounds for things that aren't natively managed declaratively.
This is unfortunately a consequence of the current ecosystem essentially being imperative-first, but I wouldn't consider it an intrinsic limitation of declarative systems.
> Then you start writing your own little helper functions and modularize things. At this point, it starts getting very smooth.
This is probably the part where you really need to spend a lot of effort, but I wonder if it's possible to reduce the need for these helper functions and modularization or provide them by default for at least most common cases. Then most wouldn't need to spend the effort for them because they either already exist or there would be no need for them.
If you just want to do 'basic stuff', declarative OS management has way too much overhead.
> Couldn't pre-made configurations be made available? For example in docker it's very easy to base your image on another image from an online registry.
Nix really is as a configuration of configurations (called modules). So yes. But no one runs the exact same OS setup or container, so eventually you will need to modify it to your specification.
> This is probably the part where you really need to spend a lot of effort, but I wonder if it's possible to reduce the need for these helper functions and modularization or provide them by default for at least most common cases
Nix already has premade helper functions for common cases via 'builtins'. As far as modularization goes, at some point you are going to want to do something custom, and if you want to apply that to multiple systems then making it a module just makes sense.
Only if you don't change your mind and do not decide to try out that new cool distro that just came out 6 months later.
I like declarative management but so far I have sticked to puppet for that. Sure like with ansible puppet needs to be installed first but on the other hand you can quite easily convert/reuse a config for say debian, to ubuntu, arch or fedora. The main differences are usually package names.
I agree that through the lens of “how much time do you save?”, automating a NixOS installation is not worth it. As you describe, it’s just a few interactive commands in the upstream installer.
But from the perspective of “how much effort is it to spin up a new VM for this new project / task?”, spending the extra few minutes on building the fully automated installation path is well worth it. Also consider the perspective of “how many steps does it take to recover this VM in a disaster scenario?”, where reducing the manual steps to a minimum is very helpful.
BTW, the maintenance of the installer is virtually free: The configuration I show is the configuration I use in NixOS as well, so that needs to be updated anyway. Aside from that, to rebase my installer from NixOS 24.11 to NixOS 25.05, I just changed a number. When setting up a new machine, I can either download the upstream installer and write it to a USB stick, or I can change a number, rebuild (< 2 minutes) and write to a USB stick. Really not much difference.
With Ansible i get repeatable setup of my whole system. I can setup and install every program, configure it (dotfiles), setup services automatically and users and i have vault to easily encrypt secrets end embed them or template things out which is much nicer than using nix. I run a playbook and set everything up in 15 mins and the most "annoying" thing i have to do is basically log into few websites that i use daily.
As far as your overall problem goes however, there's likely something else at play. You've nerd sniped me now, so I'll spend some time when I have some next to try to build a test harness for your exact config.
It seems for the author, the custom installer is mainly used for accepting user SSH public key, terminfo, and maybe also locale.
Almost none of the packages the author listed get used, including zsh. Since NixOS is installed via nixos-anywhere, it runs a bash script to do everything, and all the script's dependencies will be pulled by nix.
For people who don't want to build a custom installer, or their cloud environment doesn't allow one, you can simply host a script somewhere and download and run it on the remote machine to add your SSH public key and other customizations, including partitioning the disk.
Note that the author used disko to partition the disk declaratively. Disko won't work for a machine with very limited ram, because disko runs in the installer, and needs to install tools to the ram to do the partition.
I wrote a nix configuration library[1] that also does NixOS installation (uses nixes-anywhere under the hood), where you can choose between using disko, a default script[2] that handles 90% of the use cases (using only the default tools available on a vanilla NixOS installer, so nothing gets installed to the ram), or your own script.
[1] https://github.com/hgl/nixverse
[2] https://github.com/hgl/nixverse/blob/main/load/partitionScri...
Just to clarify: the point of having packages like lshw and zsh available is not for the case of performing the automated installation (where, yes, they are not used), but for the case where I want to interactively poke around in a booted installer to inspect the target system.
For git, you commented "for checking out github.com/stapelberg/configfiles". I wonder if you sometimes install NixOS locally from the installer? If so, I can understand having those packages around can be very useful.
Later, I refactored this config snippet into a Flake that I include: https://github.com/stapelberg/nix/ …but that’s for a follow-up blog post :)
This is only true if you use the disko-install tool, which is a horrible footgun[^1]. The safest approach is to just use the default disko command, then nixos-install.
[^1]: https://github.com/nix-community/disko/issues/947
However, since we are talking about installing NixOS declaratively, and it's done through nixos-anywhere, which will install it[0] to the ram unfortunately.
[0]: https://github.com/nix-community/nixos-anywhere/blob/abb0d72...
Side note wrt tailscale - you should be able to auth without manual registration. Two choices: 1. Make a reusable key that grants the ACL you want to give, store it somewhere secure on your provisioner, then “ssh user@tag sudo tailscale up —-auth-key=$key” to deploy. 2. Make a new tag for “disabled-machine” or similar, locked down with no access. Embed that key in your ISO and use whatever mechanism you have to start it up on boot.
Either way you no longer have to copy paste the setup link to your browser, and the machine always starts off with the ACL tags you want (setting an ACL tag automatically disables expiration btw - no need to do both).
2 is likely tricky to do securely, so take care. :)
What is lustrating? Basically, you run the NixOS installation tools on an existing Linux installation (install the tools with the Nix package manager). The installer wipes out anything on / that doesn't belong, with a few exceptions, including /home and anything listed in /etc/NIXOS_LUSTRATE, a file you create as part of the installation steps.
[0]: https://nixos.org/manual/nixos/stable/#sec-installing-from-o...
Learning this also complicates things as I am feeling overwhelmed with all the things needed for simple configuration structures instead of starting out with a simple program.
Not a controversial opinion even in the nix community as far as I know.
I really like the Nix model of derivations and approach to deterministic builds. It's the language IMO that prevents it from getting mainstream adoption.
I think they would be best served by picking a subset of an FP language that already has good ergonomics and tooling.
https://snix.dev/
I build the ISO via a Github action as well. The biggest pain point is adding / removing disks after initial install, which I do imperatively (but still disko for mounting / fstab equivalent)
When I see comments like this about NixOS I feel like I must have been using a different breed of distro before and switched to a different NixOS than you did.
My experience has been that other distros—even the supposedly stable ones like Debian—are disasters waiting to happen with no clear way of understanding what goes wrong when you do an upgrade and it breaks. Instead of one config file to troubleshoot I have hundreds of config files that I don't even know about that might be at fault. Or it could be not even a config file, it could be that there's a version mismatch that can't be resolved.
For me NixOS's config file is a breath of fresh air. If something on my system breaks it's because I made a change to that single config file. If something on my system isn't working yet it's fixable in that single config file.
The system is far from perfect, but it's much better than the black magic that other distros lean on.
It's a great interface for the same dataset. There's nothing wrong with that.
Is there an guide for it?
[0] https://wiki.nixos.org/wiki/Podman
I see a resultant fork exists in auxolotl.
The other politically inspired fork (Lix) is moving very slowly for a project that seeks to replace nixpkgs outright
99% of the actual development in the ecosystem is proceeding like normal
I used to think that you don’t need Nix to get most of the benefits that Nix/NixOS are known for. And to a certain extent, that’s true — you can achieve much in other scenarios. But by now, I think the reason why Nix/NixOS work well and deliver these powerful abstractions is because they are Nix all the way down, giving you an unparalleled level of integration/reach for your declarative layer.
Ansible at least doesn't lie to you about this: it provides the tools to be declarative, but doesn't pretend to understand your problems better then you.
I don’t know who todsacerdoti is, but looking at their submission history, it looks like this account automatically cross-posts from other sites (maybe lobsters?)
That's a pretty serious allegation to make without evidence.
Luckily I have some evidence right here:
I checked afterwards, most of those articles have different authors on Lobsters, so it doesn't seem to be one person just funding cool stuff and submitting to both.edit: some stats -
@dang - I know the anti-spam countermeasures are secret, and that there may be good reasons for cross-posting, but perhaps this might be a good thing to check for abuse of (even as a cronjob).In fact, IIRC I asked him to stop at one point (which he was totally fine with) and then changed my mind after looking closer, because many of these articles are so good for HN. Of course, when the author of an article also posts it (as was the case with the OP), or when some less prolific submitter posts it, then we want that person's post to "win", but this doesn't always happen.
I wonder if we could write some code to catch this when it does happen, and then maybe we could have the best of both worlds or at least a chunk of it.
I did something pretty lazy by taking the poster's recent submissions, seeing if they were posted to lobste.rs earlier, and how often.
Here's an slightly updated version of the stochastic parrrot excrement code I gave to a sibling thread: https://pastebin.com/gFgBVkC4
Fwiw you're giving no credence to the theory espoused here that you don't actually read every post.
Bots are an incarnation of coordinated unauthentic behavior. You could instead have meat puppets typing off a script that is auto-generated and known to be unique output to the best of anyone's or anything's ability, and that wouldn't make the output any more authentic.
The intent of your transmission matters, as well as the effects of it on the listener and the wider broadcast environment. Violate norms of airspace usage at your own discretion (and peril).
No comments yet
For real though he does have a habit of showing up when mentioned even if there isn't an real @mention mechanism.
[0] https://en.wikipedia.org/wiki/James_%22Kibo%22_Parry
https://pastebin.com/baF6RKV4
This whole situation feels like fake users on digg/reddit but on HN. What a sham. It’s all the more sad when the actual creator gets scooped/buried. Instead of moving comments and discussion to the actual OP’s thread, we favor the bot user.
As dang wrote in reply you, and echoing conversations I have had with him:
https://news.ycombinator.com/item?id=44152290
> Of course, when the author of an article also posts it (as was the case with the OP), or when some less prolific submitter posts it, then we want that person's post to "win", but this doesn't always happen.
> I wonder if we could write some code to catch this when it does happen, and then maybe we could have the best of both worlds or at least a chunk of it.
Why is anyone worried about the best of both worlds, if the worst of both worlds isn’t willing to be addressed vigorously, because that’s the reality we already find ourselves in?
If these posts are somehow better for HN than then alternative, then we should have some idea of what success or the ideal case looks like, or talk of what could be done to solve the negative externalities rings hollow when it still isn’t done years later, as this scripted behavior has been running for years now. Karma sharing still is DOA, and would be much less necessary to begin with if we didn’t have what are essentially karma front runners and karma police on behalf of capital (not directed at dang personally or HN specifically, but HN is backed by capital so let’s not beat around the bush).
It’s a matter of priorities, and how they translate into success of the community. When individuals are favored when doing things that would be disallowed if they became a norm, at the harm of the users doing the work, on a site run by capital investors, it becomes a bit silly to steelman the case for HN, but I hope you can see I’m doing my best here.
If HN is better with the posts than without, then allow users to mark their accounts or posts as bots, like on Twitter/X? Perhaps such markings should be mandatory under the guidelines? I’m sure there are other ways to balance the incentives here, and I’m sure others also have ideas. The status quo on HN apparently of allowing special good boy users to farm karma isn’t a good result when it leaves original content posted by the creator left out in the cold.
Generated comments are already against HN guidelines, and generated posts ought to be as well, for the same reasons. I come to HN to see posts made by humans, not bots. I can go literally anywhere else for bot slop. This situation is untenable.
If the intent is to allow the very large and very obvious karma farming that we know about to prevent the greater ill of karma farming we don’t know about, then dang should just come out and say that.
Since by your own admission and interaction with the user who uses scripts to make posts to HN, who made the post that was merged here, you have “seen” this before and will “see” it again. HN users deserve to read only posts by human users. It’s a stated goal of the site, as you yourself have said that generated comments are against HN guidelines. So too should generated posts be against HN guidelines. Otherwise, HN favors whoever intentionally manipulates the site and user base best, as by tacitly and then explicitly allowing an outsize bot contributor, you’ve made a mockery of the genuine human efforts I personally make to surface good posts to HN. How do you square that circle?
https://news.ycombinator.com/item?id=43249197