v2.3.0 fc65046

env.md RawHistoryFolder

Environment Variables

Configure per-application environment variables using domain-based files.

Configuration

[env]
dir = "~/.gordon/env"  # Default location

Options

Option Type Default Description
dir string ~/.gordon/env Directory containing .env files

How It Works

Gordon loads environment variables from files named after the domain:

~/.gordon/env/
├── app_mydomain_com.env      # For app.mydomain.com
├── api_mydomain_com.env      # For api.mydomain.com
└── admin_mydomain_com.env    # For admin.mydomain.com

Naming convention: Replace dots with underscores, add .env extension.

Domain File Name
app.mydomain.com app_mydomain_com.env
api.company.io api_company_io.env
staging.app.dev staging_app_dev.env

File Format

Standard .env file format:

# app_mydomain_com.env
NODE_ENV=production
PORT=3000
DATABASE_URL=postgresql://db:5432/myapp
API_KEY=sk-1234567890
DEBUG=false

Variable Merging

Variables are merged from multiple sources (lowest to highest priority):

  1. Dockerfile ENV - Base defaults from image
  2. .env file - Overrides Dockerfile values
# Dockerfile
ENV NODE_ENV=development
ENV PORT=3000
# app_mydomain_com.env
NODE_ENV=production  # Overrides Dockerfile
# PORT not set, uses 3000 from Dockerfile

Result: NODE_ENV=production, PORT=3000

Secret Provider Syntax

Reference secrets from configured backends in env files:

Pass (Unix Password Manager)

DATABASE_PASSWORD=${pass:myapp/database/password}
API_SECRET=${pass:company/api-secret}
JWT_KEY=${pass:production/jwt-signing-key}

SOPS (Encrypted Files)

DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
API_SECRET=${sops:production.yaml:api.secret}
STRIPE_KEY=${sops:secrets.yaml:stripe.api_key}

Syntax Reference

Provider Syntax Example
pass ${pass:<path>} ${pass:myapp/db-password}
sops ${sops:<file>:<key.path>} ${sops:secrets.yaml:db.password}

Examples

Basic Application

# app_mydomain_com.env
NODE_ENV=production
PORT=3000
LOG_LEVEL=info

Database Connection

# ~/.gordon/env/api_mydomain_com.env
DATABASE_HOST=postgres
DATABASE_PORT=5432
DATABASE_NAME=myapi
DATABASE_USER=apiuser
DATABASE_PASSWORD=${pass:myapi/db-password}
DATABASE_URL=postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}

Full Production Setup

# ~/.gordon/env/app_company_com.env
# Application settings
NODE_ENV=production
PORT=3000
LOG_LEVEL=warn

# Database
DATABASE_URL=postgresql://postgres:5432/production
DATABASE_PASSWORD=${pass:company/db-password}

# Redis
REDIS_URL=redis://redis:6379

# External APIs
STRIPE_SECRET_KEY=${pass:company/stripe-secret}
SENDGRID_API_KEY=${pass:company/sendgrid-key}

# Auth
JWT_SECRET=${pass:company/jwt-secret}
SESSION_SECRET=${pass:company/session-secret}

# Feature flags
ENABLE_ANALYTICS=true
MAINTENANCE_MODE=false

Development Environment

# ~/.gordon/env/app_local.env
NODE_ENV=development
PORT=3000
LOG_LEVEL=debug
DATABASE_URL=postgresql://postgres:5432/dev
DEBUG=*

File Permissions

Gordon creates env files with secure permissions:

  • Directory: 0700 (owner only)
  • Files: 0600 (owner only)

Create files with proper permissions:

mkdir -p ~/.gordon/env
chmod 700 ~/.gordon/env
touch ~/.gordon/env/app_mydomain_com.env
chmod 600 ~/.gordon/env/app_mydomain_com.env

Auto-Creation

Gordon creates empty env files automatically when deploying a new route. You can then edit the file to add your variables.

Viewing Effective Environment

To see what environment a container receives:

docker inspect gordon-app-mydomain-com | jq '.[0].Config.Env'
source
1# Environment Variables
2
3Configure per-application environment variables using domain-based files.
4
5## Configuration
6
7```toml
8[env]
9dir = "~/.gordon/env"  # Default location
10```
11
12## Options
13
14| Option | Type | Default | Description |
15|--------|------|---------|-------------|
16| `dir` | string | `~/.gordon/env` | Directory containing .env files |
17
18## How It Works
19
20Gordon loads environment variables from files named after the domain:
21
22```
23~/.gordon/env/
24├── app_mydomain_com.env      # For app.mydomain.com
25├── api_mydomain_com.env      # For api.mydomain.com
26└── admin_mydomain_com.env    # For admin.mydomain.com
27```
28
29**Naming convention:** Replace dots with underscores, add `.env` extension.
30
31| Domain | File Name |
32|--------|-----------|
33| `app.mydomain.com` | `app_mydomain_com.env` |
34| `api.company.io` | `api_company_io.env` |
35| `staging.app.dev` | `staging_app_dev.env` |
36
37## File Format
38
39Standard `.env` file format:
40
41```bash
42# app_mydomain_com.env
43NODE_ENV=production
44PORT=3000
45DATABASE_URL=postgresql://db:5432/myapp
46API_KEY=sk-1234567890
47DEBUG=false
48```
49
50## Variable Merging
51
52Variables are merged from multiple sources (lowest to highest priority):
53
541. **Dockerfile ENV** - Base defaults from image
552. **.env file** - Overrides Dockerfile values
56
57```dockerfile
58# Dockerfile
59ENV NODE_ENV=development
60ENV PORT=3000
61```
62
63```bash
64# app_mydomain_com.env
65NODE_ENV=production  # Overrides Dockerfile
66# PORT not set, uses 3000 from Dockerfile
67```
68
69Result: `NODE_ENV=production`, `PORT=3000`
70
71## Secret Provider Syntax
72
73Reference secrets from configured backends in env files:
74
75### Pass (Unix Password Manager)
76
77```bash
78DATABASE_PASSWORD=${pass:myapp/database/password}
79API_SECRET=${pass:company/api-secret}
80JWT_KEY=${pass:production/jwt-signing-key}
81```
82
83### SOPS (Encrypted Files)
84
85```bash
86DATABASE_PASSWORD=${sops:secrets.yaml:database.password}
87API_SECRET=${sops:production.yaml:api.secret}
88STRIPE_KEY=${sops:secrets.yaml:stripe.api_key}
89```
90
91### Syntax Reference
92
93| Provider | Syntax | Example |
94|----------|--------|---------|
95| pass | `${pass:<path>}` | `${pass:myapp/db-password}` |
96| sops | `${sops:<file>:<key.path>}` | `${sops:secrets.yaml:db.password}` |
97
98## Examples
99
100### Basic Application
101
102```bash
103# app_mydomain_com.env
104NODE_ENV=production
105PORT=3000
106LOG_LEVEL=info
107```
108
109### Database Connection
110
111```bash
112# ~/.gordon/env/api_mydomain_com.env
113DATABASE_HOST=postgres
114DATABASE_PORT=5432
115DATABASE_NAME=myapi
116DATABASE_USER=apiuser
117DATABASE_PASSWORD=${pass:myapi/db-password}
118DATABASE_URL=postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}
119```
120
121### Full Production Setup
122
123```bash
124# ~/.gordon/env/app_company_com.env
125# Application settings
126NODE_ENV=production
127PORT=3000
128LOG_LEVEL=warn
129
130# Database
131DATABASE_URL=postgresql://postgres:5432/production
132DATABASE_PASSWORD=${pass:company/db-password}
133
134# Redis
135REDIS_URL=redis://redis:6379
136
137# External APIs
138STRIPE_SECRET_KEY=${pass:company/stripe-secret}
139SENDGRID_API_KEY=${pass:company/sendgrid-key}
140
141# Auth
142JWT_SECRET=${pass:company/jwt-secret}
143SESSION_SECRET=${pass:company/session-secret}
144
145# Feature flags
146ENABLE_ANALYTICS=true
147MAINTENANCE_MODE=false
148```
149
150### Development Environment
151
152```bash
153# ~/.gordon/env/app_local.env
154NODE_ENV=development
155PORT=3000
156LOG_LEVEL=debug
157DATABASE_URL=postgresql://postgres:5432/dev
158DEBUG=*
159```
160
161## File Permissions
162
163Gordon creates env files with secure permissions:
164- Directory: `0700` (owner only)
165- Files: `0600` (owner only)
166
167Create files with proper permissions:
168
169```bash
170mkdir -p ~/.gordon/env
171chmod 700 ~/.gordon/env
172touch ~/.gordon/env/app_mydomain_com.env
173chmod 600 ~/.gordon/env/app_mydomain_com.env
174```
175
176## Auto-Creation
177
178Gordon creates empty env files automatically when deploying a new route. You can then edit the file to add your variables.
179
180## Viewing Effective Environment
181
182To see what environment a container receives:
183
184```bash
185docker inspect gordon-app-mydomain-com | jq '.[0].Config.Env'
186```
187
188## Related
189
190- [Secrets Configuration](./secrets.md)
191- [Routes](./routes.md)
192- [Attachments](./attachments.md)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close