Secrets inside nixos-containers

Is there a way to access secrets from tools like sops-nix or agenix inside nixos-containers, considering these tools expose secrets in the host filesystem which isn’t available after the container chroot? Or, what is the recommended way of storing secrets for nixos-containers?

what are you trying to achieve and your use case, if you give me the why, i’ll give you the the https://nix.how

I define my secrets on the host and then bind mount them inside the container like so:

containers.foo.bindMounts."${config.sops.secrets.fooSecret.path}".isReadOnly = true;
3 Likes

This works just fine, thanks a lot. Am i missing some obvious security implications when mounting the path not read-only in the container for allow changing ownership with tmpfiles.d from within the container to make the secrets accessible to other users?

In my case I didn’t need any special access because I had uid values lined up inside and out of the container so it was all good. But yeah, if you want to do that it is fine too.

1 Like

I found a solution to the user-id problem. The key is to import agenix into the container. Here is a explaining example with radicale in a container:

{ inputs, ... }: {

  containers."calendar" = {
    autoStart = true;

    # pass the private key to the container for agenix to decrypt the secret
    bindMounts."/etc/ssh/ssh_host_ed25519_key".isReadOnly = true;

    config = { config, lib, pkgs, ... }: {

      imports = [ inputs.agenix.nixosModules.default ]; # import agenix-module into the nixos-container

      age.identityPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; # isn't set automatically because we did not setup openssh
      # import the secret
      age.secrets."calendar-users" = {
        file = ../secrets/calendar-users.age;
        owner = "radicale";
      };

      services.radicale = {
        enable = true;
        settings = {
          auth = {
            type = "htpasswd";
            htpasswd_filename = config.age.secrets."calendar-users".path; # use the secret
            htpasswd_encryption = "plain";
          };

       # ...
        };
      };
    };
  };
}
2 Likes

It’s not set because it is set to config.services.openssh.hostKeys and you didn’t set up openssh in the container.

Just a tiny addition for my case; I was trying to set up a module that sets up a container and uses sops-nix inside the container too.

I had to add inputs to the module attributes at the top:)

{ config, lib, pkgs, inputs, ... }:

Edit: I see that this is what you are doing haha, oops:)

The agenix readme at point 5 says:

Here the secret1.age file becomes part of your NixOS deployment, i.e. moves into the Nix store.

Sure that is for reproducibility reasons and the age file is stored in encrypted form, but be aware that it lands in the world readable store.

1 Like