You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enveil keeps your environment variables encrypted and out of your filesystem.
3
+
Enveil keeps your environment variables encrypted and out of your filesystem — for individuals and teams.
4
4
5
-
Instead of storing secrets in `.env` files that can be accidentally committed, leaked, or read by anyone with filesystem access, Enveil stores everything in an encrypted vault and injects variables directly into processes at runtime — without ever writing them to disk.
5
+
Most developers store secrets in `.env` files. Those files get accidentally committed to version control, shared over Slack, read by AI coding tools with filesystem access, and left behind on old machines. Enveil eliminates the file entirely. Secrets live in an encrypted vault and are injected directly into your process at runtime — they never touch disk as plaintext, not even temporarily.
6
+
7
+
For teams, Enveil goes further: a self-hosted server lets every developer share the same encrypted secrets without `.env` files, chat messages, or shared drives. One developer sets a variable; everyone else has it immediately.
6
8
7
9
## How it works
8
10
9
-
Enveil uses a SQLCipher-encrypted SQLite vault stored at `~/.enveil/vault.db`. The master key never touches disk — it lives only in memory while the daemon is running, or is derived fresh from your password on each command. Variables are organized by project and environment, making it easy to manage development, staging, and production secrets separately.
11
+
When you run `enveil run npm run dev`, Enveil:
12
+
13
+
1. Derives a 256-bit key from your master password using **Argon2id** (64MB memory, 4 threads) — resistant to GPU and ASIC brute-force attacks
14
+
2. Decrypts the **SQLCipher vault** at `~/.enveil/vault.db` — the entire file is encrypted with AES-256, including table names, project names, and variable names
15
+
3. Reads the variables for the active project and environment
16
+
4. Spawns your process with those variables injected via `syscall.Exec` — no temporary files, no subshells, no intermediate writes
17
+
5. The master key lives only in memory for the duration of the command, then is gone
18
+
19
+
The vault file is opaque binary. Without the master password, it is indistinguishable from random noise.
10
20
11
-
For teams, Enveil includes a self-hosted server that centralizes secrets across developers. Variables are encrypted on the client before being sent to the server — the server never sees plaintext values.
21
+
For teams using the server, values are encrypted on the client with AES-GCM before being sent over the network. The server stores and returns ciphertext only — it never sees plaintext values, even if you trust the server operator completely.
12
22
13
23
## Installation
14
24
15
25
### Linux and macOS
26
+
16
27
```bash
17
28
curl -fsSL https://raw.githubusercontent.com/MaximoCoder/Enveil/main/install.sh | sh
18
29
```
19
30
20
-
The installer automatically detects your OS and architecture, downloads the correct binary, verifies its checksum, and installs it to `/usr/local/bin`.
31
+
The installer detects your OS and architecture, downloads the correct binary, verifies its checksum, and installs it to `/usr/local/bin`.
21
32
22
33
### Windows
23
34
24
35
Use [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install) and run the Linux installer inside it.
25
36
26
-
### Install from source
37
+
### From source
38
+
39
+
Requires Go 1.22+ and `libsqlcipher-dev` (Ubuntu/Debian) or `sqlcipher` (macOS).
27
40
28
-
Requires Go 1.22 or later and `libsqlcipher-dev` (Ubuntu/Debian) or `sqlcipher` (macOS).
29
41
```bash
30
42
go install github.com/MaximoCoder/Enveil/cli/cmd/enveil@latest
31
43
```
32
44
33
45
### Shell integration
34
46
35
-
Add this to your `~/.zshrc` or `~/.bashrc` to automatically show the active project in your prompt when you navigate to a registered directory:
47
+
Add this to your `~/.zshrc` or `~/.bashrc` to automatically show the active project and environment in your prompt when you navigate to a registered directory:
48
+
36
49
```bash
37
50
eval"$(enveil shell-init)"
38
51
```
39
52
53
+
## Quickstart
54
+
55
+
```bash
56
+
# 1. Create your vault and set a master password (run once)
57
+
enveil init
58
+
59
+
# 2. Register your project (run once per project directory)
60
+
cd~/projects/myapp
61
+
enveil init
62
+
63
+
# 3. Import your existing .env file
64
+
enveil import .env
65
+
66
+
# 4. Delete the .env file — you no longer need it
67
+
rm .env
68
+
69
+
# 5. Run your app normally
70
+
enveil run npm run dev
71
+
```
72
+
73
+
From this point on, your secrets exist only in the encrypted vault.
74
+
40
75
## Usage
41
76
42
77
### First time setup
78
+
43
79
```bash
44
80
enveil init
45
81
```
46
82
47
-
Run this once to create your vault and set your master password. Then run it again inside any project directory to register it.
83
+
Run this once globally to create your vault and set your master password. Run it again inside any project directory to register that project.
48
84
49
85
### Saving variables
86
+
50
87
```bash
51
88
enveil set DATABASE_URL=postgres://localhost/mydb
52
89
enveil set API_KEY=supersecret123
53
90
```
54
91
55
92
### Importing from an existing .env file
93
+
56
94
```bash
57
95
enveil import .env
58
96
enveil import .env.local
59
97
```
60
98
61
-
Imports all variables from the file into the active environment. Optionally deletes the original file after importing.
99
+
Imports all variables from the file into the active environment. Enveil will ask if you want to delete the original file after importing.
62
100
63
101
### Running commands with variables injected
102
+
64
103
```bash
65
104
enveil run npm run dev
66
105
enveil run python manage.py runserver
106
+
enveil run php artisan serve
67
107
enveil run printenv DATABASE_URL
68
108
```
69
109
70
-
Variables are injected into the process environment. No `.env` file is created or written to disk.
110
+
Variables are injected directly into the process environment. No `.env` file is created or written to disk at any point.
71
111
72
112
### Getting and listing variables
113
+
73
114
```bash
74
-
enveil list # show all variable names (values are masked)
115
+
enveil list # show all variable names (values are masked by default)
75
116
enveil get DATABASE_URL # get the value of a specific variable
76
117
```
77
118
78
119
### Deleting variables
120
+
79
121
```bash
80
122
enveil delete API_KEY
81
123
```
82
124
83
125
Asks for confirmation before deleting.
84
126
85
127
### Managing environments
128
+
129
+
Each project can have multiple environments. Enveil creates `development` by default.
130
+
86
131
```bash
87
-
enveil env list # list all environments
132
+
enveil env list # list all environments in the current project
88
133
enveil env add staging # create a new environment
89
-
enveil env use staging # switch active environment
134
+
enveil env add production
135
+
enveil env use staging # switch the active environment
90
136
```
91
137
138
+
All `set`, `get`, `list`, `run`, and `import` commands operate on the active environment. Switching environments is instant — no files to copy or rename.
139
+
92
140
### Comparing environments
141
+
93
142
```bash
94
143
enveil diff development staging
95
144
```
96
145
97
-
Shows which variables are missing, extra, or have different values between two environments — without revealing the values.
146
+
Shows which variables are missing, extra, or have different values between two environments — without revealing the actual values. Useful for catching configuration drift before a deployment.
98
147
99
148
### Exporting a temporary .env file
149
+
100
150
```bash
101
151
enveil export
102
152
```
103
153
104
-
For tools that require a physical `.env` file. Automatically adds `.env` to `.gitignore`. Delete it when done.
154
+
For tools that require a physical `.env` file. Automatically adds `.env` to `.gitignore`. Delete it when done — the vault is your source of truth.
105
155
106
156
### Managing projects
157
+
107
158
```bash
108
-
enveil projects # list all registered projects
109
-
enveil unregister # remove the current project from the vault
159
+
enveil projects # list all registered project directories
160
+
enveil unregister # remove the current directory from the vault
110
161
```
111
162
112
163
### Git hook
164
+
113
165
```bash
114
166
enveil hook install
115
167
```
116
168
117
-
Installs a pre-commit hook that scans staged files for secrets before every commit. Detects known secret formats (AWS keys, Stripe keys, GitHub tokens, connection strings, private keys) and high-entropy strings using Shannon entropy analysis.
169
+
Installs a pre-commit hook that scans staged files for secrets before every commit. It detects known secret formats (AWS keys, Stripe keys, GitHub tokens, connection strings, private keys) and high-entropy strings using Shannon entropy analysis.
118
170
119
171
Files like `.env` and `.env.local` are always blocked. Files like `.env.example` and `.env.template` are allowed since they are intended to contain placeholder values.
120
172
121
173
To bypass the hook when you are sure a file is safe:
174
+
122
175
```bash
123
176
ENVEIL_SKIP=1 git commit
124
177
```
125
178
126
-
To bypass all hooks entirely:
179
+
To bypass all hooks:
180
+
127
181
```bash
128
182
git commit --no-verify
129
183
```
130
184
131
185
### Daemon
132
186
133
187
The daemon keeps your master key in memory so you do not have to type your password on every command.
188
+
189
+
```bash
190
+
enveil daemon start # start the daemon, enter your password once
191
+
enveil daemon status # check if the daemon is running
192
+
enveil daemon stop # stop the daemon — the key is removed from memory immediately
193
+
```
194
+
195
+
The daemon is optional. Without it, Enveil derives the key fresh from your password on each command. With it, you type your password once per session.
196
+
197
+
The key is never written to disk — the daemon holds it in a Unix socket at `~/.enveil/daemon.sock`, accessible only to your user.
198
+
199
+
## Security verification
200
+
201
+
You can verify Enveil's security properties manually without trusting the source code.
202
+
203
+
### 1. Confirm the vault is opaque
204
+
205
+
After running `enveil init` and setting a variable:
206
+
207
+
```bash
208
+
xxd ~/.enveil/vault.db | head -5
209
+
strings ~/.enveil/vault.db
210
+
```
211
+
212
+
`xxd` will show binary data. `strings` will return nothing — there are no readable strings to extract. Every byte, including table names and variable names, is encrypted.
213
+
214
+
### 2. Confirm the wrong password is rejected
215
+
216
+
```bash
217
+
enveil daemon stop # make sure the daemon is not caching your key
218
+
enveil list # enter the wrong password
219
+
```
220
+
221
+
Enveil will refuse to open the vault and return an error. The data is never partially exposed.
222
+
223
+
### 3. Confirm variables are never written to disk during injection
224
+
225
+
```bash
226
+
# Run a command and check that no .env file was created
227
+
enveil run printenv DATABASE_URL
228
+
ls -la .env 2>/dev/null ||echo"no .env file — correct"
229
+
```
230
+
231
+
### 4. Confirm file permissions
232
+
134
233
```bash
135
-
enveil daemon start # start daemon, enter password once
136
-
enveil daemon status # check if daemon is running
137
-
enveil daemon stop # stop daemon, key is removed from memory
234
+
ls -la ~/.enveil/vault.db
138
235
```
139
236
140
-
The daemon is optional. Without it, Enveil asks for your password on each command.
237
+
The vault is created with `0600` permissions — readable and writable only by your user, not by other users on the same machine.
141
238
142
239
## Team server
143
240
144
-
The Enveil server allows teams to share encrypted secrets across developers without relying on `.env` files, chat messages, or shared drives.
241
+
The Enveil server lets teams share encrypted secrets across developers without relying on `.env` files, chat messages, or shared drives. It is self-hosted — your secrets never leave your infrastructure.
145
242
146
243
### How it works
147
244
148
-
The server stores all variables encrypted. Values are encrypted on the client before being sent over the network — the server never sees plaintext values. Even if the server is compromised, secrets remain unreadable without the API key.
245
+
Values are encrypted on the client with AES-GCM before being sent to the server. The server stores and returns ciphertext only. Even if someone gains access to the server machine or the server vault file, they cannot read the secrets without the API key used to encrypt them.
149
246
150
-
### Installing the server
247
+
### Setting up the server
151
248
152
249
Download the server binary from the [latest release](https://github.com/MaximoCoder/Enveil/releases/latest) for your platform (`enveil-server-linux-amd64`, `enveil-server-darwin-arm64`, etc.) and place it in your PATH.
153
250
154
-
### Running the server
155
251
```bash
156
252
ENVEIL_API_KEY=your-secret-key \
157
253
ENVEIL_VAULT_PASSWORD=your-vault-password \
158
254
ENVEIL_PORT=8080 \
159
255
enveil-server
160
256
```
161
257
162
-
The server stores its vault at `~/.enveil-server/vault.db` by default. You can override this with `ENVEIL_VAULT_PATH`.
258
+
The server stores its vault at `~/.enveil-server/vault.db` by default. Override with `ENVEIL_VAULT_PATH`.
163
259
164
260
For production, put the server behind a reverse proxy like nginx with HTTPS enabled.
165
261
166
-
### Connecting the CLI to the server
262
+
### Team workflow
263
+
264
+
**Admin (one time):**
265
+
167
266
```bash
168
-
enveil server connect http://your-server:8080 --key your-secret-key
enveil server connect http://your-server:8080 --key shared-api-key
272
+
273
+
# Register your project on the server
274
+
cd~/projects/myapp
275
+
enveil init
276
+
277
+
# Import your existing secrets
278
+
enveil import .env
169
279
```
170
280
171
-
Once connected, all CLI commands use the server instead of the local vault. The connection settings are saved in `~/.enveil/config.json`.
281
+
**Each developer (one time):**
282
+
172
283
```bash
173
-
enveil server status # check connection
174
-
enveil server disconnect # switch back to local vault
284
+
# Connect to the server
285
+
enveil server connect http://your-server:8080 --key shared-api-key
286
+
287
+
# Associate their local directory with the shared project
288
+
cd~/projects/myapp
289
+
enveil server use-project myapp
175
290
```
176
291
177
-
### Team workflow
292
+
From that point, all `set`, `get`, `list`, `run`, `import`, `export`, `diff`, and `env` commands operate against the shared server. Variables set by one developer are immediately available to all others. No `.env` files are shared, committed, or sent over chat.
293
+
294
+
**Checking server status:**
178
295
179
-
The admin sets up the server once and shares the server URL and API key with the team. Each developer runs:
180
296
```bash
181
-
enveil server connect http://192.168.1.100:8080 --key shared-api-key
182
-
enveil init
297
+
enveil server status # verify connection
298
+
enveil server disconnect # switch back to local vault
183
299
```
184
300
185
-
From that point, all `set`, `get`, `list`, `run`, `import`, `export`, `diff`, and `env` commands operate against the shared server. Variables set by one developer are immediately available to all others.
@@ -199,13 +314,15 @@ From that point, all `set`, `get`, `list`, `run`, `import`, `export`, `diff`, an
199
314
200
315
## Security model
201
316
202
-
-**Vault encryption**: AES-256 via SQLCipher. The entire database file is encrypted, including table names, project names, and variable names.
203
-
-**Key derivation**: Argon2id with 64MB memory, 4 threads. Resistant to GPU and ASIC brute-force attacks.
204
-
-**Master key**: Never written to disk. Lives in memory only while the daemon is running.
205
-
-**Transport encryption**: Values are encrypted with AES-GCM on the client before being sent to the server. The server stores and returns ciphertext only.
206
-
-**File permissions**: Vault and config files are created with `0600` permissions (owner read/write only).
207
-
-**Process injection**: Variables are passed directly to child process environments via `syscall.Exec`, never written to temporary files.
208
-
-**Secret scanning**: Pre-commit hook combines pattern matching and Shannon entropy analysis to catch secrets before they reach version control.
317
+
| Property | Implementation |
318
+
|---|---|
319
+
| Vault encryption | AES-256 via SQLCipher. The entire database is encrypted, including metadata. |
320
+
| Key derivation | Argon2id, 64MB memory, 4 threads. Resistant to GPU and ASIC attacks. |
321
+
| Master key at rest | Never written to disk. Held in memory by the daemon, or derived per-command and discarded. |
322
+
| Transport encryption | AES-GCM on the client before transmission. The server never sees plaintext. |
323
+
| File permissions | Vault and config created with `0600` — owner only. |
324
+
| Process injection | Variables passed via `syscall.Exec`, never through temporary files or environment exports. |
0 commit comments