Skip to content

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:

// Node.js
const PORT = process.env.PORT || 3000;
app.listen(PORT, '0.0.0.0');

# Python
import os
PORT = int(os.environ.get('PORT', 3000))
app.run(host='0.0.0.0', port=PORT)

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:

const appName = process.env.APP_NAME;
console.log(`Starting ${appName}...`);

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:

const projectHandle = process.env.PROJECT_HANDLE;
console.log(`Deployed as ${projectHandle}`);

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:

PORT=3000
LOG_LEVEL=debug
ENABLE_CACHE=true

Values with spaces (use quotes):

APP_TITLE="My Application"
ERROR_MESSAGE="An error occurred"

Multi-line values (use quotes):

CERTIFICATE="-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKL0UG...
-----END CERTIFICATE-----"

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):

  1. Environment-specific .env file (e.g., .env.staging)
  2. Default .env file (if no environment-specific file exists)
  3. 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:

# .env (production)
NODE_ENV=production

# .env.staging
NODE_ENV=development

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_URL not DB
  • 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 .env files: 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:

CMD ["sh", "-c", "streamlit run app.py --server.port=${PORT:-8501} --server.address=0.0.0.0"]


See Also