Folder Layout for an App Running from a NixOS Package

I’m playing with making a NixOS package out of an existing piece of software (see for some context: https://github.com/NixOS/nixpkgs/issues/55364 ). This piece of software comes as a single folder which holds all sorts of data, binaries, initial config, working config, temporary files, and so on. For one, this just won’t work because nix store is readonly. Then, it does not feel right anyway.

What’s the best idea for laying out the folders?

My guess was like this:

  • Binary files sit where the package is deployed, in /nix/store.
  • Static config files which stitch together pieces of the app and do not change at runtime (from the UI of the app) should be emitted based on the configuration.nix and stored under /etc.
  • Dynamic config files which change when users interact with the app UI would go under /var/lib (by “users” I do not mean Linux users, and the change of state is global for the app).
  • Temporary files go under /run.
  • Logs go under /var/log.

Is this wrong/right/excessive/not-handy in any sense? How would you lay this out?

if you’re touching those files, it sounds like you want to spin up a systemd service, in nix we would encapsulate this in a nixos module.

One thing that’s nice about creating a nixos modules, is then you can configure the application through your configuration.nix, and you get all the power of doing roll-backs and profiles.

Yes I have a module, and it does the proposed configuration to the folders. Though this causes the software to fail functioning by mere fact of reconfiguring the folders outside of its own dir – but that’s some peculiarity of the software I’m to deal with, in the meantime I would like to know if maybe the whole idea of placing the folders is wrong.

Though this causes the software to fail functioning by mere fact of reconfiguring the folders outside of its own dir – but that’s some peculiarity of the software I’m to deal with

If you expect the software to be pretty marginal, you could hardcode those external paths as symlinks during the build, and have a wrapper that copies the initial state to the writeable locations. Probably with package arguments to override the targets. Not completely perfect, but cheaper than actually fixing the package throughout.

(So you have /nix/store/hash-package/config -> /etc/package/ symlink etc.; the package still thinks it writes to its own directory)

That’s some interesting point, hardcoding links to nonexistent-yet entities when making a package.
The software theoretically has env vars which define where to look for these folders, but in reality something does not come together at runtime if you do use them.