Providing credentials (to a private container) registry

I want to load an image from a private registry:

  virtualisation.oci-containers.containers = {
    whoami = {
      image = "ghcr.io/tcurdt/foo:v1.0.1";
      ports = [ "127.0.0.1:8080:80" ];

      login = {
        registry = "ghcr.io";
        username = "tcurdt";
        passwordFile = "";
      };

    };
  };

That’s now the first time I need to somehow provide credentials to a config.

Is agenix a good way to go here?
Or what’s the current suggestion to use?

1 Like

I just found Handling Secrets in NixOS: An Overview :: LGUG2Z which demonstrates some of the options.

  • git-crypt
  • agenix
  • sops-nix

Any real world experience to add?

agenix and sops-nix are both used a bunch by different people and companys.

I personally prefer sops-nix, because sops is more widespread (also used by terraform and kubernetes people) and sops-nix has a builtin home-manager integration. They both have there quirks but over all mostly the same feature set.

5 Likes

Avoid git-crypt if you can. It breaks security measures that rely on user management, including containers, and has potential to leak secrets through remote builds and deployments.

Secrets should almost never go plain-text to the nix store, this is why most secrets have passwordFile options these days, and have lost the footgun password options, that way they can be loaded from other locations. I pointed this out to the author of that blog post, who said they would amend it, sadly that seems to have fallen between the cracks.

1 Like

I got a bit further and got sops-nix setup but it seems to get the initial set of credentials to the server I would need to build locally - not on the server it. (as the age key is only on my local machine).

While agenix also looks interesting it seems to rely on the host keys. Which means, first install the machine (that will generate the host key), then copy the host keys into the flake, then push out the secrets. Unless I am missing something - that does not feel quite right.

Is there nothing that works based on the fact that I can log in via ssh?
With a ForwardAgent yes it should be possible to transfer the trust to decrypt something on the machine - somehow. No?

Or am I missing something?

With agenix you will copy only the public key of the host into your flake and encrypt the secret with it such that only the host will be able to decrypt it with its private key (which will never leave the computer). Should that work? Or what exactly doesn’t feel right?

1 Like

That sounds just very manual.
And the flake would change with every new machine.

In all secrets deployment there must be at least one key from which the others can be derived. Find a mechanism by which you can generate that key, and deploy it to the remote, before further keys can be communicated - otherwise you cannot have secure communication to that remote, and therefore you have no way to deploy the other keys without a third party potentially snooping.

sops-nix uses the deployed-to host’s ssh key for this by default, since that one is effectively required for remote deployments, so it must exist in some form already in most cases. You can use ssh to get the remote’s public key with ssh-keyscan, which is probably as convenient as it gets.

gokey is an interesting project that came up during a recent discussion on this topic, but it has no NixOS integration yet. It would probably be pretty good at making you work with fewer keys, but it still requires manual intervention at initial system creation for each deployment - either to share the master secret (bad call), or to deploy the derived secrets for that system.

That said, I’m somewhat hesitant to try it before someone I trust more with cryptography than myself tells me how horrible deriving secrets partially with a known string is.

1 Like

The idea I had was:

Why not use the ssh key to encrypt (just like with sops-nixos) and once you make the ssh connection (with agent forwarding) the secrets can be decrypted on the remote. But…

While this feels a little better than using ssh-keyscan, it also still comes with a big drawback: The secrets cannot be available at startup.

But I guess this is always true with such a system.
The trust and the very first key has to come from somewhere.

Maybe just pass in a first key during installation (cloudinit)?

1 Like

nixos-anywhere is another option that comes with built-in support for installing a key during installation. Depends a bit on what exactly you’re deploying to.

1 Like

I am testing on UTM, Hetzner and Contabo.

I am running nixos-infect (via cloudinit if possible) and then apply my flake via ssh - for now.
But maybe I should have a closer look at nixos-anywhere then. Thanks for the pointer!

It sounded less compatible than nixos-infect so I tried with infect first.
Ah, and it also requires nix on the source machine.
I am still not sure whether that’s a pro or a con :upside_down_face:

But I guess it should be possible to sneak in a key with nixos-infect like this.

1 Like

Only nix, not NixOS, mind you. If you’re going to do deployments with nix you will probably need it somewhere in your stack anyway.

But yeah, agreed. There are cases where I wish we could break some dependencies. nixos-rebuild build-vm for example would be amazing for testing and probably help new users with adoption, if it didn’t require running on NixOS itself.

1 Like