Skip to main content

Infisical Secrets Management

Source: Anshin SRE Team — Infrastructure knowledge base, Rev 1.0, 2026-01-24

MANDATORY — Never hardcode secrets

All secrets (passwords, API keys, credentials, tokens) MUST be stored in Infisical. NEVER hardcode secrets in K8s YAML, .env files, or any file committed to git.

Quick Reference

ItemValue
Infisical URLhttps://infisical.svcs.anshinhealth.net
Auth endpointPOST /api/v1/auth/universal-auth/login
Client IDsettings.jsonmcpServers.infisical.env.INFISICAL_CLIENT_ID
Client Secretsettings.jsonmcpServers.infisical.env.INFISICAL_CLIENT_SECRET
Org ID6ee19673-90fe-4c2c-8e5f-1ebd9a9f7cf1
K8s operator namespaceinfisical-operator
K8s auth secretinfisical-universal-auth in infisical-operator namespace

Existing Projects

ProjectSlugEnvironmentUsage
Anshin DocSignanshin-docsignprodDocSign e-signature platform
Anshin SecureDocsanshin-securedocsprodSecureDocs e-signature platform

Step-by-Step: Complete Infisical Setup for a New Project

Step 1: Authenticate

TOKEN=$(curl -s -X POST "https://infisical.svcs.anshinhealth.net/api/v1/auth/universal-auth/login" \
-H "Content-Type: application/json" \
-d '{"clientId":"<CLIENT_ID>","clientSecret":"<CLIENT_SECRET>"}' \
| python -c "import sys,json; print(json.load(sys.stdin)['accessToken'])")

Get CLIENT_ID and CLIENT_SECRET from settings.jsonmcpServers.infisical.env:

  • INFISICAL_CLIENT_ID
  • INFISICAL_CLIENT_SECRET

Step 2: Create Project (if it doesn't exist)

curl -s -X POST "https://infisical.svcs.anshinhealth.net/api/v2/workspace" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"projectName":"<project-name>","slug":"<project-slug>"}' \
| python -c "import sys,json; d=json.load(sys.stdin); print(f'Project ID: {d[\"project\"][\"id\"]}')"

This creates the project with dev, staging, and prod environments automatically.

Step 3: Create Secrets

# Reusable function to create a single secret
create_secret() {
curl -s -X POST "https://infisical.svcs.anshinhealth.net/api/v3/secrets/raw/$1" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"workspaceId\":\"<PROJECT_ID>\",\"environment\":\"prod\",\"secretPath\":\"/\",\"secretValue\":\"$2\",\"type\":\"shared\"}" \
| python -c "import sys,json; d=json.load(sys.stdin); print(f' {d.get(\"secret\",{}).get(\"secretKey\",\"ERROR\")}: OK')"
}

# Example: create secrets for a project
create_secret "APP_ID" "myapp"
create_secret "SMTP_HOST" "smtp.gmail.com"
create_secret "SMTP_PASS" "the-actual-password"

Step 4: Read / Verify Secrets

curl -s "https://infisical.svcs.anshinhealth.net/api/v3/secrets/raw?workspaceSlug=<slug>&environment=prod&secretPath=/" \
-H "Authorization: Bearer $TOKEN" \
| python -c "
import sys,json
d=json.load(sys.stdin)
for s in d.get('secrets',[]):
print(f\" {s['secretKey']:25s} = {s['secretValue'][:20]}...\")
"

Step 5: Update a Secret

curl -s -X PATCH "https://infisical.svcs.anshinhealth.net/api/v3/secrets/raw/<SECRET_KEY>" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"workspaceSlug\":\"<slug>\",\"environment\":\"prod\",\"secretPath\":\"/\",\"secretValue\":\"<new-value>\"}"

Step 6: K8s InfisicalSecret CR (replaces hardcoded K8s Secrets)

Create this manifest in the project's K8s directory (e.g., k8s/base/01-secrets.yaml):

apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
name: <project>-infisical-sync
namespace: <namespace>
spec:
hostAPI: https://infisical.svcs.anshinhealth.net/api
resyncInterval: 60
authentication:
universalAuth:
secretsScope:
projectSlug: <infisical-project-slug>
envSlug: prod
secretsPath: /
credentialsRef:
secretName: infisical-universal-auth
secretNamespace: infisical-operator
managedSecretReference:
secretName: <project>-infisical
secretNamespace: <namespace>
secretType: Opaque
creationPolicy: Owner

The Infisical Operator (running in infisical-operator namespace) picks up this CR and automatically syncs secrets from Infisical into a regular K8s Secret named <project>-infisical. The sync interval is 60 seconds.

Step 7: Reference in Deployments

Option A — envFrom (all secrets as environment variables):

containers:
- name: my-app
envFrom:
- secretRef:
name: <project>-infisical

Option B — individual key reference:

env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: <project>-infisical
key: DATABASE_URL

SMTP Configuration (Gmail — Shared Across Projects)

SettingValue
Hostsmtp.gmail.com
Port465 (SSL)
Usersettings.jsongmail_smtp.user
App Passwordsettings.jsongmail_smtp.app_phrase

Always store in Infisical with these keys: SMTP_HOST, SMTP_PORT, SMTP_USER_EMAIL, SMTP_PASS


Anti-Patterns

❌ Never Do This✅ Correct Approach
Hardcode passwords in K8s YAML stringDataStore in Infisical, use InfisicalSecret CR
Commit .env files with real credentialsAdd to .gitignore, use Infisical
Put secrets in CLAUDE.md, docs, or wikisReference settings.json keys only
Create K8s Secrets manually via kubectl create secretUse InfisicalSecret CR for auto-sync
Store SMTP password in plain YAMLStore in Infisical as SMTP_PASS
Use stringData in git-tracked K8s manifestsInfisicalSecret CR only

Worked Example: anshin-securedocs

Complete end-to-end setup that was performed for the SecureDocs project:

  1. Authenticated with universal auth credentials from settings.json
  2. Created project anshin-securedocs (slug: anshin-securedocs)
  3. Created 17 secrets in prod environment: APP_ID, MASTER_KEY, appName, MONGO_USERNAME, MONGO_PASSWORD, MONGODB_URI, PUBLIC_URL, SERVER_URL, PARSE_MOUNT, NODE_ENV, GENERATE_SOURCEMAP, USE_LOCAL, SMTP_ENABLE, SMTP_HOST, SMTP_PORT, SMTP_USER_EMAIL, SMTP_PASS
  4. Replaced k8s/base/01-secrets.yaml from hardcoded Secret resources to InfisicalSecret CR
  5. Updated server deployment to use envFrom: secretRef: securedocs-infisical
  6. Updated MongoDB deployment to reference securedocs-infisical instead of securedocs-mongodb
  7. Result: Zero plaintext secrets in any git-tracked file

Document Control

RevDateAuthorDescription
1.02026-01-24Anshin SRE TeamInitial release