Skip to content
status date decision-makers consulted informed
accepted 2026-10-22 kubara-Team kubara-Team -

Improve Environment Variable Handling

Context and Problem Statement

kubara currently has a hard dependency on a .env file across init, generate, and bootstrap, and uses both .env and config.yaml to define platform parameters. This creates several problems:

  • Cluster configuration (PROJECT_NAME, PROJECT_STAGE, ARGOCD_GIT_URL, ARGOCD_GIT_HTTPS_URL, ARGOCD_GIT_AUTH_MODE, ARGOCD_HELM_REPO_URL) lives in .env. It is unclear whether these settings apply only to the Hub cluster or to Spoke clusters as well.
  • Initializing a project requires a two-step command flow: running kubara init --prep to generate .env, editing it, and then running kubara init to copy parts of those values into config.yaml.
  • Later runs using kubara init --overwrite read .env to overwrite values in config.yaml, maintaining two conflicting sources of truth.
  • kubara generate requires .env and injects its contents into template contexts under .env, creating the risk of leaking secrets into rendered GitOps manifests committed to version control. This MUST be removed.
  • Requiring a .env file on disk makes CI/CD and non-interactive automation unnecessarily cumbersome when environment variables are already available in the process environment.
  • Existing environment variables are prefixed with ARGOCD_, coupling credential names to a specific tool rather than GitOps repository access generically, and require users to manually supply ARGOCD_WIZARD_ACCOUNT_PASSWORD. This is not in line with our aim to support multiple gitops engines.

We need a clear boundary: config.yaml MUST be the sole source of truth for platform configuration (schema changes are covered in a separate ADR), the hard dependency on .env MUST be removed in favor of checking OS environment variables first and falling back to .env, ARGOCD_WIZARD_ACCOUNT_PASSWORD MUST be autogenerated, and environment variables MUST be reduced to GITOPS_-prefixed repository credentials needed only for initial bootstrap. Old names MUST also be recognized for backward compatibility.

Decision Drivers

  • Single source of truth for all cluster and platform configuration in config.yaml.
  • Zero risk of secret leakage into generated GitOps manifests.
  • No hard dependency on a .env file; first-class support for OS environment variables with .env as an optional fallback.
  • Minimal credential surface area limited strictly to initial bootstrap repository access.
  • Simpler initialization flow without --prep, --overwrite, or .env scaffolding.

Considered Options

  • Keep the existing two-stage command workflow and hard .env dependency across commands.
  • Move everything into config.yaml using external secret references or inline encryption using age or sops.
  • Remove the hard .env dependency, move all configuration to config.yaml, autogenerate the Argo CD wizard password, and restrict environment variables (and optional .env) to GITOPS_-prefixed bootstrap repository credentials.

Decision Outcome

Chosen option: remove the hard .env dependency, move all configuration to config.yaml, autogenerate the Argo CD wizard password, and restrict environment variables (and optional .env) to GITOPS_-prefixed bootstrap repository credentials. Accept the old ARGOCD_ prefix for backward compatibility, but emit a warning.

previous variable in .env moves to
PROJECT_NAME config.yaml
PROJECT_STAGE config.yaml
ARGOCD_GIT_URL config.yaml
ARGOCD_GIT_AUTH_MODE config.yaml (inferred from url)
ARGOCD_HELM_REPO_URL config.yaml
ARGOCD_WIZARD_ACCOUNT_PASSWORD autogenerated and printed once at bootstrap
ARGOCD_GIT_SSH_PRIVATE_KEY GITOPS_GIT_SSH_PRIVATE_KEY / GITOPS_GIT_SSH_PRIVATE_KEY_PATH
ARGOCD_GIT_USERNAME GITOPS_GIT_USERNAME
ARGOCD_GIT_PAT_OR_PASSWORD GITOPS_GIT_PASSWORD
ARGOCD_HELM_REPO_USERNAME GITOPS_HELM_REPO_USERNAME
ARGOCD_HELM_REPO_PASSWORD GITOPS_HELM_REPO_PASSWORD
ARGOCD_GIT_GITHUB_APP_ID GITOPS_GIT_GITHUB_APP_ID
ARGOCD_GIT_GITHUB_APP_INSTALLATION_ID GITOPS_GIT_GITHUB_APP_INSTALLATION_ID
ARGOCD_GIT_GITHUB_APP_PRIVATE_KEY GITOPS_GIT_GITHUB_APP_PRIVATE_KEY / GITOPS_GIT_GITHUB_APP_PRIVATE_KEY_PATH
ARGOCD_GIT_GITHUB_APP_ENTERPRISE_BASE_URL GITOPS_GIT_GITHUB_APP_ENTERPRISE_BASE_URL
DOCKERCONFIG_BASE64 unchanged

If an existing .env contains deprecated or removed fields, kubara logs a warning.

Credential resolution order

Only kubara bootstrap reads bootstrap credentials. When resolving credentials, kubara checks sources in the following order:

  1. OS environment variables (checked first).
  2. .env file, used as a fallback for any variables not set in the process environment).
  3. Error if required bootstrap credentials are still missing or invalid after checking both sources.

The .env file is completely optional. If the default .env file does not exist and required credentials are provided via OS environment variables, kubara bootstrap succeeds without requiring a .env file on disk.

Variable names are identical in OS environment variables and in .env (the KUBARA_ prefix is dropped).

Configuration and credential boundary

All non-secret configuration (PROJECT_NAME, PROJECT_STAGE, ARGOCD_GIT_URL, ARGOCD_GIT_HTTPS_URL, ARGOCD_GIT_AUTH_MODE, ARGOCD_HELM_REPO_URL) is removed from environment variables and .env and lives exclusively in config.yaml (the exact config.yaml schema changes are defined in a separate ADR).

Environment variables are generically prefixed with GITOPS_ instead of ARGOCD_ and are restricted to repository credentials for initial bootstrap:

  • Git repository credentials (optional for public HTTP(S) repositories; mutually exclusive when configured): Git authentication mode is inferred from the repository URL in config.yaml. At most one of the following credential sets may be configured during kubara bootstrap:
  • SSH key authentication: GITOPS_GIT_SSH_PRIVATE_KEY (inline) or GITOPS_GIT_SSH_PRIVATE_KEY_PATH (path to private key file).
  • Username/password authentication: GITOPS_GIT_USERNAME and GITOPS_GIT_PASSWORD (both must be set together).
  • GitHub App authentication: GITOPS_GIT_GITHUB_APP_ID, GITOPS_GIT_GITHUB_APP_INSTALLATION_ID, and GITOPS_GIT_GITHUB_APP_PRIVATE_KEY (or GITOPS_GIT_GITHUB_APP_PRIVATE_KEY_PATH), with optional GITOPS_GIT_GITHUB_APP_ENTERPRISE_BASE_URL.
  • Providing credentials from multiple methods, or providing partial credential sets (e.g. only one of username/password, or both inline key and key path), fails validation with an error.
  • Omitting credentials for an HTTP(S) repository URL is permitted (for public repositories), but kubara logs a warning in non---local mode that unauthenticated access is not recommended for production setups.
  • Helm repository credentials (optional):
  • GITOPS_HELM_REPO_USERNAME and GITOPS_HELM_REPO_PASSWORD (both must be set together when authenticating against a private Helm repository).
  • ARGOCD_WIZARD_ACCOUNT_PASSWORD is removed from environment variables and .env. kubara always autogenerates the initial wizard account password during kubara bootstrap and prints it once in the bootstrap completion output.

Generation boundary

kubara generate stops reading .env and environment variables entirely:

  • The .env key is removed from the template rendering context to ensure NO secrets can leak into Git manifests.
  • Templates must source all cluster and service values from config.yaml.
  • Templates attempting to reference .env will fail at render time. This is a BREAKING CHANGE!

Streamlined initialization

kubara init replaces the multi-step flow and no longer creates or reads .env:

  • The --prep flag is removed.
  • The --overwrite flag is removed.
  • Running kubara init scaffolds config.yaml, env.example (if not already existing, documenting available bootstrap credentials), and renovate.json (if enabled). Both .env and env.example are added to the generated .gitignore.
  • If config.yaml already exists, kubara init fails rather than overwriting existing configuration.
  • kubara init --local generates config.yaml pre-filled with local evaluation settings in one step without creating a .env file.

Secret resolution during bootstrap

During kubara bootstrap <cluster-name>, kubara resolves GITOPS_* credentials from OS environment variables first and an optional .env file in the working directory second, applying them to the targeted cluster. If no .env file exists, kubara expects credentials to be supplied via OS environment variables.

Consequences

  • Good, because config.yaml becomes the single source of truth for all cluster and repository configuration.
  • Good, because kubara no longer requires a .env file on disk and works natively with OS environment variables in CI/CD and local shells.
  • Good, because kubara generate cannot leak secrets into git-tracked manifests.
  • Good, because ARGOCD_WIZARD_ACCOUNT_PASSWORD is autogenerated during bootstrap instead of requiring manual management.
  • Good, because kubara init is a single step that only creates declarative configuration and a static env.example reference.
  • Good, because internal/envconfig and custom store layers are removed in favor of a clean, isolated bootstrap loader using standard godotenv.Read.
  • Bad, because any custom templates expecting .env in their rendering context will break.

Non-Goals

  • Defining the config.yaml schema changes (covered in a separate ADR).
  • Replacing environment variables / .env with a built-in secret manager or vault client.
  • Encrypting secrets within git-tracked files.