Skip to content

Infisical CI Secrets Migration

Centralized secret management for GitHub Actions via self-hosted Infisical.

GitHub Actions Workflow
├── secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID ─┐
├── secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET ├── 3 GitHub Secrets (only)
└── secrets.INFISICAL_PROJECT_ID ─┘
.github/actions/infisical-secrets/action.yml
│ 1. Validate creds
│ 2. Install Infisical CLI
│ 3. infisical login --method=universal-auth
│ 4. infisical export --format=dotenv
│ 5. Append to $GITHUB_ENV + mask values
All downstream steps see secrets as env vars
SecretPurpose
INFISICAL_UNIVERSAL_AUTH_CLIENT_IDMachine identity client ID
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRETMachine identity client secret
INFISICAL_PROJECT_IDInfisical project identifier

GITHUB_TOKEN is auto-provided by GitHub and not managed by Infisical.

All CI secrets are organized under /ci/ with environment-scoped slugs (staging, production).

PathSecretsUsed By
/ci/sharedTURBO_TOKEN, RELEASE_PATvalidate.yml, release.yml
/ci/cloudflareCLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_IDdeploy-email-worker, deploy-ops-mcp, deploy-tidycal-hubspot-sync, graphify-nightly, version-aware-build, deploy-docs
/ci/gcpGCP_SA_KEYgcp-deploy, deploy-webapp (base image pull)
/ci/coolifyCOOLIFY_TOKEN, COOLIFY_PRODUCTION_WEBHOOK_WEB, COOLIFY_STAGING_WEBHOOK_WEB, COOLIFY_PRODUCTION_WEBHOOK_INTERNALdeploy-webapp, version-aware-build
/ci/clerkPUBLIC_CLERK_PUBLISHABLE_KEY, CLERK_SECRET_KEYdeploy-webapp, deploy-branch-gate, validate, version-aware-build, flagsmith-seed, staging-canary (E2E)
/ci/posthogPUBLIC_POSTHOG_KEY, PUBLIC_POSTHOG_HOSTdeploy-webapp
/ci/evalEVAL_SERVICE_TOKEN, LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, R2_*eval, match-correctness-eval
/ci/flagsmithFLAGSMITH_API_URL, FLAGSMITH_ADMIN_EMAIL, FLAGSMITH_ADMIN_PASSWORD, FLAGSMITH_ENVIRONMENT_KEYflagsmith-seed
/ci/e2eSTAGING_TEST_EMAIL, STAGING_TEST_PASSWORD, MOMENTIC_API_KEY, E2E_FLAG_OVERRIDE_SECRETmomentic-staging, staging-canary
/ci/databaseDATABASE_URL (env-scoped: staging has STAGING_DATABASE_URL, production has PROD_DATABASE_URL)deploy-webapp (migrations), db-maintenance, flagsmith-seed
/ci/integrationsLINEAR_API_KEY, GEMINI_API_KEY, STAGING_WEBAPP_URLlinear-close-on-merge, graphify-nightly, version-aware-build
WorkflowSecret PathsNotes
eval.yml/ci/evalE2E test credentials + Langfuse
deploy-email-worker.yml/ci/cloudflareBoth staging + production jobs
deploy-docs.yml/ci/cloudflarePages deploy; token needs Pages:Edit
deploy-ops-mcp.yml/ci/cloudflareBoth staging + production jobs
deploy-tidycal-hubspot-sync.yml/ci/cloudflareSingle production deploy
deploy-branch-gate.yml/ci/clerkTypecheck jobs (webapp + internal)
validate.yml/ci/shared, /ci/clerkTURBO_TOKEN + Clerk key
version-aware-build.yml/ci/clerk, /ci/coolify, /ci/cloudflare, /ci/integrationsBuild + deploy jobs
db-maintenance.yml/ci/databaseEnvironment-scoped (staging/production)
flagsmith-seed.yml/ci/flagsmith, /ci/clerk, /ci/databaseMulti-path, identity sync
graphify-nightly.yml/ci/cloudflare, /ci/integrationsGemini + Cloudflare R2
linear-close-on-merge.yml/ci/integrationsLinear API key
match-correctness-eval.yml/ci/evalLangfuse keys
gcp-deploy.yml/ci/gcpGCP service account
release.yml/ci/sharedRELEASE_PAT for auto-merge
momentic-staging.yml/ci/e2eE2E test + Momentic secrets
staging-canary.yml/ci/e2ePlaywright E2E secrets
stuck-order-monitor.yml/ci/databaseRead-only prod DB
auto-deploy-main.yml/ci/e2ePost-promotion smoke tests

Workflows NOT Migrated (no secrets needed)

Section titled “Workflows NOT Migrated (no secrets needed)”

These workflows use only GITHUB_TOKEN (auto-provided) or no secrets at all:

  • detect-versions.yml
  • test-migrations.yml
  • codeql.yml
  • deploy-dagster.yml (uses GITHUB_TOKEN only)
  • deploy-temporal.yml (uses GITHUB_TOKEN only)
  1. Go to https://infisical.ordermatic.co > Project Settings > Machine Identities
  2. Create a new identity (e.g., github-actions-ci)
  3. Enable Universal Auth method
  4. Copy the Client ID and Client Secret

Create the following folders under both staging and production environments:

  • /ci/shared
  • /ci/cloudflare
  • /ci/gcp
  • /ci/coolify
  • /ci/clerk
  • /ci/posthog
  • /ci/eval
  • /ci/flagsmith
  • /ci/e2e
  • /ci/database
  • /ci/integrations

Copy the current GitHub Secrets values into the corresponding Infisical paths. See the path→secret mapping table above for which secrets go where.

Grant the github-actions-ci identity read access to /ci/* in both staging and production environments.

Add these 3 secrets to the GitHub repository:

  • INFISICAL_UNIVERSAL_AUTH_CLIENT_ID = Client ID from step 1
  • INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET = Client Secret from step 1
  • INFISICAL_PROJECT_ID = your Infisical project ID

After verifying all workflows work with Infisical, remove the ~40 individual secrets from GitHub Settings > Secrets.

# In your workflow job:
env:
INFISICAL_UNIVERSAL_AUTH_CLIENT_ID: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_ID }}
INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET }}
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_PROJECT_ID }}
steps:
- uses: actions/checkout@v4
- name: Fetch secrets from Infisical
uses: ./.github/actions/infisical-secrets
with:
environment: staging # or 'production'
secret-path: /ci/cloudflare # path to your secrets
# All secrets are now available as env vars
- name: Use secrets
run: echo "Token is masked: $CLOUDFLARE_API_TOKEN"