# ============================================================================= # OPERATOR CREDENTIALS (local only — never committed) # ============================================================================= # DO NOT copy this file over .env.local — that file already holds your # project's generated secrets (`vibecarbon create` wrote JWT_SECRET, # POSTGRES_PASSWORD and the rest of the Supabase keys there, and nothing can # regenerate them for a running database). Append the keys you need, or run # `vibecarbon configure`. # # This is the .example counterpart of .env.local: `carbon/_gitignore` ignores # .env.local itself (it holds real credentials) but keeps this value-free # template so a fresh clone documents exactly which OPERATOR credentials # exist and what format each one takes. Run `vibecarbon configure` to fill # most of these in interactively — it writes straight to .env.local and masks # every value it prints. # # Every key documented here is a CLI-local value: cloud/DNS provider # credentials, the Docker Hub registry pair, and the Pulumi state-backend # override. `vibecarbon deploy` (and its spawned children: ssh/pulumi/docker) # reads them on your machine, and none of THESE keys is ever written to a # deployed server or the client bundle (see the 'operator-secret' class in # src/lib/config-registry.js in the vibecarbon CLI repo, and the bundle # baseline strip it drives). Values the SERVER must read are documented in # .env.example instead — the ACME CA override (ACME_CA_SERVER) is the one # that used to sit here; it is interpolated by docker-compose.prod.yml from # the shipped .env, so it belongs there. # # Two entries below (Docker Hub) are marked "operator shell" — they are never # written to this file by `configure` (export them in your shell or CI # environment instead) but are documented here anyway so their format is in # one place with everything else. # # `vibecarbon deploy` and `vibecarbon status` check every value here against # the "# format:" line above it and refuse to deploy on a mismatch. If a # provider changes its token format before the CLI catches up, export # VIBECARBON_SKIP_CONFIG_SHAPES=1 in your shell to downgrade shape problems # to warnings (a MISSING required value still refuses — only the format check # is relaxed). # ============================================================================= # HETZNER CLOUD # ============================================================================= # Cloud API token — console.hetzner.cloud > Security > API Tokens (Read & # Write). Also drives Hetzner DNS-01 when Hetzner is your DNS provider. # format: 64 alphanumeric characters HETZNER_API_TOKEN="" # Object Storage (S3-compatible) access key — separate credentials from the # Cloud API token, created in the Hetzner console under Object Storage. # format: an opaque identifier HETZNER_ACCESS_KEY="" # Object Storage secret key, paired with HETZNER_ACCESS_KEY above. # format: at least 8 characters HETZNER_SECRET_KEY="" # OPTIONAL override — usually inferred from the compute region; pin only if # your Object Storage location differs. # format: a short identifier HETZNER_STORAGE_REGION="" # ============================================================================= # DIGITALOCEAN # ============================================================================= # Personal access token (Full Access) — cloud.digitalocean.com > API. One # token covers both compute and DNS-01 (DigitalOcean's ACME solver ships in # cert-manager core, so no extra webhook chart is needed for k8s). # format: at least 8 characters DIGITALOCEAN_API_TOKEN="" # Spaces (S3-compatible) access key — created in the DO console (Spaces > # Access Keys), separate credentials from the API token. # format: an opaque identifier DIGITALOCEAN_ACCESS_KEY="" # Spaces secret key, paired with DIGITALOCEAN_ACCESS_KEY above. # format: at least 8 characters DIGITALOCEAN_SECRET_KEY="" # OPTIONAL — a standing DO project id (env-first): when set, deploys file # droplets into this project instead of find-or-creating one per run. # format: a UUID DIGITALOCEAN_PROJECT_ID="" # OPTIONAL override — usually inferred from the compute region; pin only if # your Spaces region differs. # format: a short identifier DIGITALOCEAN_STORAGE_REGION="" # ============================================================================= # CLOUDFLARE DNS # ============================================================================= # API token — needed only when Cloudflare is your DNS provider (a compute # provider other than Cloudflare with Cloudflare-managed DNS). # format: at least 8 characters CLOUDFLARE_API_TOKEN="" # ============================================================================= # LINODE (AKAMAI) # ============================================================================= # Personal access token, 64 alphanumeric chars (cloud.linode.com > Profile > # API Tokens, Select All Read/Write). Also drives Linode DNS-01 when Linode # is your DNS provider. # format: at least 16 characters LINODE_API_TOKEN="" # Object Storage (S3-compatible) access key — created in the Linode console # (Object Storage > Access Keys), separate credentials from the API token. # NOTE: creating the first key activates Object Storage on the account (flat # monthly base fee). # format: an opaque identifier LINODE_ACCESS_KEY="" # Object Storage secret key, paired with LINODE_ACCESS_KEY above. # format: at least 8 characters LINODE_SECRET_KEY="" # OPTIONAL override — Linode assigns each account one storage cluster per # region, not always the default one; pin only if yours differs. # format: a short identifier LINODE_STORAGE_REGION="" # ============================================================================= # VULTR # ============================================================================= # API key (my.vultr.com > Account > API; check Access Control — the API # rejects calls from IPs outside the allowed subnets). # format: at least 8 characters VULTR_API_TOKEN="" # Object Storage (S3-compatible) access key — created per Object Storage # subscription in the Vultr console, separate credentials from the API token. # format: an opaque identifier VULTR_ACCESS_KEY="" # Object Storage secret key, paired with VULTR_ACCESS_KEY above. # format: at least 8 characters VULTR_SECRET_KEY="" # OPTIONAL at the prompt (guided setup warns and continues on blank), but # worth setting: Vultr mints storage keys per subscription and a subscription # lives in exactly one cluster, so this cannot be inferred from the compute # region the way the other providers' storage regions can. # format: a short identifier VULTR_STORAGE_REGION="" # ============================================================================= # SCALEWAY # ============================================================================= # A credential TRIPLE — all three required together (the Pulumi provider # demands the full set; the secret key alone drives the REST API as an # X-Auth-Token). The same pair signs Object Storage — there are no separate # storage keys. # format: at least 8 characters SCALEWAY_SECRET_KEY="" # The access-key half of the same IAM pair as SCALEWAY_SECRET_KEY above. # format: an opaque identifier SCALEWAY_ACCESS_KEY="" # REQUIRED — a dedicated Scaleway Project for this deployment (SSH keys are # Project-scoped and re-applied to every instance in the Project at each # boot, so a shared Project shares root access). # format: an opaque identifier SCALEWAY_DEFAULT_PROJECT_ID="" # OPTIONAL override (fr-par/nl-ams, not a zone) — usually derived by # stripping the zone's trailing digit; pin only if that inference is wrong. # format: a short identifier SCALEWAY_STORAGE_REGION="" # ============================================================================= # DOCKER HUB (operator shell — export in your shell/CI, never stored here) # ============================================================================= # `configure`'s Docker Hub row is informational only and never writes these # to a file — export them in your shell environment or CI secrets instead. # They are documented here so their expected format lives in one place with # every other operator credential. Without them, deploys fall back to # anonymous Docker Hub pulls (fine until you hit the per-IP rate limit on a # restore/scale re-deploy). # format: an opaque identifier DOCKER_HUB_USERNAME="" # Access token (or account password), paired with DOCKER_HUB_USERNAME above. # `docker login` accepts a personal access token (dckr_pat_…), an organization # access token (dckr_oat_…), a legacy UUID token, or the account password. # format: a Docker Hub access token or password DOCKER_HUB_TOKEN="" # ============================================================================= # PULUMI STATE BACKEND (optional override) # ============================================================================= # Opt-in backend override — absent, the CLI computes its own S3 or local # file:// backend. Accepts any scheme Pulumi documents (https://, s3://, # azblob://, gs://, file://), not just Pulumi Cloud. # format: a Pulumi backend URL (https://…, s3://…, file://…) PULUMI_BACKEND_URL=""