I’m migrating my NAS to nixos, and I got to the point of setting up my restic backups.
services.restic.backups
is great, but – on top of the systemd timers/services – I also want some helper scripts (eg. one to easily mount the backups, stuff that with ansible I currently generate into /usr/local/sbin
).
These scripts would be entirely generated from the services.restic.backups
config and would reference sops secrets also from configuration.nix
, so… I don’t think it would make sense to make a package out of them?
What should I use to make these scripts? Should I use nixpkgs.writeShellApplication
and then alter the PATH
?
Yes,
writeShellApplication
is a good solution. But instead of altering your path, put the result right in theenvironment.systemPackages
list, or inusers.users.your-user.packages
.writeShellApplication
produces a derivation (a value that will be turned into a store path when it’s “instantiated”). Basically it’s already a package. You can use the derivation the same way you would use a package from nixpkgs.You’re likely already aware, but when you get secrets from sops those are paths to files in
/var/run/
generated at runtime; so your scripts will need to run with sufficient privileges to read the secrets files.Edit: Sorry, I meant “instantiated”, not “realized”
Thanks: that helps a lot. I’m still quite confused about nixos concepts (and by the lingo too).
edit: Turns out you can’t just put
writeShellApplicaiton { ... }
insystemPackages
directly: you need to add the package via anoverlay
(see https://discourse.nixos.org/t/referencing-the-output-of-writeshellapplication-as-a-package-in-another-nix-file/23363)edit2: Actually, /u/hallettj@beehaw.org is 100% right: one can put
writeShellApplicaiton { ... }
insidesystemPackages
, but it must besystemPackages = [(writeShellApplicaiton { ... })]
with the parentheses, otherwisewriteShellApplicaiton
is not applied to its argument and the two end up as two separate elements in the list.I can at least try to define the concepts I mentioned in my comment.
/nix/store/
. It has the format/nix/store/--
. Every installed package gets a store path. There is other stuff too - if you use flakes each flake and each flake input are copied to a store path before being evaluated. IIUC certain directories within each store path are treated specially. For example if a store path has abin/
directory, and that store path is included in your user “profile” of installed packages, then everything in thatbin/
directory is automatically symlinked to your profilebin/
directory, which is in your$PATH
. For example,nixpkgs.git
, the value you get is a derivation. But you can also make derivations yourself using functions likestdenv.mkDerivation
orwriteShellApplication
. I think you can even write an attribute set from scratch if you want to.To get from a Nix attribute set to a set of files there is a process called instantiation that is separate from evaluation of Nix expressions. (By “expressions” I mean Nix programs, anything in a
.nix
file.) Certain Nix programs will evaluate a Nix expression, read a derivation that the expression produces, and do the instantiation to actually create the files. As I mentioned the derivation includes all of the information necessary to do this. Part of this process actually serializes each derivation to a file in/nix/store/
- that’s what the.drv
files in there are. Those are very-specialized scripts that produce store paths.Yeah, it was quite a learning curve for me too. I found reading Nix Pills was helpful. I put it off too long even after seeing lots of recommendations. It turns out the recommendations are apt.