Persistent packages on Steam Deck using Nix
chrastecky.dev
chrastecky.dev
https://forum.elivelinux.org/t/how-to-install-nix-packages-o...
I'm giving it a go now in the easily undoable single-user "no-daemon" mode.
Super excited how approachable this makes Nix, I've put this off for many years due to what turned out to be an incorrect assumption about the level of commitment!
There is nixgl which you can wrap around any executable to make it work and it's got support in home-manager (https://nix-community.github.io/home-manager/options.xhtml#o...) but it's a huge annoyance having to wrap `config.lib.nixGL.wrap <package>` around everything you want to install.
It's a symptom, not a cause.
- Nix: build system and package manager (available on Linux and macOS)
- Nix: language used to define how to build packages
- nixpkgs: Nix package monorepo
- NixOS: Linux distro that is fully managed using Nix (language), has Nix (package manager) built-in, and is defined as part of nixpkgs
(Also, I tend to think it's better to view NixOS as a tool for producing a linux distribution, which in many cases just happens to have an installbase of 1 - but that's not necessarily the case, and you could build your images with NixOS and deploy a dozen of them to aws.)
[1]: this was meant to be a joke, but it occurs to me that a person might think I missed that they had divided "Nix" up into two, the buildsystem and the language. But a language is not a command and doesn't do anything, so it can't possibly be an interpreter as well - and there could be and to some degree is multiple nix interpreters. So it is the first of the divisions of Nix that I sliced in two, and you end up with three Nixes: the buildsystem/sandbox; the main language interpreter; and the language.
https://kagi.com/proxy/images?c=_m3km2RjA3G0qleowsZXHZb9NEn0...
Anyway, traits are "is a" descriptive thing, not a referential equality "is". The trinity relations are not "is a" to begin with, or we'd be having many gods and Christian priests are not into that.
I tend to agree traits is not an accurate description, but it is a reasonable analogy.
> The trinity relations are not "is a" to begin with, or we'd be having many gods and Christian priests are not into that.
Sayings "priests" seems and off choice of wording. Why not just Christians, or even "Christian theologians"?
> Sayings "priests" seems and off choice of wording.
Meh. Priests set the norm for the regional communities.
This installer and the relationship between DetSys and Nix has also been subject to major criticism about conflict of interest between community interests and DetSys, since everyone agrees the official Nix installer has major issues. "Determinate Nix" (as DetSys calls the nix configured with their installer) also enables features that are the de-facto way to use Nix these days, but are disabled in the default distribution because of... let's say... commitment issues.
If you want a community run alternative, try Lix. They have a version of the DetSys installer too - and they actually cut releases of nix instead of building moats around it.
It's basically at the point where it just needs a redirect from the nixos.org domain, and for the project/community to work through how to manage its development/relationship to the Nix repo.
It's generally a response to corporate interests (including Anduril, who put Nix on autonomous weapons) and elbow-shoving so-called meritocracy (including a very infamous concern troll) becoming dominant inside the Nix community and Nix leadership, by people who didn't want to work from inside the system to reform, but also know they can't maintain all of Nixpkgs by themselves either (which already bled a bunch of maintainers).
- Normally, just deleting /nix gets you 95% of the way back to normal.
- If you want a bulletproof removal, the determinate systems Nix installer saves a file with a list of all the operations it made during installation so that it can be cleanly removed.
- If you want to stop home-manager from hooking into your shell without completely removing Nix, there's a separate uninstall command for that.
It's a bit more involved than homebrew, but you end up with a very precise definition of what your project depends on. This prevents all kinds of headaches re: Linux and Mac users depending on subtly different versions of grep or sed. Plus you can recreate the same environment in CI and Prod without having to define those dependencies separately.
Or you could, if your team was bought in. That's the hard part.
I always see these type of arguments for why nix is so great but it’s never been a pain point for me in 10+ languages and 20 years of development experience. I see your example of bash scripts but this can’t be all for writing scripts.
In addition, I play with all sorts of open source tools and they often come with their own tool chains and expectations. Python version management in particular benefits a lot from this level of isolation. Instead of figuring out the different version management tools for each stack I use a higher order environment management tool in Nix.
Some others are solving these issues with containers, and that’s a part of the nix strategy as well.
Nix is a pain in the ass, people mostly use it because it's the only reliable option.
Because regardless of what the cool kids are doing, important work is being done in conda, and usually by people whose expertise isn't software packaging.
People will just install the latest version and start hacking away, and now you've got all this code that depends on that version. Backwards compatibility ain't perfect, so maybe several years later the original author doesn't work here anymore, so tests are breaking in subtle ways when you install what's the now latest version and there's nobody to ask what the "right" version is.
But since we're a culture that uses these tools (though I wish we weren't), this story has played out several times so different projects need different versions--you can't just discover the right one once and leave it installed in your system, you have to install the right one for your project and change it when you switch to a new project.
For the most part these are go projects, so even though there is language-specific dependency locking via go.mod and such, dependencies which aren't go libraries but which are nonetheless needed to work with the project (e.g. make) are left as an exercise to the reader. Make is pretty well behaved, I haven't had to do much version antics with it, but I wouldn't say that's the norm.
When I find one of these repos I put my archaeologist hat on and write a flake.nix to provide whatever the dependency is, and then I walk the version backwards until it starts working. That way next time I'm in that project I don't have to go through that exercise again.
To make matters worse, people often try to help by adding entries to the makefiles which download the correct version for that project, but some people have the newer arm chips and others are still on x86 so confusion of a new kind ensues. Of course it's easy to fix these scripts to detect the local architecture, but that's a whole extra step.
And then maybe you're trying to make this stuff work in CircleCI or somesuch, and you don't want the workflow to just be reaching out via https and blindly running whatever comes across the wire because who knows if it'll be the same thing tomorrow, so you add hash checks, but once you've got the hash checks and the architecture checks and you're checking the right hash for your architecture... we'll you've basically got a poor man's flake.lock at that point, might as well use the same nix config in both places rather than use homebrew or apt or whatever locally and then figure out how to do the same thing via circleci orbs in yaml and god forbid you have to do it in prod too so now there's a Dockerfile... Having a single source of truth for dependencies and using it everywhere is super handy.
That's work. Another example is in my personal projects. I use helix, so there's a .helix/languages.toml in my repo which defines the language servers that I'd like it to use for that project. But merely pointing helix at the language server isn't enough, it also has to be on the PATH. My older projects are using mypy, and my newer ones are using pyright (python type checkers).
Sure I guess I could just install both at the system level everywhere I go, but when I clone the project on a new machine I want to have everything work right away--I don't want to start coding and then wonder why my editor sucks and then go discover and install the right LSP and then resume coding. I'd end up with a smattering of different versions installed across all of my devices, even for the same project. If I find a bug which happens on this machine but not that one, I'd have a much harder time knowing where to start re: debugging it.
Finally there's this idea that maybe you don't even have to clone the repo, you can just reference the app you want to run from anywhere. I invoke some of my tools like:
nix run git+ssh://git@github.com/myorg/myrepo -- mycli --best-arg
Nix knows how to set up the environment for running the app (the one I have in mind is written in python, so a certain version of poetry is involved etc...) so I really don't need the caller to think about that environment at all. I like this because it decouples the orchestrator from the executor. So if I can manage to get something working locally with one of these commands, then I can go put the command someplace weird like in an Airflow DAG (kubernetes pod operator, NixOS image) and I have a pretty strong assurance that it'll work the same in the remote environment as it does locally.From the perspective of a nix user, these problems are all the same problem and they're everywhere and nix is the only thing that solves all of them at once. My feeling is that from the outside, they look like separate problems, and it's not clear just how many of them are solved by nix--so the juice doesn't appear to be worth the squeeze.
Agreed, but people have a tendency to do otherwise. At the very least you still have to install the right version of the language. And there are probably an few other tools, linters and such... Next thing you know you've got quite a pile that's not covered by your language's package manager.
I only worked in a Java shop once, but I remember that they looked at me like I was an alien when I proposed that we involve a subprocess written in a different language.
At the time I thought they were insane for writing everything themselves but I've since seen how gnarly packaging can get and now think that they're... less insane.
The determinate systems installer for Nix is honestly a really great example of a great command line tool. It very transparently tells you "this is what we're going to be doing. Will you allow me to do all of these things?" and it tells you what when it is doing them. Then they bundle the uninstaller.
I use arch, btw, because its a solid rolling release and the AUR. Its the absolute best distro for a developer, theres really no competition.
We should promote this more :)
I've actually been using NixOS on my Legion Go to give me the SteamOS experience while I wait for the official image from Valve [1].
I knew that Valve had whitelisted /nix, but seeing how the author explicitly loads Nix in Bash:
.nix-profile/etc/profile.d/nix.sh
makes me wonder how it works in game mode. Say that someone uses Nix to install a game like YARG that's not in the Steam store [2]. That will install the game to /nix/store and write an alias to the user's desktop. /home/deck is not immutable, so you could add the desktop file as a non-Steam game, and everything will work as expected, right?What are the boundaries between things that work everywhere, things that only work after you've loaded a bash profile (e.g. from a terminal), and things that only work in NixOS? What if a package wants to run at login? What if it uses its own systemd rules?
Not sure if I'm misunderstanding what you mean by systemd rules, but from what I understand, enabling a systemd service (either at the system or user level) is the most reliable way to make sure that something starts up in game mode as well as desktop mode. Because I find it useful to ssh into my Steam deck for a lot of things rather than trying to do it all via desktop mode (e.g. managing config files for Baldur's Gate 3 mods that aren't from the in-game mod installer), and I always turn off wifi on it whenever I leave my apartment with it to save battery, I enabled the sshd systemd service, and it's available even if I boot up directly into game mode. I haven't actually been able to find any other way outside of an enabled systemd service to make things start up automatically in game mode, which ended up being an issue for me when I wanted to autostart something through Wine that didn't have an option to avoid trying (and failing) to open a window.
https://nixos.wiki/wiki/RetroArch https://nixos.wiki/wiki/Playstation2
I really want to get game developers using Nix. That is a large reason why I am working on the Windows port!
>nix-channel --add https://nixos.org/channels/nixos-24.11 nixpkgs
>This command sets your nixpkgs channel to the latest stable version (in this example, 24.11). In the future, check the current stable version on the NixOS homepage.
Any particular reason for not having a "latest" that will automatically detect the latest release instead of forcing each user to manually check and set the latest stable release every time?
I'm able to run steam games and have had no issues at all. Im using Lutris as the launcher, but you could easily use the official steam launcher (programs.steam.enable = true).
So you could technically get yourself a full gaming experience just with nix, without relying on the shipped steam client in SteamOS.
RetroDeck bundles everything into a single flatpak and seems a lot saner, but is a lot newer.
We generally mean an asterisk as a glob wildcard, and *nix definitely doesn't match Linux. There are vanishingly few operating systems whose names match this glob, and all of the ones I'm aware of are either true UNIXes or Unix-likes.
One of my favorite examples of this precision-be-damned absurdity is from the wiki page for Unix-like (https://en.wikipedia.org/wiki/Unix-like):
> Other parties frequently treat "Unix" as a genericized trademark. Some add a wildcard character to the name to make an abbreviation like "Un*x"[2] or "*nix", since Unix-like systems often have Unix-like names such as AIX, A/UX, HP-UX, IRIX, Linux, Minix, Ultrix, Xenix, and XNU.
Of these, zero match `Un*x` and only "Minix" and "Xenix" match `*nix`.
If we want to talk about the category of OS that includes both UNIXes and Linux, I wish we'd just call them Unix-like :)
The asterisk character in this context/usage is not used as a wildcard/glob but as a censoring device[3], in a manner similar to: "Don't censor f*ck on HN."
In the case of "Un*x" the motivation is not one of propriety but of proprietary--it was motivated by matters of legality (real or imagined) in relation to trademarks.
AIUI at the time UNIX(TM) was a trademark and it was thought by some that in order to avoid potential legal issues it was required to always include the TM superscript in order to avoid the wrath of the trademark owners for trademark infringement/generic-ism.
But as "Un*x" is not "UNIX"[4], the reasoning went, no trademark attribution was required.
Anyway, that's why when referring to "***/L*nux" I’ve (very) recently taken to calling it "***/L*nux", not wanting to infringe on Linus's trademark and all...
----
[0] The Wikipedia text doesn't really fully represent/match the text of the cited reference[1][2]:
"Used to refer to the Unix operating system [...] in writing, but avoiding the need for the ugly ™ typography [...] lawyers now say that the requirement for the trademark postfix has no legal force [...]"
[1] https://en.wikipedia.org/wiki/Unix-like#cite_note-jargonfile...
[2] http://catb.org/jargon/html/U/UN-asterisk-X.html
[3] https://en.wikipedia.org/wiki/Asterisk#Censorship
[4] Coincidentally, GNU is also Not Unix: https://en.wikipedia.org/wiki/GNU#Name
Given that package management on the Deck is traditionally handled with Flatpak, Nix seems like a great alternative for power users with storage to spare.
Long story short, it would be faster to go check the computer physically. But it was more fun this way, even though I didn't have the time to play the game in the end.
Every few months I have to rerun an install script though, if I choose to upgrade to their latest release, since I don't want to risk doing that upgrade with the overlay in place.
But otherwise it's been working well for a couple of years.