feat: add nixos hacks
This commit is contained in:
parent
caedd08804
commit
a7733d1d2b
2 changed files with 202 additions and 0 deletions
193
content/Hacks/nixos-cheat-sheet.md
Normal file
193
content/Hacks/nixos-cheat-sheet.md
Normal file
|
@ -0,0 +1,193 @@
|
|||
---
|
||||
id: nixos-cheat-sheet
|
||||
aliases: []
|
||||
tags:
|
||||
- nixos
|
||||
- nixpkgs
|
||||
- linux
|
||||
---
|
||||
|
||||
# Assorted NixOS hacks and tricks
|
||||
|
||||
The Nix package manager and NixOS Linux distribution are woefully
|
||||
underdocumented. There are many, many powerful features that are difficult to
|
||||
find, sans directly reading through source code.
|
||||
|
||||
I can't fix that, but this document serves as a personal cheat sheet of all the
|
||||
small Nix features that I don't want to forget.
|
||||
|
||||
## Derivations
|
||||
|
||||
Stuff related to writing derivations of software.
|
||||
|
||||
### Sparse Checkout with fetchGit (and friends)
|
||||
|
||||
You can do sparse checkouts when using `fetchgit` and its friends
|
||||
`fetchFromGitHub`, etc. This is useful if you're cloning a large repository and
|
||||
know you only need one specific directory. If you only need a specific file,
|
||||
consider `fetchurl`.
|
||||
|
||||
```nix
|
||||
fetchgit {
|
||||
url = "https://github.com/foo/bar";
|
||||
hash = "sha256-0000000000000000000000000000000";
|
||||
|
||||
# takes a list of directories that should be checked out
|
||||
sparseCheckout = ["dir", "another/dir", "foo/bar/dir"];
|
||||
}
|
||||
```
|
||||
|
||||
### The `callPackage` pattern
|
||||
|
||||
This isn't even a note for myself since I use this feature so much, but I'm add
|
||||
it anyways so I can point to it as a reference.
|
||||
|
||||
When you look at `package.nix` files in the source code of `nixpkgs`, you'll
|
||||
see they typically take the form:
|
||||
|
||||
```nix
|
||||
{
|
||||
stdenv,
|
||||
libfoo,
|
||||
libbar,
|
||||
fetchFromGitHub,
|
||||
...
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
nativeBuildInputs = [ stdenv libfoo libbar ];
|
||||
|
||||
src = fetchFromGitHub {
|
||||
# blah blah
|
||||
};
|
||||
# rest of file omitted for brevity
|
||||
}
|
||||
```
|
||||
|
||||
It's a lambda (anonymous function) that takes in an attrset of everything the
|
||||
derivation needs, and returns the derivation. As you clearly see, the `...`
|
||||
means that the attrset contains all of the attributes specified, but also
|
||||
arbitrarily more.
|
||||
|
||||
Exactly what attributes are available in this input attrset? It turns out that
|
||||
this attrset is actually populated with the _entirety of nixpkgs_. Basically,
|
||||
any package that can be referencd from `pkgs.xxx` is available in that input
|
||||
attrset.
|
||||
|
||||
This is very useful for writing clean derivations. Oftentimes I see people
|
||||
haphazardly pass `pkgs` around to all their derivations and directly make use
|
||||
of it. While this is fine in small derivations, it quickly gets messy in large
|
||||
ones. I prefer to always write non-trivial derivations using the nixpkgs
|
||||
pattern. However, how do we go from a file like the example above to an actual
|
||||
package that we can, say, output from a flake?
|
||||
|
||||
There's a function called `pkgs.callPackage` that handles precisely this task.
|
||||
It takes in two arguments. Here is its pseudo type signature:
|
||||
|
||||
```
|
||||
callPackage :: file -> attrset -> package
|
||||
```
|
||||
|
||||
The first argument is the file that contains the derivation as shown in the
|
||||
example. The second argument is an attrset that allows you to pass or overwrite
|
||||
any values in the attrset passed to argument 1.
|
||||
|
||||
Oftentimes the second argument is not even needed and so you simply pass an
|
||||
empty attrset (`{ }`).
|
||||
|
||||
```nix
|
||||
packages.default = pkgs.callPackage ./my-derivation.nix { };
|
||||
```
|
||||
|
||||
An example of the second argument in use is in a situation where you have a
|
||||
flake that provides multiple packages, but one of these packages depends on the
|
||||
other. Then, you can pass the packages to each other using the attrset
|
||||
argument.
|
||||
|
||||
```nix
|
||||
packages = rec {
|
||||
foo = pkgs.callPackage ./foo.nix { inherit bar; };
|
||||
bar = pkgs.callPackage ./bar.nix { };
|
||||
};
|
||||
```
|
||||
|
||||
Then, in the corresponding derivation of `foo`, `bar` will be available as an input:
|
||||
|
||||
```nix
|
||||
# file: foo.nix
|
||||
{
|
||||
stdenv,
|
||||
libblah,
|
||||
bar, # the bar package we provided is now available here
|
||||
...
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
buildInputs = [ bar ];
|
||||
}
|
||||
```
|
||||
|
||||
## nixpkgs and the nixpkgs lib
|
||||
|
||||
General stuff related to quirks in nixpkgs and `lib`.
|
||||
|
||||
## Flakes
|
||||
|
||||
Niche features of Nix flakes.
|
||||
|
||||
### Nix flake inputs have additional properties
|
||||
|
||||
Everyone knows the common properties of Nix flake inputs: the standard outputs
|
||||
like `packages`, `apps`, `nixosModules`, etc.
|
||||
|
||||
However, there a few that I have seen seldom used and hard to find mentions of
|
||||
in documentation
|
||||
|
||||
```nix
|
||||
{
|
||||
inputs.cool-flake.url = "github:hackerman/cool-flake";
|
||||
|
||||
outputs =
|
||||
{ self, cool-flake, ...}:
|
||||
{
|
||||
# gives the commit hash of the flake
|
||||
rev = cool-flake.rev;
|
||||
|
||||
# gives the UNIX timestamp of the commit of the flake
|
||||
lastModified = cool-flake.lastModified;
|
||||
|
||||
# you can also get these attributes on the current flake using `self`
|
||||
|
||||
# gets current git commit hash
|
||||
# caveat: this property isn't defined if the git tree is dirty (there are uncommitted changes)
|
||||
selfRev = self.rev;
|
||||
|
||||
# I often use this pattern due to the above reason
|
||||
selfRev' = if (self ? rev) then self.rev else "FALLBACK"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## NixOS
|
||||
|
||||
Things from the NixOS distribution, including the module system.
|
||||
|
||||
## Misc
|
||||
|
||||
Stuff to do with other stuff. Potentially community made flakes.
|
||||
|
||||
### Set the right time in Typix (and LaTeX)
|
||||
|
||||
When using Typix to compile Typst documents, sometimes it's a little _too
|
||||
reproducible_. Attempting to reference the current date and time in the Typst
|
||||
document will always return `January 1st, 1980` when compiled in the Nix build
|
||||
environment.
|
||||
|
||||
You can set an environment variable to get the right time.
|
||||
|
||||
```
|
||||
SOURCE_DATE_EPOCH = builtins.toString self.lastModified;
|
||||
```
|
||||
|
||||
Here `self` is the self provided to the flake outputs that refers to the flake
|
||||
itself. As shown in
|
||||
[[./nixos-cheat-sheet.md#Nix-flake-inputs-have-additional-properties]], you can
|
||||
get the timestamp of the current Git commit.
|
|
@ -1,4 +1,7 @@
|
|||
---
|
||||
id: index
|
||||
aliases: []
|
||||
tags: []
|
||||
title: "Alexandria: a knowledge garden"
|
||||
---
|
||||
|
||||
|
@ -15,6 +18,12 @@ which I took in the fall quarter of 2024. You can find them in
|
|||
[[./Fall-2024/as-am-5/week-2.md]] and [[./Fall-2024/mes-45/week-1.md]] being
|
||||
the weekly notes.
|
||||
|
||||
If you're interested in the Nix package manager, I've also started maintaining
|
||||
a sort of "cheat sheet" or "tips and tricks" collection around variou quirks
|
||||
and features of the NixOS / nixpkgs ecosystem in
|
||||
[[assorted-nixos-hacks-and-tricks]]. Maybe you'll find something useful in
|
||||
there!
|
||||
|
||||
Feel free to take a look around and appreciate the scenery.
|
||||
|
||||
## FAQ
|
||||
|
|
Loading…
Reference in a new issue