2023-09-26 13:51:15 +00:00
|
|
|
# ess (env sample sync)
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-06-08 13:56:58 +00:00
|
|
|
[](https://app.gitter.im/#/room/#env-sample-sync-dev:gitter.im)
|
|
|
|
|
|
2024-10-25 20:03:42 +00:00
|
|
|
Automatically keep `env.sample` files in sync with `.env`
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
---
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2025-04-11 00:28:54 +00:00
|
|
|
`ess` transforms environment files containing secrets (e.g. `.env`, `.envrc`) into sample environment files (e.g.
|
2024-01-20 00:23:56 +00:00
|
|
|
`env.sample`) that may be safely checked into git.
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2024-01-20 00:23:56 +00:00
|
|
|
`ess` may be run manually by running the cli executable, or automatically by installing the pre-commit hook with `ess install`
|
2025-04-11 00:28:54 +00:00
|
|
|
in any git repository. Installing `ess` as a git hook ensures that project environment files are automatically and safely
|
|
|
|
|
revision controlled when they change.
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2024-01-20 00:23:56 +00:00
|
|
|
Doing so allows environment configurations to be shared across teams without leaking secrets.
|
|
|
|
|
|
2025-04-11 00:28:54 +00:00
|
|
|
## How it works
|
2024-01-20 00:23:56 +00:00
|
|
|
|
|
|
|
|
By default, `ess` checks the local directory for environment files named `.env`. The env file name is controlled by
|
2025-04-11 00:28:54 +00:00
|
|
|
the `--env-file` switch. Next, the environment file is parsed for environment variables. Environment variables
|
2024-01-20 00:23:56 +00:00
|
|
|
may be of the following forms:
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
# Standard environment variables
|
|
|
|
|
FOO=bar baz
|
|
|
|
|
FOO="bar baz"
|
|
|
|
|
FOO='bar baz'
|
|
|
|
|
|
|
|
|
|
# Envrc environment variable
|
|
|
|
|
export FOO=bar baz
|
|
|
|
|
export FOO="bar baz"
|
|
|
|
|
export FOO='bar baz'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
By default, variable values are replaced with innert values named after the variable, e.g. `FOO=bar` is replaced by `FOO=<FOO>`.
|
|
|
|
|
|
2025-04-11 00:28:54 +00:00
|
|
|
Example values may be provided with the `--example` switch, e.g. `--exmaple=FOO="enter your foo here"` will set `FOO`'s
|
|
|
|
|
value as follows `FOO="enter your foo here"` in the sample file.
|
2024-01-20 00:23:56 +00:00
|
|
|
|
2025-04-11 00:28:54 +00:00
|
|
|
Finally, when all variables are replaced, the sample file is written with the sanitized variable values, along with all
|
2024-01-20 00:23:56 +00:00
|
|
|
non-variable strings from the file. By default the sample file is named `env.sample`, which is controlled by the `--env-sample`
|
2025-04-11 00:28:54 +00:00
|
|
|
switch.
|
2024-01-20 00:23:56 +00:00
|
|
|
|
2025-04-11 00:28:54 +00:00
|
|
|
Because `ess` permits non-variable strings in environment files, it means that both comments and script code (in the case
|
|
|
|
|
of `.envrc` files) is included in environment sample files. This allows environment files to not only be checked into git, but
|
|
|
|
|
documented with comments.
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
# Installation & Usage
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
`ess` can be run in three ways:
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
1. Manually
|
|
|
|
|
2. As a native git-hook
|
|
|
|
|
3. As a [pre-commit plugin](https://pre-commit.com/#install) (a utility for organizing pre-commit hooks)
|
|
|
|
|
|
|
|
|
|
## Installation
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
Installation is required to run `ess` manually, or as a native git hook. See [pre-commit configuration]
|
2023-09-09 07:49:30 +00:00
|
|
|
(#running-as-a-pre-commit-plugin) for pre-commit usage.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
**Install from the releases page**
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
Download [the latest release](https://github.com/acaloiaro/ess/releases/latest) and add it to your `$PATH`.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
**Install with `go install`**
|
2022-11-26 16:05:23 +00:00
|
|
|
|
|
|
|
|
```bash
|
2023-09-26 13:51:15 +00:00
|
|
|
go install github.com/acaloiaro/ess@latest
|
2023-05-29 16:54:11 +00:00
|
|
|
```
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-09-09 07:49:30 +00:00
|
|
|
**Nix Flake**
|
|
|
|
|
|
|
|
|
|
This application may be added as a flake input
|
|
|
|
|
|
|
|
|
|
**flake.nix**
|
|
|
|
|
```nix
|
2023-09-26 13:51:15 +00:00
|
|
|
inputs.ess = {
|
|
|
|
|
url = "github:acaloiaro/ess";
|
2023-09-09 07:49:30 +00:00
|
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**configuration.nix**
|
|
|
|
|
```nix
|
|
|
|
|
users.users.<USERNAME>.packages = [
|
|
|
|
|
...
|
2023-09-26 13:51:15 +00:00
|
|
|
inputs.ess.packages.${system}.default
|
2023-09-09 07:49:30 +00:00
|
|
|
];
|
|
|
|
|
```
|
|
|
|
|
|
2024-10-10 17:51:28 +00:00
|
|
|
Or simply run directly
|
2023-09-09 07:49:30 +00:00
|
|
|
```bash
|
2023-09-26 13:55:04 +00:00
|
|
|
nix run github:acaloiaro/ess
|
2023-09-09 07:49:30 +00:00
|
|
|
```
|
|
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
## Running manually
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
`ess` can be run with no arguments to use defaults.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
**Sync `.env` with `env.sample`**
|
|
|
|
|
|
|
|
|
|
```bash
|
2023-09-26 13:51:15 +00:00
|
|
|
ess
|
2022-11-26 16:05:23 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
**With a non-default `.env` and `env.sample` location**
|
2022-11-26 16:05:23 +00:00
|
|
|
|
|
|
|
|
```bash
|
2023-09-26 13:51:15 +00:00
|
|
|
ess --env-file=.env-file-name --sample-file=env-sample-file-name
|
2023-05-29 16:54:11 +00:00
|
|
|
```
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
**Provide example values for variables**
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
By default, `ess` uses the name of environment variables in `<brackets>` as example values in `env.sample`,
|
2023-09-09 07:49:30 +00:00
|
|
|
e.g. `FOO=secret value` is replaced with `FOO=<FOO>`. This behavior is customizable wit the `--example` flag.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
Add custom examples for variables `FOO` and `BAR`.
|
|
|
|
|
|
|
|
|
|
```bash
|
2023-09-26 13:51:15 +00:00
|
|
|
ess --example=FOO="must be a valid UUID" --example=BAR="bars must be a positive integer"
|
2023-05-29 16:54:11 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The above invocation yields the following `env.sample`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
FOO=must be a valid UUID
|
|
|
|
|
|
|
|
|
|
BAR=bars must be a positive integer
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Running as a native git-hook
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
To add `ess` as a pre-commit git hook in a git repository, run:
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
```bash
|
2023-09-26 13:51:15 +00:00
|
|
|
ess install
|
2022-11-26 16:05:23 +00:00
|
|
|
```
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
This installs `ess` as a pre-commit git hook with default arguments.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
The `install` command supports all [command flags](#command-flags).
|
|
|
|
|
|
2023-09-26 13:51:15 +00:00
|
|
|
If you need to change `ess` flags, simply run `ess install` again with the desired flags and
|
2023-09-09 07:49:30 +00:00
|
|
|
choose the overwrite [o] option when prompted what to do with the existing pre-commit hook.
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
## Running as a pre-commit plugin
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
This utility can be used as a [pre-commit plugin](https://pre-commit.com/#install)
|
2022-11-26 16:05:23 +00:00
|
|
|
|
|
|
|
|
## Add configuration
|
|
|
|
|
```bash
|
2025-04-11 00:29:04 +00:00
|
|
|
cat <<EOF >.pre-commit-config.yaml
|
2022-11-26 16:05:23 +00:00
|
|
|
repos:
|
2023-09-26 13:51:15 +00:00
|
|
|
- repo: https://github.com/acaloiaro/ess.git
|
2025-04-12 14:25:05 +00:00
|
|
|
rev: v2.18.0
|
2022-11-26 16:05:23 +00:00
|
|
|
hooks:
|
2023-09-26 13:51:15 +00:00
|
|
|
- id: ess
|
2022-11-26 16:05:23 +00:00
|
|
|
EOF
|
|
|
|
|
pre-commit install
|
2023-05-29 16:54:11 +00:00
|
|
|
git add .pre-commit-config.yaml
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
See [pre-commit configuration examples](#pre-commit-configuration-examples) for additional pre-commit documentation.
|
|
|
|
|
|
|
|
|
|
# Background
|
|
|
|
|
|
2023-09-09 07:49:30 +00:00
|
|
|
It's important to document the environment variables required to run applications, both in production and development. A
|
|
|
|
|
great way to do so is with `env.sample` files, but sample files tend to get out of date very quickly.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
2024-10-10 17:51:28 +00:00
|
|
|
For example, let's say you're adding a new feature to your application, and it requires the variable `FOO` to be set.
|
2023-09-09 07:49:30 +00:00
|
|
|
While you're developing locally, you likely have a `.env` file that looks something like:
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
APPLICATION_SECRET=supersekrit
|
|
|
|
|
|
|
|
|
|
# I got this FOO from the detailed process documented at: http:://wiki.example.com/how_to_get_a_foo
|
|
|
|
|
FOO="My super secret value for foo"
|
|
|
|
|
```
|
|
|
|
|
|
2023-09-09 07:49:30 +00:00
|
|
|
Working on large teams, it's common to share these `.env` files somewhere secure where all developers have access to
|
|
|
|
|
them. Retrieval is often integrated into application startup and/or bootstrap processes.
|
2023-05-29 16:54:11 +00:00
|
|
|
|
2023-09-09 07:49:30 +00:00
|
|
|
But working on open source projects or teams with less trust and less shared infrastructure, it's more common to share
|
2023-09-26 13:51:15 +00:00
|
|
|
an `env.sample`. `ess` automatically keeps the sample file in sync with `.env`, so you don't have to. Your
|
2023-09-09 07:49:30 +00:00
|
|
|
`.env` file stays the same, and is automatically converted to the following `env.sample`:
|
2023-05-29 16:54:11 +00:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
APPLICATION_SECRET=<APPLICATION_SECRET>
|
|
|
|
|
|
|
|
|
|
# I got this FOO from the detailed process documented at: http:://wiki.example.com/how_to_get_a_foo
|
|
|
|
|
FOO=<FOO>
|
2022-11-26 16:05:23 +00:00
|
|
|
```
|
|
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
It's even possible to provide default/example values for every environment variables with the `--example` [flag](#command-flags).
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
## Command Flags
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-09-09 07:49:30 +00:00
|
|
|
| Name | Description | Example | Default |
|
|
|
|
|
| --------------- | --------------------------------------------------- | --------------------------------------------------------- | ----------------------------- |
|
2023-05-30 02:07:35 +00:00
|
|
|
| `--env-file` | The name of the environment file | `--env-file=.secrets` | `--env-file=.env` |
|
2024-10-25 20:18:58 +00:00
|
|
|
| `--debug` | Enable debugging | `--debug` | `false` |
|
|
|
|
|
| `--skip-git-add` | Skip performing `git add` after syncing | `--skip-git-add` | `false` |
|
2023-05-30 02:07:35 +00:00
|
|
|
| `--sample-file` | The name of the sample environment file | `--sample-file=secrets.example` | `--sample-file=env.sample` |
|
2024-10-25 20:18:58 +00:00
|
|
|
| `--example` | Provide examples for specific environment variables | `--example=FOO="Example FOO" --example=BAR="Example BAR"` | `--example=VAR=<VAR>` |
|
2022-11-26 16:05:23 +00:00
|
|
|
|
2023-05-29 16:54:11 +00:00
|
|
|
## Pre-commit Configuration Examples
|
2022-11-26 16:05:23 +00:00
|
|
|
|
|
|
|
|
### Default configuration
|
|
|
|
|
|
|
|
|
|
```yml
|
|
|
|
|
repos:
|
2023-09-26 13:51:15 +00:00
|
|
|
- repo: https://github.com/acaloiaro/ess.git
|
2025-04-12 14:25:05 +00:00
|
|
|
rev: v2.18.0
|
2022-11-26 16:05:23 +00:00
|
|
|
hooks:
|
2023-09-26 13:51:15 +00:00
|
|
|
- id: ess
|
2022-11-26 16:05:23 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Customize `.env` and `env.sample` paths
|
|
|
|
|
|
|
|
|
|
```yml
|
|
|
|
|
repos:
|
2023-09-26 13:51:15 +00:00
|
|
|
- repo: https://github.com/acaloiaro/ess.git
|
2025-04-12 14:25:05 +00:00
|
|
|
rev: v2.18.0
|
2022-11-26 16:05:23 +00:00
|
|
|
hooks:
|
2023-09-26 13:51:15 +00:00
|
|
|
- id: ess
|
2022-11-26 16:05:23 +00:00
|
|
|
args: ['--env-file=.env_file', '--sample-file=env_file.sample']
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Customize variable example values
|
|
|
|
|
|
2024-10-10 17:51:28 +00:00
|
|
|
Sometimes environment variables need to conform to specific formats, and it's necessary to provide better documentation.
|
2023-09-09 07:49:30 +00:00
|
|
|
For this reason, environment variable examples may be provided in lieu of the default behavior, which is to use the
|
|
|
|
|
environment variable name surrounded by `<brackets like this>` in sample files.
|
2022-11-26 16:05:23 +00:00
|
|
|
|
|
|
|
|
```yml
|
|
|
|
|
repos:
|
2023-09-26 13:51:15 +00:00
|
|
|
- repo: https://github.com/acaloiaro/ess.git
|
2025-04-12 14:25:05 +00:00
|
|
|
rev: v2.18.0
|
2022-11-26 16:05:23 +00:00
|
|
|
hooks:
|
2023-09-26 13:51:15 +00:00
|
|
|
- id: ess
|
2022-11-26 16:05:23 +00:00
|
|
|
args: [--example=FOO="Provide your foo here", --example=BAR="You can fetch bars from https://example.com/bars"]
|
|
|
|
|
```
|
|
|
|
|
|
2024-01-20 00:23:56 +00:00
|
|
|
Example environment file
|
2022-11-26 16:05:23 +00:00
|
|
|
`.env`
|
|
|
|
|
```
|
|
|
|
|
FOO=the_value_of_my_secret_foo
|
|
|
|
|
BAR=the_value_of_my_secret_bar
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Example sample file output
|
|
|
|
|
`env.sample`
|
|
|
|
|
```bash
|
|
|
|
|
FOO=Provide your foo here
|
|
|
|
|
BAR=You can fetch bars from https://example.com/bars
|
|
|
|
|
```
|