How to convert a script that dynamically calls other (dropped in scripts) to Nix

Erm, freudian tag? Sorry!

First of all, TY for the help @TLATER @waffle8946.

I got It working with environment.etc…

Still I’m not 100% happy. If I understand it correctly symlinkJoin will symlink/bundle stuff in the store but is no mechanism to link something to the store.

Is there something more generic to do that, outside of etc?

You could use systemd.tmpfiles for example?

Yes, but you can then place the bundled path wherever you please.

systemd.tmpfiles is indeed the generic path creation option - yes the NixOS community has complained about the name being inaccurate before, no systemd aren’t changing it.

That’d in total look something like:

# backups.nix
{ lib, config, ... }: let
  cfg = config.backups;
in {
  options.backups.perServiceScripts =  lib.mkOption {
    type = lib.types.listOf lib.types.package;
    default = [ ];
  };

  config = {
    systemd.tmpfiles.settings."/backup-scripts"."L+" = pkgs.symlinkJoin {
       name = "backup-scripts";
       paths = cfg.perServiceScripts;
    };
  };
}

You’d then use this option in your service modules:

# service.nix
{ pkgs, ... }: {
  # Imagine some pithy service configuration here

  backups.perServiceScripts = [
    # Use `writeScript` if you don't want a `bin` directory
    (pkgs.writeShellApplication { ... })
  ];
}

Once you’re here, you can even stop symlinking stuff, and just write your configuration file to point to the right path to begin with, and symlink it to /etc (or give it directly as an arg to your main script in a systemd service).

It’ll work but be aware that systemd won’t clean up the link when you remove the tmpfiles entry. It’ll continue to exist as a symlink until it bitrots (gc removes the reference) and then you’ll have a broken symlink.

environment.etc doesn’t have this issue which is why I suggested that first.

3 Likes

I destroyed what I had yesterday and now I cant remember how I plumbed that together and Nix is throwing error msgs at me that I don’t understand.

How do I actually plumb the lambda let
lambda = pkgs.writeShellScriptBin {…} in environment.etc.“something”.source = ?

If it’s a lambda, that’s because you’re missing arguments. writeShellScriptBin takes two args, the name of the derivation and the script in string form. writeShellApplication is different.

Sometimes you also need to grab the .outpath since nix doesn’t automatically type convert, but I think here a derivation is fine.

1 Like