Environment Variables Reference¶
Complete reference for environment variables in Airbase
This document provides a comprehensive reference for all environment variables used in Airbase, including system-provided variables and user-defined configuration.
Overview¶
Environment variables in Airbase provide configuration for your applications without requiring code changes or rebuilds. They are injected into your container at runtime.
Key concepts: - System variables: Automatically provided by Airbase - User variables: Defined in .env files - Environment-specific: Different values per environment (staging, production) - Runtime injection: Available when container starts
System-Provided Variables¶
These variables are automatically set by Airbase and available to all applications.
PORT¶
Description: The port your application must listen on
Type: Integer
Example value: 3000, 8080, 8501
Required: Yes - your application MUST bind to this port
Usage:
Notes: - Airbase assigns this dynamically - Do not hardcode port numbers in your application - Always bind to 0.0.0.0 (not localhost or 127.0.0.1) - Default port in Dockerfile should be 3000 for consistency
ENVIRONMENT¶
Description: The name of the current deployment environment
Type: String
Possible values: staging, production, or custom environment names
Example usage:
const env = process.env.ENVIRONMENT;
if (env === 'production') {
console.log('Running in production mode');
}
Notes: - Use this to enable environment-specific features - Useful for conditional logging, feature flags, etc. - Not the same as NODE_ENV (you should set that separately)
APP_NAME¶
Description: Your application name from airbase.json
Type: String
Example value: my-app, data-dashboard
Usage:
Notes: - Derived from airbase.json configuration - Useful for logging and monitoring
PROJECT_HANDLE¶
Description: Your project handle in the format namespace/name
Type: String
Example value: myteam/myapp, analytics/dashboard
Usage:
Notes: - Unique identifier for your project in Airbase - Format: {namespace}/{project-name}
User-Defined Variables¶
Variables you define in .env files for your application configuration.
Variable Definition¶
File location: Project root
File names: - .env - Production environment - .env.staging - Staging environment - .env.development - Development environment (local only) - .env.{custom} - Custom environment names
Format:
# Comments start with #
VARIABLE_NAME=value
DATABASE_URL=postgres://db.internal.gov.sg:5432/myapp
API_KEY=abc123xyz789
LOG_LEVEL=info
# Multi-line values (use quotes)
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"
Variable Syntax Rules¶
Naming Conventions¶
Valid variable names: - Must start with letter or underscore - Can contain letters, numbers, underscores - Case-sensitive (by convention, use UPPERCASE) - No spaces
Examples:
# ✅ Valid
DATABASE_URL=value
API_KEY=value
MAX_CONNECTIONS=100
_INTERNAL_VAR=value
# ❌ Invalid
123_VAR=value # Cannot start with number
MY-VAR=value # Hyphens not allowed
MY VAR=value # Spaces not allowed
Value Formatting¶
Simple values:
Values with spaces (use quotes):
Multi-line values (use quotes):
Special characters (escape or quote):
# Quotes protect special characters
PASSWORD="p@ssw0rd!#$"
CONNECTION_STRING="Server=db;User=admin;Password=p@ss"
Empty values:
# Empty value (variable exists but is empty)
OPTIONAL_CONFIG=
# Unset variable (comment it out)
# OPTIONAL_CONFIG=value
Variable Precedence¶
When multiple sources define the same variable, Airbase uses this precedence order (highest to lowest):
- Environment-specific
.envfile (e.g.,.env.staging) - Default
.envfile (if no environment-specific file exists) - System-provided variables (PORT, ENVIRONMENT, etc.)
Example:
# .env (production default)
DATABASE_URL=postgres://prod-db.internal.gov.sg:5432/myapp
LOG_LEVEL=error
# .env.staging (staging-specific)
DATABASE_URL=postgres://staging-db.internal.gov.sg:5432/myapp
LOG_LEVEL=debug
Result: - Deploying to staging: Uses .env.staging values - Deploying to production: Uses .env values
Variable Categories¶
Database Configuration¶
Common patterns:
# PostgreSQL
DATABASE_URL=postgres://user:password@host:5432/dbname
# MySQL
DATABASE_URL=mysql://user:password@host:3306/dbname
# MongoDB
MONGODB_URI=mongodb://user:password@host:27017/dbname
# Redis
REDIS_URL=redis://host:6379
# Connection pool settings
DB_POOL_MIN=2
DB_POOL_MAX=10
DB_TIMEOUT=30000
API Configuration¶
Common patterns:
# External API endpoints
API_BASE_URL=https://api.example.gov.sg
API_TIMEOUT=30000
API_RETRY_COUNT=3
# Authentication
API_KEY=your-api-key-here
API_SECRET=your-api-secret-here
JWT_SECRET=your-jwt-secret-here
# Rate limiting
API_RATE_LIMIT=1000
API_RATE_WINDOW=3600
Application Configuration¶
Common patterns:
# Logging
LOG_LEVEL=info # trace, debug, info, warn, error, fatal
LOG_FORMAT=json # json, text, pretty
# Features flags
ENABLE_ANALYTICS=true
ENABLE_DEBUG_MODE=false
MAINTENANCE_MODE=false
# Application behavior
SESSION_TIMEOUT=3600
MAX_UPLOAD_SIZE=10485760 # 10MB in bytes
CACHE_TTL=300 # 5 minutes
Security Configuration¶
Common patterns:
# Secrets (rotate regularly)
SESSION_SECRET=random-secret-string-here
ENCRYPTION_KEY=32-character-encryption-key-here
# CORS
CORS_ORIGIN=https://app.example.gov.sg
CORS_CREDENTIALS=true
# Security headers
CSP_REPORT_URI=https://csp-reporter.example.gov.sg/report
⚠️ Security warning: - Never commit .env files to git - Add .env* to .gitignore - Rotate secrets regularly - Use strong, random values for secrets
Special Variables¶
NODE_ENV (Node.js)¶
Not set by Airbase - you should define this yourself
Recommended values:
Why it matters: - Controls Node.js optimizations - Many libraries check this variable - production enables performance optimizations
PYTHON Environment Variables¶
Common Python-specific variables:
# Unbuffered output (see logs immediately)
PYTHONUNBUFFERED=TRUE
# Python path
PYTHONPATH=/app/src
# Django settings
DJANGO_SETTINGS_MODULE=myapp.settings
DJANGO_SECRET_KEY=your-secret-key
# Flask settings
FLASK_ENV=production
FLASK_APP=app.py
Variable Access in Code¶
Node.js (JavaScript/TypeScript)¶
// Access variables
const dbUrl = process.env.DATABASE_URL;
const port = parseInt(process.env.PORT || '3000');
const isProduction = process.env.NODE_ENV === 'production';
// With validation
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API_KEY environment variable is required');
}
// With defaults
const logLevel = process.env.LOG_LEVEL || 'info';
const maxConnections = parseInt(process.env.MAX_CONNECTIONS || '10');
Type-safe approach (TypeScript):
interface Config {
databaseUrl: string;
port: number;
apiKey: string;
logLevel: string;
}
function loadConfig(): Config {
const databaseUrl = process.env.DATABASE_URL;
if (!databaseUrl) throw new Error('DATABASE_URL is required');
const apiKey = process.env.API_KEY;
if (!apiKey) throw new Error('API_KEY is required');
return {
databaseUrl,
port: parseInt(process.env.PORT || '3000'),
apiKey,
logLevel: process.env.LOG_LEVEL || 'info'
};
}
const config = loadConfig();
Python¶
import os
# Access variables
db_url = os.environ.get('DATABASE_URL')
port = int(os.environ.get('PORT', 3000))
is_production = os.environ.get('ENVIRONMENT') == 'production'
# With validation
api_key = os.environ.get('API_KEY')
if not api_key:
raise ValueError('API_KEY environment variable is required')
# With defaults
log_level = os.environ.get('LOG_LEVEL', 'info')
max_connections = int(os.environ.get('MAX_CONNECTIONS', '10'))
Using python-decouple:
from decouple import config
# Automatic type conversion and defaults
DATABASE_URL = config('DATABASE_URL')
PORT = config('PORT', default=3000, cast=int)
DEBUG = config('DEBUG', default=False, cast=bool)
Variable Validation¶
Startup Validation¶
Check required variables at startup:
Node.js:
function validateEnv() {
const required = ['DATABASE_URL', 'API_KEY', 'SESSION_SECRET'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
console.error('Missing required environment variables:', missing);
process.exit(1);
}
}
validateEnv();
Python:
def validate_env():
required = ['DATABASE_URL', 'API_KEY', 'SESSION_SECRET']
missing = [key for key in required if not os.environ.get(key)]
if missing:
raise EnvironmentError(f'Missing required variables: {missing}')
validate_env()
Restrictions and Limitations¶
Variable Name Restrictions¶
Cannot override system variables: - PORT - Set by Airbase - ENVIRONMENT - Set by Airbase - APP_NAME - Set by Airbase - PROJECT_HANDLE - Set by Airbase
If you define these in .env, they will be ignored.
Value Size Limits¶
Practical limits: - Single variable: Up to 1MB per value - Total size: Up to 10MB for all variables combined
For large configurations: - Consider using external configuration services - Store large files in mounted volumes - Use configuration URLs instead of inline values
Security Restrictions¶
Do not store in .env: - Production database passwords (use secrets management) - Private keys for production (use secrets management) - OAuth client secrets for production
For production secrets: - Use proper secrets management (contact platform team) - Rotate regularly - Audit access
Troubleshooting¶
Variable Not Available¶
Problem: process.env.MY_VAR is undefined
Solutions: 1. Check .env file exists in project root 2. Verify variable name matches exactly (case-sensitive) 3. Check .env.{environment} file for environment-specific deployments 4. Rebuild and redeploy: airbase container build && airbase container deploy
Variable Has Wrong Value¶
Problem: Variable has unexpected value
Solutions: 1. Check environment-specific file (.env.staging overrides .env) 2. Verify no trailing spaces in .env file 3. Check for quotes: VAR="value" vs VAR=value 4. Redeploy to pick up changes: airbase container deploy
Syntax Errors in .env¶
Problem: Variables not loading due to syntax errors
Common issues:
# ❌ Wrong - spaces around =
DATABASE_URL = postgres://...
# ✅ Correct - no spaces
DATABASE_URL=postgres://...
# ❌ Wrong - unquoted value with spaces
APP_TITLE=My Application
# ✅ Correct - quoted value with spaces
APP_TITLE="My Application"
# ❌ Wrong - multi-line without quotes
CERT=-----BEGIN CERT-----
MIIDXTCCAkWg...
# ✅ Correct - quoted multi-line
CERT="-----BEGIN CERT-----
MIIDXTCCAkWg..."
Best Practices¶
✅ Do's¶
- Use descriptive names:
DATABASE_URLnotDB - Use UPPERCASE: By convention for environment variables
- Group related variables: Prefix with category (e.g.,
DB_,API_) - Provide defaults:
const port = process.env.PORT || 3000 - Validate at startup: Check required variables exist
- Document variables: Add comments in
.env.example - Use
.env.example: Template without secrets
Example .env.example:
# Database connection
DATABASE_URL=postgres://localhost:5432/myapp
# API configuration
API_KEY=your-api-key-here
API_TIMEOUT=30000
# Application settings
LOG_LEVEL=info
❌ Don'ts¶
- Don't commit
.envfiles: Add to.gitignore - Don't hardcode secrets: Use environment variables
- Don't use inline logic: Keep values simple
- Don't store files: Use paths or URLs instead
- Don't duplicate values: Use one variable, reference in code
Examples by Framework¶
Express.js¶
// config.js
module.exports = {
port: parseInt(process.env.PORT || '3000'),
database: {
url: process.env.DATABASE_URL,
pool: {
min: parseInt(process.env.DB_POOL_MIN || '2'),
max: parseInt(process.env.DB_POOL_MAX || '10')
}
},
api: {
key: process.env.API_KEY,
timeout: parseInt(process.env.API_TIMEOUT || '30000')
},
logging: {
level: process.env.LOG_LEVEL || 'info'
}
};
Flask¶
# config.py
import os
class Config:
PORT = int(os.environ.get('PORT', 3000))
DATABASE_URL = os.environ.get('DATABASE_URL')
API_KEY = os.environ.get('API_KEY')
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'info')
@classmethod
def validate(cls):
if not cls.DATABASE_URL:
raise ValueError('DATABASE_URL is required')
if not cls.API_KEY:
raise ValueError('API_KEY is required')
# app.py
from config import Config
Config.validate()
app.run(host='0.0.0.0', port=Config.PORT)
Streamlit¶
# app.py
import os
import streamlit as st
# Configuration
PORT = int(os.environ.get('PORT', 8501))
API_KEY = os.environ.get('API_KEY')
LOG_LEVEL = os.environ.get('LOG_LEVEL', 'info')
# Validate
if not API_KEY:
st.error('API_KEY environment variable is required')
st.stop()
st.title('My Streamlit App')
Dockerfile CMD:
See Also¶
- How-To: Set Environment Variables - Step-by-step guide
- Reference: airbase.json Configuration - Project configuration
- Explanation: Environment Variable Design - Design decisions