diff --git a/README.md b/README.md index 95ead41..d01b85e 100644 --- a/README.md +++ b/README.md @@ -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 @@ -96,6 +123,7 @@ | Flag | Short | Description | |------|-------|-------------| | `--directory ` | `-D ` | Use the Opsfile in the given directory instead of searching parent directories | + | `--env-file ` | `-e ` | 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 | diff --git a/docs/site/index.html b/docs/site/index.html index 8113aee..e205b11 100644 --- a/docs/site/index.html +++ b/docs/site/index.html @@ -131,6 +131,7 @@

Step 2: Run ops commands

--directory <path>-D <path>Use the Opsfile in the given directory + --env-file <path>-e <path>Load secrets from a .env file (defaults to .ops_secrets.env) --dry-run-dPrint resolved commands without executing --list-lList available commands and environments --silent-sExecute commands without printing output @@ -182,7 +183,7 @@

Why use it?

🔒
Secrets-Safe by Design
-

Reference secrets via environment variables — never commit them.

+

Inject secrets from .env files with -e — never commit them to your Opsfile.

diff --git a/examples/Opsfile_azure b/examples/Opsfile_azure index 78ce898..8cce101 100644 --- a/examples/Opsfile_azure +++ b/examples/Opsfile_azure @@ -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 diff --git a/examples/Opsfile_baremetal b/examples/Opsfile_baremetal index 7020bd5..c5c7669 100644 --- a/examples/Opsfile_baremetal +++ b/examples/Opsfile_baremetal @@ -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)" diff --git a/examples/Opsfile_local b/examples/Opsfile_local index bcf9179..8d2fc0c 100644 --- a/examples/Opsfile_local +++ b/examples/Opsfile_local @@ -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