Agenix and Syncthing devices & folders

I’ve just set up Syncthing via nix and it works beautifully. The issue is that I’m not comfortable putting my device and folder ids into potentially public git repos.

Agenix would be perfect for this, but the issue is that services.syncthing.settings.devices and services.syncthing.settings.folders expect strings, not file paths. This is not unique to Syncthing but a general limitation of the secret management solutions I’ve found for nix.

I’m wondering if anybody has a solution for cases like this. I personally wouldn’t mind if less secret secrets like this ended up in the Nix store, even if it’s not the most elegant solution.

I’d also be curious if somebody knows how to extend a service module with something like a passfile option in an overlay, which seems like a nicer approach.

Agenix would be perfect for this, but the issue is that services.syncthing.settings.devices and services.syncthing.settings.folders expect strings, not file paths. This is not unique to Syncthing but a general limitation of the secret management solutions I’ve found for nix.

You can use a double-flake pattern for this with one of the flakes being private.

In my dotfiles I have quite a few modules coming in from so-called data-flake that is hosted on my private gitea instance. I am then passing around a reference to this input and importing the modules in proper locations – machine-level and user-level.

I’d also be curious if somebody knows how to extend a service module with something like a passfile option in an overlay, which seems like a nicer approach.

Overlay is not necessarily the right interface for this since it’s a way to add new packages. You could wrap around a package with some machinery that would read from some file this way.

However, if you’re using a systemd service to run a service based on package, you can override any part of the systemd service definition like so:

config.systemd.services.<foo-service>.<systemd-section> = {
  <systemd-directive> = <some-value>;
};

Pretty much like in this bit of code, but you would probably need to tweak *Credential* or EnvironmentFile directives.

2 Likes

Thank you, that double-flake approach might be what I was looking for.

Overlay is not necessarily the right interface for this since it’s a way to add new packages. You could wrap around a package with some machinery that would read from some file this way.

Yeah, that makes sense. Do you have a source where I could learn how to wrapping a package this way?

There is no way of just extending a module like the services.syncthing module, right?

Do you have a source where I could learn how to wrapping a package this way?

This is heavily package dependent as the package has to have some means of loading some secrets at its runtime – like from environment. You could probably search for LoadCredential examples in nixpkgs to see how this is implemented for some services.

An example for home assistant secrets is here in my repo. This bit of code uses agenix to symlink the secret somewhere where home-assistant can see it and the code relies on the fact that home assistant can load any yaml files in ha’s configuration directory.

a general limitation of the secret management solutions I’ve found for nix.

This stems from a general limitation of nix itself: nix content evaluated at build time can be disclosed on build servers, and config written out is world-readable in the nix store. The file-based mechanism used by agenix and others means that the files can be decrypted and read at runtime, but it relies on the service in question having that capability (or a runtime helper / wrapper to do the substitution then).

If your requirement is only to protect secrets in the repo, and you’re not concerned with readable store contents or cached build servers, then git-crypt is also a viable option.

However, be aware also that it’s not enough to move the contents to a protected location (whatever variant you use) since the earlier versions are still in history.

Thank you both. This largely confirmed what I suspected, but gave me some good ideas on how to proceed.

However, be aware also that it’s not enough to move the contents to a protected location (whatever variant you use) since the earlier versions are still in history.

That’s partly of why I was posting this thread. I wanted to make an informed choice before putting sensitive (encrypted) data into the repo.

What solution did you end up using? Do you mind sharing it?

I pretty much where I was when posting this thread.

I was aware of gitcrypt before but was hoping for an alternative using agenix, as that’s something I’ve been using anyway.

I think it’s the easiest option if agenix/sops-nix don’t work for you.

@nadir for clarification on my side allow me to ask further, by “exposing secrets” you explicitly would mean the names of the folders / devices provided in services.syncthing.settings right ?

Just wondering if I get the whole strings materialize in store picture.

Also the message I get when checking makes me wonder a bit more:
nix path-info --derivation -vvvvv --show-trace .#nixosConfigurations.privacyconcerneduser.config.services.syncthing.settings.folders.some-uuid.path

error: string ‘~/foldername’ has 0 entries in its context. It should only have exactly one entry

This is the same issue that I was also having with syncthing. I solved this by using my already existing secrets-flake (which is a private repo). Normally, I put stuff in there that is actually sensitive, so everything is stored in sops-encrypted files. But for the Sync-IDs, while I don’t want to put them out in the open, I’m not overly concerned because (according to syncthing themselves) they are not really sensitive information. So I just put them unencrypted in the private repo.

Here is how I set everything up: dotfiles/modules/syncthing.nix at c1c41d62dbabebc144ee84d6d581986a4e3c8d4f · polygon/dotfiles · GitHub

Now you cannot see the private contents but it’s literally a .nix-file containing:

{
    fon = "ABCDEFG-ABCDEFG-...";
}

just containing the IDs. You could do the same for the folders, but I never bothered.

I also made Scalpel a while back to inject secrets into config files for packages that do not provide a way for sops-nix or agenix to dock. But I considered this overkill for syncthing, so not using it there.