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
.
inputs.secrix.url = "github:Platonic-Systems/secrix";
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
).
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 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.
The age bin to use for encryption and decryption.
- Type: String
- Default:
"${pkgs.age}/bin/age"
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"
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:
{}
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..."
The name of the directory for system secrets. It will end up as /run/<name>
.
- Type: String
- Default:
system-keys
Permissions for the directory containing system secrets.
- Type: String
- Default:
111
The user that owns the directory for system secrets.
- Type: String
- Default:
"0"
The group that owns the directory for system secrets.
- Type: String
- Default:
"0"
The name of the service that manages system secrets.
- Type: String
- Default:
"system-keys"
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:
{}
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>
Public keys with which to encrypt the secret.
- Type: AttrSet of Lists of Strings
- Default:
secrix.defaultEncryptKeys
Local location of the secret.
- Type: Path
The name of the decrypted file on disk. This defaults to the secret name.
- Type: String
- Default:
secrix.system.secrets.<name>.name
Permissions of the secret when decrypted.
- Type: String
- Default:
"0400"
Secret user.
- Type: String
- Default:
"0"
Secret group.
- Type: String
- Default:
"0"
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
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
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:
{}
The directory name for the service secrets.
- Type: String
- Default:
"<name>-keys"
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>
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:
[]
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
The name of the service that will decrypt the keys.
- Type: String
- Default:
<name>-keys
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
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>
Public keys with which to encrypt the secret.
- Type: AttrSet of Lists of Strings
- Default:
secrix.defaultEncryptKeys
Local location of the secret.
- Type: Path
The name of the decrypted file on disk. This defaults to the secret name.
- Type: String
- Default:
secrix.services.<service>.secrets.<name>.name
Permissions of the secret when decrypted.
- Type: String
- Default:
0400
Secret user.
- Type: String
- Default:
systemd.services.<service>.serviceConfig.User or "0"
Secret group.
- Type: String
- Default:
systemd.services.<service>.serviceConfig.Group or "0"
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
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