Environment Variables Reference¶
This document provides a complete reference for all environment variables used by CertifyClouds.
Quick Reference¶
Required for Production¶
| Variable | Description | Example |
|---|---|---|
DB_PASSWORD | PostgreSQL password | openssl rand -hex 16 |
SECRET_KEY | Application secret key | openssl rand -hex 32 |
CERTIFYCLOUDS_LICENSE_KEY | License key | CC-XXXX-XXXX-XXXX |
CORS_ALLOWED_ORIGINS | Allowed CORS origins | https://yourdomain.com |
Required for Azure¶
At least one authentication method:
| Method | Variables |
|---|---|
| Managed Identity | AZURE_USE_MANAGED_IDENTITY=true |
| Service Principal | AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET |
Database Configuration¶
| Variable | Description | Default | Required |
|---|---|---|---|
DATABASE_URL | PostgreSQL connection string | - | Yes (production) |
DB_PASSWORD | Database password | - | Yes (production) |
DATABASE_POOL_SIZE | Connection pool size | Configured internally | No |
DATABASE_MAX_OVERFLOW | Max overflow connections for burst | Configured internally | No |
DATABASE_POOL_RECYCLE | Pool recycle time (seconds) | Configured internally | No |
DATABASE_POOL_TIMEOUT | Pool timeout (seconds) | 60 | No |
Example:
DB_PASSWORD=<YOUR_SECURE_PASSWORD>
DATABASE_URL=postgresql://<DB_USER>:${DB_PASSWORD}@<YOUR_DB_HOST>:5432/<DB_NAME>
Security Configuration¶
| Variable | Description | Default | Required |
|---|---|---|---|
SECRET_KEY | Application secret for credential encryption + audit-log HMAC | - | Yes (production) |
JWT_SECRET | Signs auth tokens issued at login | Falls back to SECRET_KEY | No (recommended) |
RATE_LIMIT_PER_MINUTE | API rate limit per minute per IP | Configured internally | No |
RATE_LIMIT_PER_HOUR | API rate limit per hour per IP | Configured internally | No |
COOKIE_SECURE | Require HTTPS for auth cookies | true | No |
COOKIE_SAMESITE | SameSite cookie policy | strict | No |
Generating SECRET_KEY:
JWT_SECRET: separate session key for forced-logout drills
By default the JWT signing key falls back to SECRET_KEY. Setting a separate JWT_SECRET (also openssl rand -hex 32) lets you rotate the auth key in isolation. Useful if you ever need to force every active user to re-authenticate (suspected token compromise, audit response, employee offboarding sweep) without re-encrypting every stored cloud credential. The onboarding .env we generate for new customers pre-populates both. Existing deployments can add it any time; restart invalidates all current sessions and users sign in again.
SECRET_KEY persistence: read this before your first redeploy
SECRET_KEY is the master encryption key for every cloud credential stored in your database: AWS access keys, GCP service-account JSON, B2C tenant secrets, SSO client secrets, SMTP passwords. Lose it and these credentials become unrecoverable; they must be re-entered through the UI.
On every startup, CertifyClouds runs a boot canary: it decrypts one row of encrypted data using the current SECRET_KEY. If decryption fails, the container refuses to start with SECRET_KEY does not match the encrypted credentials stored in the database.
Persist SECRET_KEY somewhere durable:
- Keep the original
.envfile from your initial deploy (the onboarding package already writesSECRET_KEY=...there). - Or store it in Azure Key Vault and inject as an env var at container deploy time.
- Do not rely on regenerating it. The auto-generation in
deploy-certifyclouds-{aci,cae}.shonly applies to fresh deploys with no existing data.
Recovery if lost: Restore the original SECRET_KEY from a backup. If no backup exists, the only option is to clear the encrypted columns from the database (automation_sync_configs, b2c_tenants, alerts_email_config, sso_config) and re-enter every credential through the UI. See Troubleshooting for the exact SQL.
Authentication Security Hardening¶
CertifyClouds includes configurable security controls for authentication hardening:
| Variable | Description | Default |
|---|---|---|
ACCOUNT_LOCKOUT_ATTEMPTS | Failed login attempts before lockout | Configurable |
ACCOUNT_LOCKOUT_DURATION_MINUTES | Lockout duration | Configurable |
SESSION_IDLE_TIMEOUT_MINUTES | Session idle timeout (0 to disable) | Configurable |
LOGIN_RATE_LIMIT_PER_MINUTE | Max login attempts per minute per IP | Configurable |
ENABLE_IP_BINDING | Bind sessions to IP address | false |
IP_BINDING_MODE | IP binding enforcement mode | warn |
IP Binding
IP binding may cause issues for users on VPN or mobile networks where IP addresses change frequently. Use warn mode to log IP changes without blocking, or block to enforce strict IP binding.
Initial Admin Account¶
On first startup, if no users exist, CertifyClouds creates an initial admin account:
| Variable | Description | Default | Required |
|---|---|---|---|
INITIAL_ADMIN_USERNAME | Initial admin username | admin | No |
INITIAL_ADMIN_PASSWORD | Initial admin password | - | Yes (first startup) |
Example:
Important
Change this password after first login via Settings > User Management.
CORS Configuration¶
| Variable | Description | Default | Required |
|---|---|---|---|
CORS_ALLOWED_ORIGINS | Comma-separated allowed origins | http://localhost:3000,... | No (see note) |
Why CORS rarely matters for CertifyClouds deployments
CertifyClouds ships the React frontend and the API from the same container at the same origin. When your users load https://certifyclouds.mycompany.com, the SPA's API calls go to https://certifyclouds.mycompany.com/api/*. Same origin, so the browser never triggers CORS. The allow-list is only consulted for genuinely cross-origin requests, which a stock deployment doesn't generate.
Set CORS_ALLOWED_ORIGINS explicitly only if you split frontend and API onto different hosts (e.g., API on api.mycompany.com, SPA on app.mycompany.com) or you consume the API from another web app on a different domain. For the standard same-origin deployment the default is harmless even with localhost entries in it.
The startup logs only warn when * appears in the list. That's the only setting that actually weakens the API's cross-origin exposure.
Examples:
# Development
CORS_ALLOWED_ORIGINS=http://localhost:8080,http://localhost:3000
# Production with split frontend/API hosts
CORS_ALLOWED_ORIGINS=https://app.mycompany.com,https://api.mycompany.com
Azure Authentication¶
Supported Methods: CertifyClouds supports Azure CLI, Service Principal, and Managed Identity authentication. Configure the method appropriate for your environment.
Option 1: Local Development (Azure CLI)¶
| Variable | Description | Default |
|---|---|---|
AZURE_LOCAL_AUTH | Use Azure CLI from host | false |
Usage:
Best for: Local development, testing
Option 2: Service Principal¶
| Variable | Description | Required |
|---|---|---|
AZURE_TENANT_ID | Azure AD tenant ID | Yes |
AZURE_CLIENT_ID | Service principal client ID | Yes |
AZURE_CLIENT_SECRET | Service principal secret | Yes |
Usage:
AZURE_TENANT_ID=<YOUR_TENANT_ID>
AZURE_CLIENT_ID=<YOUR_CLIENT_ID>
AZURE_CLIENT_SECRET=<YOUR_CLIENT_SECRET>
Best for: On-premises deployments, non-Azure cloud
Option 3: Managed Identity (Recommended for Production)¶
| Variable | Description | Default |
|---|---|---|
AZURE_USE_MANAGED_IDENTITY | Enable managed identity auth | false |
Usage:
Best for: Azure VMs, Azure Container Instances, Azure Kubernetes Service
Azure Subscription Filtering¶
| Variable | Description | Default |
|---|---|---|
DISCOVERY_TARGET_SUBSCRIPTION | Scan only this subscription | All accessible |
DISCOVERY_ALLOWED_SUBSCRIPTIONS | Comma-separated allowed subscription IDs | All accessible |
Examples:
# Scan single subscription
DISCOVERY_TARGET_SUBSCRIPTION=<YOUR_SUBSCRIPTION_ID>
# Scan specific subscriptions
DISCOVERY_ALLOWED_SUBSCRIPTIONS=<SUB_ID_1>,<SUB_ID_2>,<SUB_ID_3>
License Configuration¶
| Variable | Description | Default | Required |
|---|---|---|---|
CERTIFYCLOUDS_LICENSE_KEY | License key (CC-XXXX-XXXX-XXXX) | - | Yes |
CERTIFYCLOUDS_LICENSE_SERVER | License validation server | https://license.certifyclouds.com/api/validate | No |
CERTIFYCLOUDS_LICENSE_GRACE_DAYS | Days to use cached license if server unreachable | 7 | No |
Example:
Email Notifications¶
Option 1: SMTP¶
| Variable | Description | Default | Required |
|---|---|---|---|
SMTP_HOST | SMTP server hostname | - | Yes (if using SMTP) |
SMTP_PORT | SMTP server port | 2525 | No |
SMTP_USE_TLS | Use TLS for SMTP connection | true | No |
SMTP_USERNAME | SMTP username | - | Yes (if using SMTP) |
SMTP_PASSWORD | SMTP password | - | Yes (if using SMTP) |
SMTP_FROM_EMAIL | From email address | alerts@certifyclouds.com | No |
SMTP_FROM_NAME | From display name | CertifyClouds Alerts | No |
Example:
SMTP_HOST=<YOUR_SMTP_HOST>
SMTP_PORT=<YOUR_SMTP_PORT>
SMTP_USERNAME=<YOUR_SMTP_USERNAME>
SMTP_PASSWORD=<YOUR_SMTP_PASSWORD>
SMTP_FROM_EMAIL=alerts@mycompany.com
SMTP_FROM_NAME=CertifyClouds Alerts
Option 2: SendGrid¶
| Variable | Description | Default | Required |
|---|---|---|---|
SENDGRID_API_KEY | SendGrid API key | - | Yes (if using SendGrid) |
SENDGRID_FROM_EMAIL | From email address | alerts@certifyclouds.com | No |
SENDGRID_FROM_NAME | From display name | CertifyClouds Alerts | No |
Example:
SENDGRID_API_KEY=<YOUR_SENDGRID_API_KEY>
SENDGRID_FROM_EMAIL=alerts@yourcompany.com
SENDGRID_FROM_NAME=CertifyClouds Alerts
Logging Configuration¶
| Variable | Description | Default | Options |
|---|---|---|---|
LOG_LEVEL | Logging level | INFO | DEBUG, INFO, WARNING, ERROR, CRITICAL |
LOG_FILE | Log file path (optional) | - | Any valid path |
LOG_MAX_BYTES | Max log file size in bytes | 10MB | Any integer |
LOG_BACKUP_COUNT | Number of backup log files to retain | Configured internally | 0-10 |
Example:
Performance Tuning¶
UI Configuration
Most performance settings are UI-configurable via Settings > Advanced tab. The priority is: Database (UI) > Environment Variable > Default. Use environment variables to enforce settings that users cannot override.
Discovery Scanning¶
| Variable | Description | Range | UI-Configurable |
|---|---|---|---|
DISCOVERY_MAX_WORKERS | Concurrent scan workers | 1-20 | Yes |
DISCOVERY_SCAN_TIMEOUT | Scan timeout (seconds) | 60-600 | Yes |
DISCOVERY_MAX_RETRIES | Max retry attempts per vault | 0-5 | Yes |
DISCOVERY_RETRY_WAIT_MIN | Min retry wait (seconds) | 0-10 | Yes |
DISCOVERY_RETRY_WAIT_MAX | Max retry wait (seconds) | 1-30 | Yes |
Automation Rotation (PRO + ENTERPRISE)¶
| Variable | Description | Range | UI-Configurable |
|---|---|---|---|
ROTATION_MAX_WORKERS | Concurrent workers for hint prefetching | 1-50 | Yes |
ROTATION_CACHE_TTL_MINUTES | Cache TTL (minutes) | 1-60 | Yes |
ROTATION_WORKER_TIMEOUT | Worker timeout (seconds) | 1+ | No |
ROTATION_CHECK_INTERVAL_SECONDS | Rotation check interval (seconds) | 60+ | No |
ROTATION_MAX_CONCURRENT_JOBS | Max concurrent rotation jobs | 1-20 | No |
ROTATION_BATCH_SIZE | Rotation batch size | 1+ | No |
Multi-Cloud Sync (PRO + ENTERPRISE)¶
Sync intervals are controlled by the background worker and are not configurable via environment variables. AWS and GCP credentials entered in the UI are encrypted using SECRET_KEY before being stored in the database.
Compliance¶
| Variable | Description | Default | Range |
|---|---|---|---|
COMPLIANCE_SCAN_TIMEOUT | Compliance scan timeout (seconds) | 30 | 5+ |
API¶
| Variable | Description | Default | Range |
|---|---|---|---|
API_BATCH_MAX_WORKERS | Concurrent API batch workers | 5 | 1-20 |
API_REQUEST_TIMEOUT | API request timeout (seconds) | 30 | 5+ |
Notifications¶
| Variable | Description | Default | Range |
|---|---|---|---|
NOTIFICATION_WEBHOOK_TIMEOUT | Webhook delivery timeout (seconds) | 10 | 5+ |
NOTIFICATION_EMAIL_TIMEOUT | Email delivery timeout (seconds) | 30 | 5+ |
Feature Flags¶
UI Configuration
Feature flags are UI-configurable via Settings > Advanced tab.
| Variable | Description | Default |
|---|---|---|
ENABLE_HINT_CACHING | Enable hint caching | true |
ENABLE_NOTIFICATIONS | Enable email/webhook alert notifications | true |
ENABLE_SUBSCRIPTION_MATCHING | Enable subscription matching | true |
ENABLE_COMPLIANCE_SCANNING | Enable compliance scanning | true |
Environment Mode¶
| Variable | Description | Default | Options |
|---|---|---|---|
ENVIRONMENT | Environment name | development | development, staging, production |
Production mode enforces:
SECRET_KEYmust not be defaultAZURE_TENANT_IDis required- Additional security validations
Docker/Deployment Variables¶
| Variable | Description | Default |
|---|---|---|
PORT | Application port | 8080 |
APP_PORT | Host port mapping | 8080 |
APP_VERSION | Semantic version (shown in UI footer) | 1.0.0 |
CERTIFYCLOUDS_VERSION | Docker image tag | latest |
Build Metadata¶
These variables are set during Docker image build and are embedded in the running container. You do not need to set them manually.
| Variable | Description |
|---|---|
BUILD_DATE | Image build date (ISO 8601) |
GIT_COMMIT | Git commit hash (8 characters) |
CI/CD Integration¶
For using cc-scan in GitHub Actions, Azure DevOps, or GitLab CI pipelines, see the CI/CD Integration Guide.
Example .env Files¶
Development¶
# Development .env
ENVIRONMENT=development
DATABASE_URL=postgresql://<DB_USER>:<YOUR_SECURE_PASSWORD>@<DB_HOST>:5432/<DB_NAME>
CERTIFYCLOUDS_LICENSE_KEY=<YOUR_LICENSE_KEY>
AZURE_LOCAL_AUTH=true
LOG_LEVEL=DEBUG
CORS_ALLOWED_ORIGINS=http://localhost:8080,http://localhost:3000
Production¶
# Production .env
ENVIRONMENT=production
DB_PASSWORD=<YOUR_SECURE_PASSWORD>
DATABASE_URL=postgresql://<DB_USER>:${DB_PASSWORD}@<YOUR_DB_HOST>:5432/<DB_NAME>
SECRET_KEY=<YOUR_SECRET_KEY>
CERTIFYCLOUDS_LICENSE_KEY=<YOUR_LICENSE_KEY>
# Azure (choose one)
AZURE_USE_MANAGED_IDENTITY=true
# OR
AZURE_TENANT_ID=<YOUR_TENANT_ID>
AZURE_CLIENT_ID=<YOUR_CLIENT_ID>
AZURE_CLIENT_SECRET=<YOUR_CLIENT_SECRET>
# CORS
CORS_ALLOWED_ORIGINS=https://certifyclouds.mycompany.com
# Notifications (optional)
SENDGRID_API_KEY=<YOUR_SENDGRID_API_KEY>
SENDGRID_FROM_EMAIL=alerts@mycompany.com
# Logging
LOG_LEVEL=INFO
Validation¶
CertifyClouds validates configuration on startup. In production mode:
SECRET_KEYmust be changed from defaultAZURE_TENANT_IDis required- All database connection parameters must be valid
Check configuration: