Infisical Operations Cheatsheet
Service: Self-hosted Infisical (secrets management) URL: https://sm.solanasis.com Admin: admin@solanasis.com Last updated: 2026-03-28
Master docs:
- Deep plan:
C:\_my\.claude-plans\deep-plan-infisical-hardening-2026-03-25.md- Original plan:
C:\Users\zasya\.claude\plans\vectorized-frolicking-comet.md- Continuation prompt:
solanasis-docs/temp-working/infisical-hardening-continuation-prompt.md- Service inventory:
solanasis-docs/operations/service-inventory.md- Backup restore instructions:
C:\_my\infisical-backups\README.md
Quick Access
- Navigate to https://sm.solanasis.com
- Cloudflare Access gate appears — enter your
@solanasis.comemail - Check email for One-Time PIN (OTP) from Cloudflare
- Enter OTP — you’re now past the perimeter gate
- Log into Infisical with your Infisical credentials
Allowed emails: mr.sunshine@solanasis.com, ds@solanasis.com
Session duration: 24 hours (Cloudflare Access), then re-authenticate
Managing Secrets
Web UI
- Log in at https://sm.solanasis.com
- Select project “Solanasis Apps”
- Secrets are organized by folder:
/shared/— Secrets shared across all repos (imported into each repo folder)/solanasis-site/— Website-specific secrets/solanasis-scripts/— Script-specific secrets/solanasis-docs/— Docs-specific secrets/matchkeyz/— Matchkeyz-specific secrets
Architecture
/shared/ ← Common secrets (API keys, service credentials)
├── BASEROW_BASE_URL
├── BASEROW_DB_TOKEN
├── BREVO_SMTP_KEY ← Brevo SMTP password (starts with xsmtpsib-)
├── BREVO_SMTP_USER ← Brevo SMTP login (xxx@smtp-brevo.com, NOT sender address)
├── CLOUDFLARE_GLOBAL_API_KEY
├── INFISICAL_BACKUP_PASSPHRASE
└── ... (15 total)
/solanasis-site/ ← Imports from /shared/ via Secret Imports
/solanasis-scripts/ ← Imports from /shared/ via Secret Imports
/solanasis-docs/ ← Imports from /shared/ via Secret Imports
/matchkeyz/ ← Imports from /shared/ via Secret Imports
/mrsunshine-site/ ← Imports from /shared/ via Secret Imports
/selfinquire/ ← Imports from /shared/ via Secret Imports
Adding a new shared secret: Add it to /shared/ — all repo folders inherit it automatically via Secret Imports.
Adding a repo-specific secret: Add it directly to that repo’s folder.
Machine Identity (for API/automation)
- Client ID:
10baaf13-1ca9-468f-ae61-38b76fa060fc - Client Secret:
INFISICAL_CLIENT_SECRET, looked up in order:INFISICAL_CLIENT_SECRETenvironment variableC:\_my\.env(Windows)~/.config/infisical/credentials(WSL/Linux)/mnt/c/_my/.env(WSL fallback via Windows mount)
- Project ID:
ec70b6f3-da5a-4eac-bb7a-e6bbd4c9dd4d - API docs: https://infisical.com/docs/api-reference/overview/introduction
Managing Secrets (CLI)
Script: _solanasis/infisical/manage_secrets.py
Alias: secret (bash alias on WSL, secret.cmd on Windows)
Docs: https://infisical.com/docs/api-reference/overview/introduction
Zero-Disk Secrets (Preferred)
Use secret run to inject secrets as in-memory env vars — no .env file created on disk.
This prevents secret exposure if a directory is accidentally served via tunnel or web server.
# Run a command with secrets injected from an Infisical folder
secret run shared -- python script.py # /shared/ secrets
secret run solanasis-scripts -- python my_script.py # /solanasis-scripts/ + imports
secret run matchkeyz -- dotnet run # /matchkeyz/ + imports
secret run matchkeyz --env staging -- dotnet run # Staging environment
# Cron jobs use cron-wrapper.py for automatic secret injection
python3 cron-wrapper.py shared -- python3 backup-infisical.pyHow it works: Authenticates via Machine Identity → fetches secrets from Infisical API → injects as environment variables into child process → secrets exist only in process memory, never on disk.
Fallback: If Infisical is down, secret run auto-falls back to .env.master
with a warning. Both secret get and secret run support this fallback.
Other Commands
# Set a secret (creates or updates — upsert)
secret set STRIPE_KEY sk_live_xxx # → /shared/ (default)
secret set STRIPE_KEY sk_live_xxx -f solanasis-site # → /solanasis-site/
secret set DB_URL "postgres://..." -c "Production DB" # With comment
# Get a secret
secret get STRIPE_KEY # Pretty output with version info
secret get STRIPE_KEY --plain # Just the value (for scripting)
secret get STRIPE_KEY -f matchkeyz # From specific folder
# List secrets
secret list # All folders, keys only
secret list -f shared # Specific folder
secret list -f shared --values # Show values too
secret list --imports # Include imported (/shared/) secrets
# Delete a secret
secret delete OLD_KEY # Prompts for confirmation
secret delete OLD_KEY --yes # Skip confirmation
secret delete OLD_KEY -f matchkeyz # From specific folder
# Manage folders
secret folders # List all folders
secret folders create new-repo # Create a new folder
# Initialize a new repo (creates folder + secret import + .infisical.json + updates sync_env.py)
secret init new-repo C:\path\to\repo
# Sync secrets to local .env files (legacy — prefer `secret run` instead)
secret sync --all # All repos
secret sync solanasis-site # Specific repo
secret sync --backup # Generate .env.master fallbackDefaults: Environment = dev, Folder = /shared/. Override with -e prod and -f folder-name.
Official Infisical CLI (installed via winget)
# Full-featured CLI for advanced operations
infisical secrets --path=/shared --projectId=ec70b6f3-da5a-4eac-bb7a-e6bbd4c9dd4d
infisical export --path=/solanasis-site --format=dotenv > .env
infisical secrets set KEY=VALUE --path=/shared
infisical scan # Scan for leaked secrets in git historyEnv vars configured: INFISICAL_API_URL=http://localhost:8580, INFISICAL_DISABLE_UPDATE_CHECK=true
Syncing Secrets to Local .env Files (Legacy)
Prefer
secret runinstead — it injects secrets at runtime without creating.envfiles on disk. Usesecret synconly when a tool specifically requires a.envfile and cannot accept environment variables.
Script: _solanasis/infisical/sync_env.py
# Sync all repos
secret sync --all
# Sync a specific repo
secret sync solanasis-site
# Generate .env.master fallback file
secret sync --backupFallback (.env.master)
When Infisical is down, secret get, secret list, and secret run automatically
fall back to .env.master (cross-platform: C:\_my\.env.master or /mnt/c/_my/.env.master).
# Generate/refresh the fallback file
secret sync --backup
# Manual fallback test
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml down
secret get BASEROW_BASE_URL --plain # Should show [FALLBACK] warning + value
secret run shared -- echo "works too" # secret run also falls back
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml up -dWhat works in fallback mode: get, list, run
What does NOT work: set, delete, init, folders (require Infisical to be running)
Environment Hierarchy
| Environment | Slug | Usage |
|---|---|---|
| Development | dev | Default. Local development. |
| Staging | staging | QA / pre-prod testing. |
| Production | prod | Live production values. |
# Access different environments
secret get KEY -f matchkeyz --env staging # QA environment
secret list -f shared --env prod # Production secrets
python sync_env.py matchkeyz --env staging # Sync QA .envFolders (projects) x Environments (stages) form a 2D matrix:
/shared/xdev= shared development secrets/matchkeyz/xstaging= Matchkeyz QA secrets/matchkeyz/xprod= Matchkeyz production secrets
Backup & Restore
Automated Backup
- Schedule: Daily at 2:00 AM (WSL cron via
cron-wrapper.py) - Verification: Sunday 6:30 AM (WSL cron — decrypts + validates latest backup)
- Script:
solanasis-docs/scheduled-tasks/scripts/backup-infisical.py - Pipeline: pg_dump + .env → tar.gz → AES-256-CBC encrypt → git push to GitHub
- Storage:
dzinreach/infisical-backups(private repo) + localinfisical-backups/ - Retention: 7 daily + 4 weekly rolling
- Logs:
solanasis-docs/logs/infisical-backup-*.log,infisical-verify-*.log
Passphrase
- Windows env var:
INFISICAL_BACKUP_PASSPHRASE - Bitwarden: “Infisical Backup Encryption Passphrase”
- Infisical:
/shared/INFISICAL_BACKUP_PASSPHRASE
Manual Backup
python C:\_my\_solanasis\solanasis-docs\scheduled-tasks\scripts\backup-infisical.pyRestore Procedure
Full instructions: C:\_my\infisical-backups\README.md
# 1. Decrypt
openssl enc -aes-256-cbc -d -pbkdf2 -iter 600000 \
-in daily/infisical-backup-YYYY-MM-DD.tar.gz.enc \
-out backup.tar.gz
# Enter passphrase when prompted (from Bitwarden or env var)
# 2. Extract
tar xzf backup.tar.gz
# Yields: infisical_dump.sql, dot_env
# 3. Restore .env
cp dot_env C:\_my\_solanasis\infisical\.env
# 4. Restore database
docker exec -i infisical-db psql -U infisical -c "DROP DATABASE IF EXISTS infisical;"
docker exec -i infisical-db psql -U infisical -c "CREATE DATABASE infisical;"
docker exec -i infisical-db psql -U infisical -d infisical < infisical_dump.sql
# 5. Restart
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml restart
# 6. Verify — open https://sm.solanasis.com and check secrets are intactTesting
Test file: C:\_my\_solanasis\infisical\test_sync_env.py
# Preflight health check (credential lookup, Infisical auth, repo paths)
python test_sync_env.py --check-only
# Full test suite (unit + live smoke test — needs Infisical running)
pytest test_sync_env.py -v
# Unit tests only (no Infisical dependency)
pytest test_sync_env.py -v -k "not smoke"
# Smoke test only (sets _TEST_CANARY key, syncs, verifies, cleans up)
pytest test_sync_env.py -v -k smokeWhat’s covered:
_resolve_path— Windows-to-WSL path translation (9 cases)get_client_secret— credential file parsing and error handlingwrite_env_file— output format, quoting, escaping, line endingsdetect_repo— auto-detection from working directory- Smoke test — live round-trip:
set → get → fetch → write .env → delete
WSL Cross-Platform Support
Both manage_secrets.py and sync_env.py work on Windows and WSL.
Windows paths in the REPOS dict (C:\_my\...) are translated to WSL
mount paths (/mnt/c/_my/...) at runtime via _resolve_path().
Docker Management
Config Files
- Docker Compose:
C:\_my\_solanasis\infisical\docker-compose.yml - Environment:
C:\_my\_solanasis\infisical\.env - Infisical docs: https://infisical.com/docs/self-hosting/deployment-options/docker-compose
Common Commands
# Check container status
docker ps --filter "name=infisical"
# View logs (follow)
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml logs -f backend
# Restart all containers
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml restart
# Restart just the backend
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml restart backend
# Stop everything
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml down
# Start everything
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml up -d
# Update to latest image
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml pull
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml up -d
# Check database health
docker exec infisical-db pg_isready -U infisicalContainer Details
| Container | Image | Port | Purpose |
|---|---|---|---|
| infisical-backend | infisical/infisical:latest | 8580→8080 | API + Web UI |
| infisical-db | postgres:14-alpine | 5432 (internal) | Database |
| infisical-redis | redis:7-alpine | 6379 (internal) | Cache |
Cloudflare Access Management
Current Config
- Zero Trust org: solanasis.cloudflareaccess.com
- Access app: “Infisical Vault” (ID:
da38e27f-5a00-4378-afbe-4b7219ceff64) - Identity provider: One-Time PIN / email OTP (ID:
0e45b63d-da8a-45f8-8d46-a45b31019690) - Policy: Allow
mr.sunshine@solanasis.comandds@solanasis.com - Session duration: 24 hours
- Cloudflare docs: https://developers.cloudflare.com/cloudflare-one/
API Credentials
- Account ID:
5bc74cd88016b1dd85d05955675fdba8 - Auth header:
X-Auth-Email: mr.sunshine@solanasis.com - Auth key:
CLOUDFLARE_GLOBAL_API_KEY(Windows env var + Infisical/shared/)
Add a New Allowed Email
CF_KEY=$(powershell -Command "[System.Environment]::GetEnvironmentVariable('CLOUDFLARE_GLOBAL_API_KEY', 'User')")
# Get current policy
curl -s "https://api.cloudflare.com/client/v4/accounts/5bc74cd88016b1dd85d05955675fdba8/access/apps/da38e27f-5a00-4378-afbe-4b7219ceff64/policies/3a898274-8606-41f7-9efd-c322f90aa21a" \
-H "X-Auth-Email: mr.sunshine@solanasis.com" \
-H "X-Auth-Key: $CF_KEY"
# Update policy to add new email (include ALL existing emails + new one)
curl -s -X PUT "https://api.cloudflare.com/client/v4/accounts/5bc74cd88016b1dd85d05955675fdba8/access/apps/da38e27f-5a00-4378-afbe-4b7219ceff64/policies/3a898274-8606-41f7-9efd-c322f90aa21a" \
-H "X-Auth-Email: mr.sunshine@solanasis.com" \
-H "X-Auth-Key: $CF_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Solanasis Team",
"decision": "allow",
"include": [
{"email": {"email": "mr.sunshine@solanasis.com"}},
{"email": {"email": "ds@solanasis.com"}},
{"email": {"email": "NEW_EMAIL@solanasis.com"}}
]
}'WAF Rate Limiting
- Ruleset ID:
63dd254071b6436fa7e377ecd54681a2 - Rule: 10 req per 10s per IP on
/api/paths, block 10s - Zone ID:
ceb3c9dcba422dc31900360da7117173
Security Layers
| Layer | What It Does | Config Location |
|---|---|---|
| Cloudflare Access (OTP) | Perimeter gate — email allowlist + OTP | Cloudflare Zero Trust dashboard |
| Infisical auth | Application login (email + password) | Infisical admin panel |
| Invite-only signup | Blocks new registrations | INVITE_ONLY_SIGNUP=true in .env |
| Email domain restriction | Only @solanasis.com can register | Infisical admin panel (allowedSignUpDomain) |
| WAF rate limiting | 10 req/10s per IP on API endpoints | Cloudflare WAF rulesets |
| Encrypted backups | AES-256-CBC encrypted daily backups | Backup script + GitHub |
Emergency Procedures
ENCRYPTION_KEY Lost
Severity: Critical — ALL secrets in Infisical become unrecoverable.
- Check Bitwarden first: ENCRYPTION_KEY and AUTH_SECRET are stored in Bitwarden vault
- If not in Bitwarden: Decrypt the latest daily backup (see Restore Procedure above)
- The
dot_envfile in the archive contains the ENCRYPTION_KEY - Copy it back to
C:\_my\_solanasis\infisical\.env - Restart containers
If neither Bitwarden nor backup has it: All stored secrets are permanently lost. You’ll need to:
- Delete Docker volumes:
docker volume rm infisical_pg_data infisical_redis_data - Set up Infisical from scratch with a new ENCRYPTION_KEY
- Re-enter all secrets manually
Cannot Access sm.solanasis.com
- Check Cloudflare tunnel:
sudo systemctl status cloudflared(in WSL2) - Check Docker containers:
docker ps --filter "name=infisical" - Check localhost directly:
curl http://localhost:8580(bypasses Cloudflare) - Restart tunnel:
sudo systemctl restart cloudflared(in WSL2) - Restart containers:
docker compose -f C:\_my\_solanasis\infisical\docker-compose.yml restart
Cloudflare Access Issues
- Check identity providers: API GET
/accounts/{acct}/access/identity_providers - Check app config: API GET
/accounts/{acct}/access/apps - Cloudflare status: https://www.cloudflarestatus.com/