Skip to content

Platonic-Systems/secrix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Secrix

Secrex is based on ideas in agenix, however is written from the ground up.

Secrix allows you to bind secrets to systemd services to ensure that their lifetime is only as long as the service itself. As well, it allows for system secrets, which are by default bound to the lifetime of the system. All secrets are stored in virtual memory and do not end up on disk.

Creating a service secret is as easy as secrix.services.<systemd-service>.secrets.<name>.encrypted.file. Its final location will end up in secrix.services.<systemd-service>.secrets.<name>.decrypted.path. System secrets are defined as secrix.system.secrets, with the same pattern as service secrets, minus the service.

For encryption/decryption usage, see nix run .#secrix -- --help.

Adding Secrix

inputs.secrix.url = "github:Platonic-Systems/secrix";

Getting Started

In your flake.nix, simply define an app as such:

{
    apps.x86_64-linux.secrix = inputs.secrix.secrix self;
}

This in and of itself is enough to start using Secrix. Ideally, for ease of use, you should define some options that will make your life easier when using Secrix. Defining secrix.defaultEncryptKeys (or encryptKeys for any given secret) as an attribute set as such:

secrix.defaultEncryptKeys = {
    my-user = [ "my-key" ];
}

will allow you to use -u my-user when encrypting a secret. Similarly, defining secrix.hostPubKey for some nixosConfigurations will allow you to use -s my-host (assuming outputs.nixosConfigurations.my-host).

Defining Secrets

Binding a Secret to a Service

Service secrets are bound specifically to systemd services. For example, Minio:

{
    secrix.services.minio.secrets.minio-rootCreds.encrypted.file = ./secrets/minio-rootCreds;
    minio = {
        ...
        rootCredentialsFile = config.secrix.services.minio.secrets.minio-rootCreds.decrypted.path;
    };
}

This will ensure that the secret itself is owned and accessible by the minio user and will only be extant while minio is up.

System Secrets

System secrets are not bound to anything except the system's lifetime via their own service. For example:

{
    secrix.system.secrets.my-secret.encrypted.file = ./secrets/my-secret;
}

secrix.system.secrets.my-secret.decrypted.path can be used to get its final path on the system when decrypted.

Options

secrix.ageBin

The age bin to use for encryption and decryption.

  • Type: String
  • Default: "${pkgs.age}/bin/age"

secrix.hostIdentityFile

The path of the private key of the host that will be decrypting the secret. This path is used on the target host.

  • Type: String
  • Default: "/etc/ssh/ssh_host_ed25519_key"

secrix.defaultEncryptKeys

The default encryption keys for all secrets. This will be overriden for any given secret if encryptKeys is specified for that secret.

  • Type: AttrSet of Lists of Strings
  • Default: {}

secrix.hostPubKey

The public key for the host that the secrets will exist on. Specify in OpenSSH public key format.

  • Type: Null or String
  • Default: null
  • Example: "ssh-ed25519 AAAAC3Nz..."

secrix.system.secretsDir.name

The name of the directory for system secrets. It will end up as /run/<name>.

  • Type: String
  • Default: system-keys

secrix.system.secretsDir.permissions

Permissions for the directory containing system secrets.

  • Type: String
  • Default: 111

secrix.system.secretsDir.user

The user that owns the directory for system secrets.

  • Type: String
  • Default: "0"

secrix.system.secretsDir.group

The group that owns the directory for system secrets.

  • Type: String
  • Default: "0"

secrix.system.secretsServiceName

The name of the service that manages system secrets.

  • Type: String
  • Default: "system-keys"

secrix.system.secrets

An attribute set of secrets that will be decrypted on the system. System secrets will be decrypted at system start and will exist decrypted for the uptime of the system but will not remain on disk if the system is shut down sanely.

  • Type: AttrSet of Submodules
  • Default: {}

secrix.system.secrets.<name>.name

The name of the secret. This defaults to the attribute name. This is simply a referential token to the secret, however if no name is set for the decrypted file, this will be used.

  • Type: String
  • Default: <name>

secrix.system.secrets.<name>.encryptKeys

Public keys with which to encrypt the secret.

  • Type: AttrSet of Lists of Strings
  • Default: secrix.defaultEncryptKeys

secrix.system.secrets.<name>.encrypted.file

Local location of the secret.

  • Type: Path

secrix.system.secrets.<name>.decrypted.name

The name of the decrypted file on disk. This defaults to the secret name.

  • Type: String
  • Default: secrix.system.secrets.<name>.name

secrix.system.secrets.<name>.decrypted.mode

Permissions of the secret when decrypted.

  • Type: String
  • Default: "0400"

secrix.system.secrets.<name>.decrypted.user

Secret user.

  • Type: String
  • Default: "0"

secrix.system.secrets.<name>.decrypted.group

Secret group.

  • Type: String
  • Default: "0"

secrix.system.secrets.<name>.decrypted.path

The path to the secret when decrypted on disk. This is automatically set by secrix and is available only for reference.

  • Type: String
  • Default: "/run/${secrix.system.secretsDir.name}/${secrix.system.secrets.<name>.name}"
  • Read Only

secrix.system.secrets.<name>.decrypted.builder

A builder script (if needed) to perform additional actions on the secret before it ends up in its final location.

If this is a function that yields a string, it will be passed a single argument which is the final location of the built file.

If this is a string, a special bash variable $inFile can be used to reference the secret as it is, however there will be no reference available to its final destination as that will be up to the builder. Use a string only if you know what you're doing.

  • Type: Null or Either Lines or String -> Lines
  • Default: null

secrix.services

An attribute set of systemd service names to which to bind secrets. All secrets bound to a service will exist only for the lifetime of the service.

  • Type: AttrSet of Submodules
  • Default: {}

secrix.services.<service>.secretsDirName

The directory name for the service secrets.

  • Type: String
  • Default: "<name>-keys"

secrix.services.<service>.systemdService

The name fo the systemd service that the secrets contained within will be bound to. This defaults to the attribute name.

  • Type: String
  • Default: <service>

secrix.services.<service>.additionalRuntimeDirNames

In the case that the systemd service these secrets will be bound to has a RuntimeDirectory specified as a string, secrix will be unable to add an additional RuntimeDirectory, so add that here.

  • Type: List of Strings
  • Default: []

secrix.services.<service>.forceRuntimeDirs

Set this to true of the service these secrets will be bound to has a RuntimeDirectory already specified as a string.

  • Type: Boolean
  • Default: false

secrix.services.<service>.secretsServiceName

The name of the service that will decrypt the keys.

  • Type: String
  • Default: <name>-keys

secrix.services.<service>.secrets

An attribute set of secrets that will be decrypted on the system. Service secrets will be decrypted at the start of and will exist for the lifetime of the service they are bound to.

  • Type: AttrSet of Submodules

secrix.services.<service>.secrets.<name>.name

The name of the secret. This defaults to the attribute name. This is simply a referential token to the secret, however if no name is set for the decrypted file, this will be used.

  • Type: String
  • Default: <name>

secrix.services.<service>.secrets.<name>.encryptKeys

Public keys with which to encrypt the secret.

  • Type: AttrSet of Lists of Strings
  • Default: secrix.defaultEncryptKeys

secrix.services.<service>.secrets.<name>.encrypted.file

Local location of the secret.

  • Type: Path

secrix.services.<service>.secrets.<name>.decrypted.name

The name of the decrypted file on disk. This defaults to the secret name.

  • Type: String
  • Default: secrix.services.<service>.secrets.<name>.name

secrix.services.<service>.secrets.<name>.decrypted.mode

Permissions of the secret when decrypted.

  • Type: String
  • Default: 0400

secrix.services.<service>.secrets.<name>.decrypted.user

Secret user.

  • Type: String
  • Default: systemd.services.<service>.serviceConfig.User or "0"

secrix.services.<service>.secrets.<name>.decrypted.group

Secret group.

  • Type: String
  • Default: systemd.services.<service>.serviceConfig.Group or "0"

secrix.services.<service>.secrets.<name>.decrypted.path

The path to the secret when decrypted on disk. This is automatically set by secrix and is available only for reference.

  • Type: String
  • Default: "/run/${secrix.services.<service>.secretsDirName}/${secrix.services.<service>.secrets.<name>.name}"
  • Read Only

secrix.services.<service>.secrets.<name>.decrypted.builder

A builder script (if needed) to perform additional actions on the secret before it ends up in its final location.

If this is a function that yields a string, it will be passed a single argument which is the final location of the built file.

If this is a string, a special bash variable $inFile can be used to reference the secret as it is, however there will be no reference available to its final destination as that will be up to the builder. Use a string only if you know what you're doing.

  • Type: Null or Either Lines or String -> Lines
  • Default: null