CI/CD Setup
Overview
Section titled “Overview”CI/CD pipelines use machine identities to pull secrets. Each machine is scoped to one project + one environment. Machines are pull-only — they authenticate with a challenge-response flow and get a short-lived JWT (15 minutes, non-refreshable).
Setup (3 steps)
Section titled “Setup (3 steps)”Step 1: Create a machine identity
Section titled “Step 1: Create a machine identity”On your local machine (admin only):
envsh machine create github-prod \ --project my-api \ --env production# ok: Created machine github-prod# ok: Private key saved to ~/.envsh/machines/github-prod## To use this machine, set:# ENVSH_MACHINE_KEY=envsh-machine-v1:AABBCCDD...Copy the ENVSH_MACHINE_KEY value. The private key is shown once and never stored on the server.
Step 2: Re-push secrets
Section titled “Step 2: Re-push secrets”After creating a machine, push secrets again so the machine’s key is included as a recipient:
envsh push .env --project my-api --env production --message "include CI machine key"The CLI automatically includes all registered keys (user SSH keys + active machine keys) when encrypting.
Step 3: Add the key to your CI system
Section titled “Step 3: Add the key to your CI system”Add ENVSH_MACHINE_KEY as a secret environment variable in your CI/CD platform.
GitHub Actions
Section titled “GitHub Actions”name: Deploy
on: push: branches: [main]
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Install envsh run: curl -fsSL https://envsh.dev/install.sh | sh
- name: Deploy with secrets env: ENVSH_MACHINE_KEY: ${{ secrets.ENVSH_MACHINE_KEY }} run: envsh run --project my-api production -- ./deploy.shAdd ENVSH_MACHINE_KEY in GitHub → Settings → Secrets and variables → Actions → New repository secret.
GitLab CI
Section titled “GitLab CI”deploy: stage: deploy script: - curl -fsSL https://envsh.dev/install.sh | sh - envsh run --project my-api production -- ./deploy.sh variables: ENVSH_MACHINE_KEY: $ENVSH_MACHINE_KEYAdd ENVSH_MACHINE_KEY in GitLab → Settings → CI/CD → Variables (masked + protected).
Bitbucket Pipelines
Section titled “Bitbucket Pipelines”pipelines: branches: main: - step: name: Deploy script: - curl -fsSL https://envsh.dev/install.sh | sh - envsh run --project my-api production -- ./deploy.shAdd ENVSH_MACHINE_KEY in Bitbucket → Repository settings → Pipelines → Repository variables (secured).
CircleCI
Section titled “CircleCI”jobs: deploy: docker: - image: cimg/base:current steps: - checkout - run: name: Install envsh command: curl -fsSL https://envsh.dev/install.sh | sh - run: name: Deploy command: envsh run --project my-api production -- ./deploy.shAdd ENVSH_MACHINE_KEY in CircleCI → Project Settings → Environment Variables.
Docker containers
Section titled “Docker containers”Don’t bake secrets into images. Pull at runtime:
# Option 1: use envsh run (secrets never touch disk)CMD ["envsh", "run", "--project", "my-api", "production", "--", "node", "server.js"]# Option 2: entrypoint script (writes .env, then starts app)#!/bin/shenvsh pull production --project my-api --output .envexec "$@"# Option 3: pull to stdout and sourceeval $(envsh pull production --project my-api --stdout --format export)exec node server.jsHow machine auth works
Section titled “How machine auth works”CLI Server │ │ ├─ POST /auth/machine-challenge ──→│ Returns 32-byte nonce (30s TTL) │ │ ├─ Sign nonce with Ed25519 key │ │ │ ├─ POST /auth/machine-verify ────→│ Verify signature → JWT (15min) │ │ ├─ GET /secrets/pull ────────────→│ Return encrypted bundle │ │ └─ Decrypt locally │Each CI job re-authenticates. No long-lived tokens. No refresh tokens. If the 15-minute JWT expires, the CLI re-authenticates automatically.
Multiple environments
Section titled “Multiple environments”Create one machine per environment:
envsh machine create ci-staging --project my-api --env stagingenvsh machine create ci-prod --project my-api --env productionEach gets its own key. A staging machine cannot access production secrets. Store each key as a separate CI/CD secret.
Revoking a machine
Section titled “Revoking a machine”envsh machine revoke github-prodAfter revocation, the machine cannot obtain new tokens. Remove the old ENVSH_MACHINE_KEY from your CI/CD system and create a new machine if needed.