Ever since I tried Nix, my favorite part of it has been Nix
home-manager. As I expanded my usage of it, I
noticed that it was really annoying that I couldn’t create many of my config files because they
often contained secrets. I knew tools like sops exist, but
managing yet another key and then committing those files to a repo, even though encrypted, wasn’t
really something I wanted to do. On top of that, I use 1Password and their very useful op
CLI tool
to manage my secrets. There was a cool project called opsops (props
on that name!), but that also just felt like a hassle for adding just a few secrets into places.
So, with that said, I figured I’d show my hacky, poor man’s way to adding secrets.
Basically, this leverages the home.activation
section available as part of home-manager. This lets
you run scripts with side effects once everything is place. Here is a code snippet of an example
setting up my config file for aichat
:
home.activation = {
setupAichatConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
run mkdir -p "$HOME/Library/Application Support/aichat"
yaml_path="$HOME/Library/Application Support/aichat/config.yaml"
run rm -f "$yaml_path"
run cat > "$yaml_path" << 'EOF'
model: openrouter:openai/gpt-4o
function_calling: true
clients:
- type: openai-compatible
name: openrouter
api_base: https://openrouter.ai/api/v1
api_key: <REPLACE ME>
EOF
# On macOS, sed -i requires an extension argument but we need to avoid escaping issues
run ${pkgs._1password-cli}/bin/op read --account <ACCOUNT_ID_HERE> "op://Private/aichat-openrouter-token/credential" | run xargs -I{} sed -i"" 's/<REPLACE ME>/{}/g' "$yaml_path"
run chmod 400 "$yaml_path"
'';
}
There are a couple of notes here about how this works. First off, the lib
here is referring to
home-manager.lib
which can be passed into your home.nix
file. The run
command is a command
provided by Nix that ensures you don’t run these commands when running in a dry run mode. This must
be run after the writeBoundary
event, which is why that exists in the entryAfter
line.
Otherwise, this is just pretty much normal bash. What we do here is pass in the op
cli from the
nix package we are installing, explicitly pass an account ID (this matters when you’re doing
something on a work machine where you might have multiple accounts), and then use sed to replace the
value in the file. Please note that you do need to have 1Password desktop app installed and the CLI
integration checkbox checked for this to work. For security purposes, and to imitate Nix, we then
set the file to readonly for the user.
And that is that! There are probably other, better ways to do this, so please reach out if you want to correct me here. Otherwise, I hope this is a useful tip for people who might be doing something similar with Nix