Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nix darwin module #614

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Nix darwin module #614

wants to merge 2 commits into from

Conversation

Mic92
Copy link
Owner

@Mic92 Mic92 commented Sep 5, 2024

No description provided.

j-baker and others added 2 commits September 5, 2024 14:44
This is somewhat but not entirely duplicative with the home manager
support. The difference is primarily for MacOS servers, for which there
is no LaunchAgent support (as launch agents are tied to user sessions).

This PR adds a nix-darwin module (configured similarly to the home
manager module) which is suitable for e.g. other launchd daemons.
@niklasravnsborg
Copy link

niklasravnsborg commented Sep 7, 2024

@Mic92 I've tried to use this but for me it doesn't create the secrets in the defaultSymlinkPath and defaultSecretsMountPoint. For me it only created age-keys.txt and and empty sops-nix-secretfs file...


EDIT: I think this is because my SSH-key is password protected. I found out by running: cat /var/log/sops.log.

Comment on lines +253 to +261
launchd.daemons.sops-nix = {
serviceConfig = {
Program = script;
KeepAlive = false;
RunAtLoad = true;
StandardOutPath = cfg.logFile;
StandardErrorPath = cfg.logFile;
};
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Mic92, I've tested this module on my setup and it works well but the launchd service isn't started after reboot. This is an issue with nix-darwin where the nix store is not yet mounted when the launchd services are started.

There is some work on the way to fix this in: LnL7/nix-darwin#1052 but for it to work correctly, we need to use command (or script) here instead of serviceConfig.Program.

Suggested change
launchd.daemons.sops-nix = {
serviceConfig = {
Program = script;
KeepAlive = false;
RunAtLoad = true;
StandardOutPath = cfg.logFile;
StandardErrorPath = cfg.logFile;
};
};
launchd.daemons.sops-nix = {
command = script;
serviceConfig = {
KeepAlive = false;
RunAtLoad = true;
StandardOutPath = cfg.logFile;
StandardErrorPath = cfg.logFile;
};
};

domain-target = "system";
in ''
/bin/launchctl bootout ${domain-target}/org.nixos.sops-nix && true
/bin/launchctl bootstrap ${domain-target} /Library/LaunchAgents/org.nixos.sops-nix.plist

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably has to be LaunchDaemons instead of LaunchAgents...

Suggested change
/bin/launchctl bootstrap ${domain-target} /Library/LaunchAgents/org.nixos.sops-nix.plist
/bin/launchctl bootstrap ${domain-target} /Library/LaunchDaemons/org.nixos.sops-nix.plist

@Mic92
Copy link
Owner Author

Mic92 commented Sep 9, 2024

@Mic92 I've tried to use this but for me it doesn't create the secrets in the defaultSymlinkPath and defaultSecretsMountPoint. For me it only created age-keys.txt and and empty sops-nix-secretfs file...

EDIT: I think this is because my SSH-key is password protected. I found out by running: cat /var/log/sops.log.

password protected ssh keys are unfortunately nothing we can support, because sops runs early in boot, where we cannot prompt for passwords. I would suggest generating an age key for now.

@niklasravnsborg
Copy link

niklasravnsborg commented Sep 9, 2024

password protected ssh keys are unfortunately nothing we can support, because sops runs early in boot, where we cannot prompt for passwords. I would suggest generating an age key for now.

Thank you. My solution was to use your ssh-to-age program to generate the age key from my encrypted SSH key and store it locally, and it worked well :)

My problem now is that secrets aren't available immediately after logging in for other launchd services to consume. The secrets mount is only available after sops-install-secrets was run. On macOS, this gets triggered by the launchd daemon, and it might take a few seconds to decrypt the secrets and mount the in-memory volume.

In my use case, I have another launchd daemon that runs a service dependent on the decrypted secrets file. But this file is not available yet when the service is started. I only realized sops-nix is using a volume mount after tinkering with this module and the code a bit. Before that, I assumed that the secret files would just be replaced on disk when sops-install-secrets was run and that they would persist on reboot. In such a case, we wouldn't even need a launchd service and could only redecrypt the secret on "nixos / nix-darwin switch", but I see the need for an in-memory volume.

One solution might be to use wait4path /path/to/secret in the other services before they are run, but this would require overriding the launchd.daemons."some-service".command for the according services, which seems hacky and cumbersome.

For now, it feels like this might be the reason why I can't use sops-nix for my use case. @Mic92 Do you have some thoughts on that?

@niklasravnsborg
Copy link

UPDATE: In the end I used some scripting to restart my other service when the secret files are available: niklasravnsborg/dotfiles@1afccc9. A problem I encountered was that file watching doesn't quite work as expected for symbolic links to files inside of a volume that may not be yet mounted, when the file watcher is started. But my solution handles most cases fine.

@Mic92
Copy link
Owner Author

Mic92 commented Sep 19, 2024

@niklasravnsborg do you have a clue how I could make error reporting better in the darwin activation phase? launchd just silently fails, which is not great. I was wondering if I should not just run sops-install-secrets additionally in foreground on updates.

@niklasravnsborg
Copy link

Which errors did you encounter? The /bin/launchctl bootstrap in the activation might not work because of the wrong path as I mentioned in a previous comment.

I guess it's fine to have it either restart the daemon or run the sops-install-secrets on activation but not do both.

@Mic92
Copy link
Owner Author

Mic92 commented Sep 19, 2024

I mean if the service fails, I want to see the error in the shell that runs launchd service.

@niklasravnsborg
Copy link

I see, yeah this makes it harder to debug sometimes. I think seeing errors in the shell that bootstraps the service is not what launchd is made for, since launchd services run in the context of the system in the background (similarily to what systemd does on linux). On bootstraping they are just scheduled for starting and there is no immediate feedback.

So I guess we could just run the launchd service on boot but use the sops-install-secrets script directly in the activation. There it doesn't have to trigger the launchd service again.

I found sudo launchctl print system/org.nixos.sops-nix quite useful for debugging and looking at the logs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants