A collection of mix tasks to interact with age. Inspired by rails credential management. Born from frustration of desync secrets.
Thanks to @FiloSottile for building age <3.
And thanks to the maintainers of phoenixframework/tailwind which I leaned on heavily while implementing this <3.
This isn't currently well tested (only on mac). I will try to upgrade this as soon as I am able to test on different platforms.
def deps do
[
{:secret_mana, "~> 0.0.1"}
]
endconfig :secret_mana,
backend: SecretMana.AgeBackend,
otp_app: :my_app
config :secret_mana, SecretMana.AgeBackend,
version: "1.2.1" # default: "1.2.1", used to specify version installed
local_install: true/false # default: "true"; if false installation is always skipped. Then you can either manually set `bin_dir` or let the backend handle the finding of the binaries (by using which/where).
Useful to bundle binaries in deployments
bin_dir: "my_bin_path" # see `local_install`
secret_base_path: "config/custom_secrets_folder" # default: "config/secrets"; path SecretMana will put files in, useful to scope for different environments
key_file: "my.key" # default: "age.key"; used to rename key-file; stored under base_path
pub_key_file: "my.key.pub" # default: "age.pub"; used to rename pub-key-file; stored under base_path
encrypted_file: "secret.enc" # default: "age.enc"; used to rename secret-file; stored under base_path
file_type: :yaml # default: :json; currently only json and yaml are supported,
binary: "age" # default: "age", only required if binary name differs from default
key_generator_binary: "age-keygen" # default: "age-keygen", only required if keygen-binary name differs from default,
mix secret_mana.install - install
mix secret_mana.gen.key <env> - generates a new key pair depending on your config
mix secret_mana.encrypt <env> <file> - encrypts a given json/yaml file and stores it accordingly to your config
EDITOR="code --wait" mix secret_mana.edit <env> - allows editing your secrets (falls back to vim)
Its as simple as this:
# read all secrets
SecretMana.read!()
# read specific secret
SecretMana.read!(["foo", "bar"])
Note: read! will raise an error if the requested key is not found, with helpful information about available keys.
Copyright (c) 2025 Nick Duitz.
age source code is licensed under the BSD 3-Clause "New" or "Revised" License.