An open API service indexing awesome lists of open source software.

https://github.com/atty303/mise-dotenv-sops

Load .env values from YAML/JSON/dotenv with optional SOPS decryption, variable expansion and command substitution — directly from Mise
https://github.com/atty303/mise-dotenv-sops

dotenv dotenvx mise mise-plugin sops

Last synced: 9 months ago
JSON representation

Load .env values from YAML/JSON/dotenv with optional SOPS decryption, variable expansion and command substitution — directly from Mise

Awesome Lists containing this project

README

          

# mise-dotenv-sops

[![Build](https://github.com/atty303/mise-dotenv-sops/actions/workflows/build.yaml/badge.svg?event=push)](https://github.com/atty303/mise-dotenv-sops/actions/workflows/build.yaml)
[![MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://github.com/atty303/mise-dotenv-sops/blob/main/LICENSE)

Load `.env` values from YAML/JSON/dotenv with
optional [SOPS](https://getsops.io/)
decryption, variable expansion (`$VAR`) and command substitution (`$(cmd)`) —
directly from [Mise](https://mise.jdx.dev/).

- Cleanly loads environment variables from `.env`, `.env.yaml`, and `.env.json`
files in your
project.
- Decrypts SOPS-encrypted files when needed.
- Supports `$VAR` expansion and `$(command)` substitution.
- Respects ordered `MISE_ENV` like `stg,prod` with last-one-wins merging.

## Quickstart

```bash
# install the plugin (once per machine)
❯ mise plugin install dotenv-sops https://github.com/atty303/mise-dotenv-sops.git

# in your project
❯ mise set "_.dotenv-sops="
❯ echo '{"URL":"http://localhost:3000"}' > .env.json

# show effective environment
❯ mise env --dotenv
URL=http://localhost:3000
```

A full example is available in [example/complete](./example/complete).

## Features

- Load dotenv, YAML, and JSON `.env` files
- `MISE_ENV` supports comma-separated ordered environments (e.g. `stg,prod`)
- Variable expansion: `$VAR`
- Command substitution: `$(command)`
- Flatten nested keys using a configurable separator
- SOPS-aware: auto-decrypt if sops metadata is present

## Requirements

- [`mise`](https://mise.jdx.dev/)
- `mise use sops` (only when decrypting encrypted files)
- `mise use yq` (reading plain YAML when `yq = true`)

## Usage

Minimal `mise.toml` (see example/complete for a full version):

```toml
[env._.dotenv-sops]
# log level: "debug" | "info" | "warn" | "error" | "off" (default: "off")
log = "off"
# allow $(...) command substitution (default: false)
command = false
# allow $VAR expansion (default: true)
env = true
# separator for flattening nested keys (default: "_")
sep = "_"
# stop on failure; when false, continue and log errors (default: true)
strict = true
# use slower but complete yq parser instead of lua-tinyyaml (default: false)
yq = false
```

### SOPS decryption

When decrypting a file with the corresponding identity, SOPS will look for a
text file name `keys.txt` located in a `sops` subdirectory of your user
configuration directory:

- On Linux, this would be `$XDG_CONFIG_HOME/sops/age/keys.txt`.
- On macOS, this would be `$HOME/Library/Application Support/sops/age/keys.txt`.
- On Windows, this would be `%AppData%\sops\age\keys.txt`.

You can specify the location of this file manually by setting the environment
variable `SOPS_AGE_KEY_FILE` or `MISE_SOPS_AGE_KEY_FILE`.
Alternatively, you can provide the key(s) directly by setting the `SOPS_AGE_KEY`
or `MISE_SOPS_AGE_KEY` environment variable.

`MISE_SOPS_AGE_KEY` and `MISE_SOPS_AGE_KEY_FILE` are prioritized over
`SOPS_AGE_KEY` and `SOPS_AGE_KEY_FILE`.
And it can share
with [Mise's secrets feature](https://mise.jdx.dev/environments/secrets.html).

### SOPS encryption

Nothing special. Just use `sops` CLI.
See [SOPS documentation](https://getsops.io/docs/).

### File loading order

Files are loaded from the current directory only. When `MISE_ENV=ENV1,ENV2`,
existing files are read in this order and merged; later entries win.

- `.env`, `.env.json`, `.env.yaml`
- `.env.local`, `.env.local.json`, `.env.local.yaml`
- `.env.`, `.env..json`, `.env..yaml`
- `.env..local`, `.env..local.json`, `.env..local.yaml`
- `.env.`, `.env..json`, `.env..yaml`
- `.env..local`, `.env..local.json`, `.env..local.yaml`

## Tips & FAQ

- Nothing loaded?
- Turn on debug logs to see what’s happening: set `log = "debug"` in your
`mise.toml`, then run `mise env` to view file discovery, decryption, and
resolving steps.
- Can I reference outer environment variables in expansions?
- Yes. Later values in the same file can reference earlier ones, too.
- Is command substitution risky?
- It is disabled by default. Enable only in trusted projects.
- `mise env --env NAME` doesn’t load variables from `.env.NAME.yaml`
- The `--env` global option only affects `mise.toml` loading; it doesn’t
affect plugins. Use `MISE_ENV=NAME mise env`.
- My YAML file is not parsed correctly
- Use `yq = true` to use `yq` instead of `lua-tinyyaml`.

## Security notes

- Keep `command = false` unless you fully trust the repository.
- Review `.env.*` files for unintended secrets before committing.

## Development

Local link plugin for development:

```bash
mise plugin link dotenv-sops . --force
```

Run tests:

```bash
mise run test
```

How tests work:

- Compare `mise env -J` output with each case’s `expected.yaml`.
- SOPS keys are set temporarily according to `expected.yaml` using
`MISE_SOPS_AGE_KEY` / `MISE_SOPS_AGE_KEY_FILE`.

## Roadmap

- [ ] Import another dotenv file from dotenv files
- [ ] Use cache for speed optimization
- [ ] Support TOML and INI formats