Symlink to /etc from within a package vs. purity?

Hi folks,

I’m packaging a (closed-source) software with a quirk: It requires a system-wide configuration file which the administrator has to prepare and which must reside in a directory that also contains most of the software’s binaries and static data (e.g. language files). On classic Linux distributions, the software usually resides in /opt/$APPNAME/... and the config file is created and edited there. When packaged with Nix, the config file would end up in the package where it can’t be altered later. Consequently, the config file would be a build input and the package be rebuilt whenever the config changes.

By looking at build recipes in nixpkgs, I grew the idea of placing a symlink to /etc/$APPNAME where the config file would normally reside during the package’s build process (like this https://github.com/NixOS/nixpkgs/blob/master/pkgs/os-specific/linux/bluez/default.nix#LC78 ). It works fine: The program follows the symlink and processes the config file in /etc/$APPNAME. On NixOS, the config file is generated by a module. Yet, after proposing this as a pull request, I met resistance: I learned that packages depending on config files outside of the Nix store are considered impure and to be avoided whenever possible.

A proposed alternative would be to create another package that “wraps” the original one by creating a copy (via symlinks) of the directory that should contain the config file. The config file would be placed directly in the wrapping package (as build input), which would have to be rebuild each time the configuration changes. This could be accomplished in a NixOS module. However, on non-NixOS systems (an important use case for me) this process would have to be done manually each time the config file is changed. I consider maintaining a separat wrapper package that depends on the config file and needs to be rebuilt regularly too tedious. In particular, the user would no longer be able to use the package by just installing it with nix-env -i ....

With this posting I’m looking for opinions on how to balance purity with practicability. Also, assuming a refernce to /etc is not acceptable here, are there any alternative designs that – ideally – would permit the user to install/use the package with nix-env?

The “Learn” category recommends to include context, yet I had to simplify the problem to keep this message short (I hope this is ok). See here for the pull request in question: https://github.com/NixOS/nixpkgs/pull/61312 .

Thanks for your help (and for NixOS)

Maybe do the wrapper, but on non-NixOS have the wrapper just add a symlink to /etc/$APPNAME instead of writing the config file directly?

This could be accomplished by having the wrapper take a required parameter which is the config file to use, and have the wrapper symlink that config file into place. The nixpkgs package can then look like appname = callPackage ./path/to/appname { configFile = /etc/$appname/main.conf; } and the NixOS module can pass configFile = writeText "appname-conf" desiredConfigText. The wrapper itself will just take whatever path was passed and give that to ln -s (make sure to pass it as a string so it doesn’t copy the path into the store).

1 Like

Thanks for sharing this idea, lilyball. I reformulated my pull request.