We've all been there, sharing .env
files in Slack to get an application working quickly while feeling bad about security practices. 🫠
But teams always have a shared secret or password manager, and you already have a way to access it through a CLI or service account, right?
What if you just had a nice little JSON file in your code repository that defined which environment variables to fetch from any manager through URIs?
// salakala.json
{
"DATABASE_URL": "op://application-secrets/db/url"
}
salakala does exactly that! It wraps around your manager and generates environment variables for you as .env
files or by setting variables directly in your environment.
# Install globally to use the CLI
npm install -g salakala
- Create a
salakala.json
file in your project (safe to commit to your repository!) - Run salakala to generate your
.env
file or set environment variables:
# Generate .env file in the current directory (default)
salakala
# Set environment variables in the current shell
salakala -s
# Specify an environment
salakala -e staging
# Specify a different output file
salakala -o .env.local
# Overwrite existing file instead of merging
salakala -w
# Show help
salakala --help
// salakala.json
{
"SECRET_ENV_VALUE": "op://application-secrets/test/test-section"
}
// salakala.json
{
"development": {
"SECRET_ENV_VALUE": "op://application-secrets/test/test-section"
},
"staging": {
"SECRET_ENV_VALUE": "op://application-secrets/staging/test-section"
}
}
You can use environment variables in your secret paths using ${VARIABLE_NAME}
syntax:
// salakala.json
{
"development": {
"GCP_API_KEY": "gcsm://projects/${PROJECT_ID}/secrets/api-key/versions/latest"
}
}
The environment variables must of course be set before running:
PROJECT_ID=my-project salakala
You can also include regular, non-secret values. Any value that doesn't start with a provider prefix (like op://
, gcsm://
, etc.) will be passed through:
{
"development": {
"DB_PASSWORD": "op://vault/database/password",
"APP_NAME": "My Development App",
}
}
In this example:
DB_PASSWORD
will be fetched from the secret managerAPP_NAME
will be passed through directly to the generated environment variables
1Password (op://)
Uses the 1Password CLI to fetch secrets. Requires the op
CLI to be installed.
- ✅ Tested against a real 1Password account in CI
- 🧑💻 Interactive login via invoking
op
- 🤖 Noninteractive login using environment variables
Format:
op://vault-name/item-name/[section-name/]field-name
Example:
op://Personal/AWS/access-key
Bitwarden (bw://)
Uses the Bitwarden CLI (bw
) to fetch secrets. Requires the bw
CLI to be installed. Supports different vault locations.
- ✅ Tested against a real Bitwarden account in CI
- 🧑💻 Interactive login via invoking
bw
- 🤖 Noninteractive login using environment variables
Format:
bw://[folder]/item-name-or-id/field::json-key
Example: Plaintext field via item ID:
bw://1c9448b3-3d30-4f01-8d3c-3a4b8d14d00a/password
Example: Plaintext field via item name:
bw://my-folder/my-item/password
Example: JSON field via item name:
bw://my-folder/my-item/notes::foo.bar[1]
This expects that the item has a notes
field that is a JSON object. It will return the value of the foo.bar[1]
key.
Example: URI from a login item:
bw://my-folder/my-item/uris/0
This would get the first URI from the uris
field.
KeePassXC (kp://)
Uses the KeePassXC CLI to fetch secrets from a KeePass database. Requires the `keepassxc-cli` CLI to be installed.
- ✅ Tested against a real KeePass database in CI
- 🧑💻 Interactive login via invoking
keepassxc-cli
- 🤖 Noninteractive login using environment variables
Format:
kp://path/to/database.kdbx/entry-path/field
Example:
kp:///Users/me/secrets.kdbx/Web/GitHub/Password
Notes:
- To find field titles, you can use the
keepassxc-cli
command:keepassxc-cli show "/path/to/database.kdbx" "entry-name"
AWS Secrets Manager (awssm://)
Fetches secrets from AWS Secrets Manager. Requires some form of AWS credentials to be configured. Uses the AWS SDK to fetch secrets.
- ✅ Tested against a real AWS account in CI
- 🧑💻 Semi-interactive login
- 🤖 Noninteractive login using environment variables
Format:
awssm://region/secret-name[:key]
Example: Plaintext secret:
awssm://us-east-1/prod/api-key
Example: JSON object:
awssm://us-east-1/prod/database
This will fetch the entire JSON object in the database
secret and pass it through as a JSON string.
Example: Specific key in JSON object:
awssm://us-east-1/prod/database::password
This will fetch the password
key from the JSON object in the database
secret.
Google Cloud Secret Manager (gcsm://)
Fetches secrets from Google Cloud Secret Manager. Requires Google Cloud credentials to be configured. Uses the Google Cloud SDK to fetch secrets.
- ✅ Tested against a real Google Cloud project in CI
- 🧑💻 Semi-interactive login
- 🤖 Noninteractive login using environment variables
Format:
gcsm://projects/project-id/secrets/secret-id/versions/version[:key]
Example: Plaintext secret:
gcsm://projects/my-project/secrets/api-key/versions/latest
Example: JSON object:
gcsm://projects/my-project/secrets/database/versions/latest
This will fetch the entire JSON object in the database
secret and pass it through as a JSON string.
Example: Specific key in JSON object:
gcsm://projects/my-project/secrets/database/versions/latest::password
This will fetch the password
key from the JSON object in the database
secret.
LastPass (lp://)
Uses the LastPass CLI to fetch secrets. Requires the lpass
CLI to be installed.
❌ Needs testing
Format:
lp://group/item-name[/field]
Example:
lp://Personal/AWS/api-key
Azure Key Vault (azurekv://)
Fetches secrets from Azure Key Vault. Requires Azure credentials to be configured. Uses the Azure SDK to fetch secrets.
❌ Needs testing
Format:
azurekv://vault-name.vault.azure.net/secret-name
Example:
azurekv://my-vault.vault.azure.net/database-password
HashiCorp Vault (hcv://)
Fetches secrets from HashiCorp Vault. Requires the VAULT_ADDR
and VAULT_TOKEN
environment variables to be set. Uses the HashiCorp Vault SDK to fetch secrets.
❌ Needs testing
Format:
hcv://vault-address/secret/path
Example:
hcv://vault.example.com:8200/secret/data/database/credentials
Doppler (doppler://)
Uses the Doppler CLI to fetch secrets. Requires the Doppler CLI to be installed.
❌ Needs testing
Format:
doppler://project/config/secret-name
Example:
doppler://my-project/dev/DATABASE_URL
Infisical (inf://)
Uses the Infisical CLI to fetch secrets. Requires the Infisical CLI to be installed.
❌ Needs testing
Format:
inf://workspace/environment/secret-name
Example:
inf://my-project/dev/DATABASE_URL
- ✅ DO commit
salakala.json
- it should only contain paths to secrets, not the secrets themselves - ❌ DON'T commit generated
.env
files - Add
.env*
to your.gitignore
Contributions are welcome! Feel free to submit issues and pull requests.
MIT