Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,35 @@
> [!TIP]
> There are more sample Opsfile examples in the `/examples` folder.

> [!WARNING]
> Be sure not to include any secrets or access keys into your Opsfile as they could get shared visibly once committed to the repo. Instead you can inject your secrets into the Opsfile via environment variables if needed.
> [!WARNING]
> Be sure not to include any secrets or access keys into your Opsfile as they could get shared visibly once committed to the repo. Instead you can inject your secrets using the `--env-file` flag or environment variables.

### Injecting Secrets with `--env-file`

Use the `-e` / `--env-file` flag to load secrets from a `.env`-format file at invocation time, keeping them out of your Opsfile and version control.

```bash
# Load secrets from a specific file
ops -e .env.prod prod rollback

# By default, ops auto-loads .ops_secrets.env from the Opsfile directory (silent no-op if absent)
ops prod rollback
```

The env file uses the same `NAME=value` format as Opsfile variables. Env-scoped keys (e.g. `prod_DB_PASSWORD`) are supported. Values can be quoted with single or double quotes, and `#` comments are allowed.

```bash
# .ops_secrets.env
DB_PASSWORD=hunter2
prod_API_TOKEN="sk-prod-abc123"
staging_API_TOKEN="sk-staging-xyz789"
```

**Important notes:**
- The `-e` flag must appear **before** the environment and command positionals
- Only one `-e` per invocation — an explicit `-e` replaces the default `.ops_secrets.env`
- Add `.ops_secrets.env` to your `.gitignore`
- `--dry-run` will print resolved commands including injected values — be cautious with secrets

### Step 2: Call the `ops` CLI

Expand All @@ -96,6 +123,7 @@
| Flag | Short | Description |
|------|-------|-------------|
| `--directory <path>` | `-D <path>` | Use the Opsfile in the given directory instead of searching parent directories |
| `--env-file <path>` | `-e <path>` | Load variables from a `.env`-format file (defaults to `.ops_secrets.env` if present) |
| `--dry-run` | `-d` | Print the resolved commands without executing them |
| `--silent` | `-s` | Execute commands without printing output |
| `--list` | `-l` | List available commands and environments defined in the Opsfile, then exit |
Expand Down
3 changes: 2 additions & 1 deletion docs/site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ <h3>Step 2: Run ops commands</h3>
</thead>
<tbody>
<tr><td><code>--directory &lt;path&gt;</code></td><td><code>-D &lt;path&gt;</code></td><td>Use the Opsfile in the given directory</td></tr>
<tr><td><code>--env-file &lt;path&gt;</code></td><td><code>-e &lt;path&gt;</code></td><td>Load secrets from a <code>.env</code> file (defaults to <code>.ops_secrets.env</code>)</td></tr>
<tr><td><code>--dry-run</code></td><td><code>-d</code></td><td>Print resolved commands without executing</td></tr>
<tr><td><code>--list</code></td><td><code>-l</code></td><td>List available commands and environments</td></tr>
<tr><td><code>--silent</code></td><td><code>-s</code></td><td>Execute commands without printing output</td></tr>
Expand Down Expand Up @@ -182,7 +183,7 @@ <h2>Why use it?</h2>
<div class="feature-card">
<div class="feature-icon">🔒</div>
<div class="feature-title">Secrets-Safe by Design</div>
<p>Reference secrets via environment variables — never commit them.</p>
<p>Inject secrets from <code>.env</code> files with <code>-e</code> — never commit them to your Opsfile.</p>
</div>
</div>
</div>
Expand Down
8 changes: 8 additions & 0 deletions examples/Opsfile_azure
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# AZURE_SUBSCRIPTION_ID is used by commands below but not defined here —
# inject it via env-file to keep subscription IDs out of version control:
# ops -e .ops_secrets.env prod tail-logs
#
# .ops_secrets.env:
# prod_AZURE_SUBSCRIPTION_ID=aaaa-bbbb-cccc
# staging_AZURE_SUBSCRIPTION_ID=dddd-eeee-ffff

prod_RESOURCE_GROUP=my-service-prod-rg
staging_RESOURCE_GROUP=my-service-staging-rg

Expand Down
6 changes: 6 additions & 0 deletions examples/Opsfile_baremetal
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ staging_SSH_USER=deploy
SERVICE_NAME=my-service
LOG_FILE=/var/log/my-service/app.log

# SSH_KEY is a secret — inject it via env-file instead of committing it here:
# ops -e .ops_secrets.env prod tail-logs
#
# .ops_secrets.env:
# SSH_KEY=~/.ssh/prod_deploy_key

tail-logs:
default:
ssh $(SSH_USER)@$(HOST) "tail -f $(LOG_FILE)"
Expand Down
6 changes: 6 additions & 0 deletions examples/Opsfile_local
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ APP_CONTAINER=app
APP_PORT=8080
DB_PORT=5432

# PGUSER is referenced by db-connections below — inject it via env-file:
# ops -e .ops_secrets.env default db-connections
#
# .ops_secrets.env:
# PGUSER=mydbadmin

tail-logs:
default:
docker compose -f $(COMPOSE_FILE) logs $(APP_CONTAINER) --follow --tail 100
Expand Down