Skip to content

🚀 Day 6: Environment Configuration

Using .env Files

Nexios supports environment configuration through .env files. First, install the python-dotenv package:

bash
pip install python-dotenv

Basic Configuration Setup

python
from nexios import NexiosApp
from nexios.config import MakeConfig
import os
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Create configuration with environment variables
config = MakeConfig({
    "debug": os.getenv("DEBUG", "False").lower() == "true",
    "secret_key": os.getenv("SECRET_KEY", "default-secret-key"),
    "database_url": os.getenv("DATABASE_URL", "sqlite:///app.db"),
    "port": int(os.getenv("PORT", "8000")),
    "host": os.getenv("HOST", "127.0.0.1"),
    "cors": {
        "allow_origins": os.getenv("CORS_ORIGINS", "*").split(",")
    }
})

app = NexiosApp(config=config)

Example .env File

Create a .env file in your project root:

env
# Application Settings
APP_NAME=My Nexios App
DEBUG=true
SECRET_KEY=your-super-secret-key-change-in-production
DATABASE_URL=postgresql://user:pass@localhost/db
REDIS_URL=redis://localhost:6379

# Server Configuration
HOST=127.0.0.1
PORT=8000
WORKERS=4

# CORS Settings
CORS_ORIGINS=http://localhost:3000,https://app.example.com

# Database Settings
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DB_USER=postgres
DB_PASSWORD=password

# Security
ALLOWED_HOSTS=localhost,example.com
SESSION_SECRET=session-secret-key

Environment-Specific Configuration

You can create different configurations for different environments:

python
import os
from nexios import NexiosApp
from nexios.config import MakeConfig
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

def get_development_config():
    """Development environment configuration"""
    return {
        "debug": True,
        "port": 8000,
        "host": "127.0.0.1",
        "secret_key": "dev-secret-key",
        "database_url": "sqlite:///dev.db",
        "cors": {
            "allow_origins": ["*"]
        }
    }

def get_production_config():
    """Production environment configuration"""
    return {
        "debug": False,
        "port": int(os.getenv("PORT", "8000")),
        "host": "0.0.0.0",
        "secret_key": os.getenv("SECRET_KEY"),
        "database_url": os.getenv("DATABASE_URL"),
        "cors": {
            "allow_origins": os.getenv("CORS_ORIGINS", "").split(",")
        }
    }

# Choose configuration based on environment
env = os.getenv("ENVIRONMENT", "development")
if env == "production":
    config = MakeConfig(get_production_config())
else:
    config = MakeConfig(get_development_config())

app = NexiosApp(config=config)

CORS Configuration

Configure Cross-Origin Resource Sharing (CORS):

python
from nexios import NexiosApp
from nexios.middleware import CORSMiddleware
from nexios.config import MakeConfig
import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Create configuration with CORS settings
config = MakeConfig({
    "debug": os.getenv("DEBUG", "False").lower() == "true",
    "cors": {
        "allow_origins": os.getenv("CORS_ORIGINS", "*").split(","),
        "allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["*"],
        "allow_credentials": True
    }
})

app = NexiosApp(config=config)

# Add CORS middleware
app.add_middleware(CORSMiddleware())

Advanced Configuration Patterns

Configuration with Validation

python
import os
from nexios import NexiosApp
from nexios.config import MakeConfig
from dotenv import load_dotenv

load_dotenv()

def validate_config(config_dict):
    """Validate configuration values"""
    required_keys = ["SECRET_KEY", "DATABASE_URL"]
    missing_keys = [key for key in required_keys if not config_dict.get(key)]
    
    if missing_keys:
        raise ValueError(f"Missing required configuration: {missing_keys}")
    
    return config_dict

# Create configuration with validation
config_dict = {
    "debug": os.getenv("DEBUG", "False").lower() == "true",
    "secret_key": os.getenv("SECRET_KEY"),
    "database_url": os.getenv("DATABASE_URL"),
    "port": int(os.getenv("PORT", "8000")),
    "host": os.getenv("HOST", "127.0.0.1")
}

# Validate configuration
validated_config = validate_config(config_dict)
config = MakeConfig(validated_config)

app = NexiosApp(config=config)

Configuration with Nested Settings

python
import os
from nexios import NexiosApp
from nexios.config import MakeConfig
from dotenv import load_dotenv

load_dotenv()

config = MakeConfig({
    "debug": os.getenv("DEBUG", "False").lower() == "true",
    "server": {
        "host": os.getenv("HOST", "127.0.0.1"),
        "port": int(os.getenv("PORT", "8000")),
        "workers": int(os.getenv("WORKERS", "4"))
    },
    "database": {
        "url": os.getenv("DATABASE_URL"),
        "pool_size": int(os.getenv("DB_POOL_SIZE", "20")),
        "max_overflow": int(os.getenv("DB_MAX_OVERFLOW", "30"))
    },
    "security": {
        "secret_key": os.getenv("SECRET_KEY"),
        "session_timeout": int(os.getenv("SESSION_TIMEOUT", "3600")),
        "csrf_enabled": os.getenv("CSRF_ENABLED", "True").lower() == "true"
    },
    "cors": {
        "allow_origins": os.getenv("CORS_ORIGINS", "*").split(","),
        "allow_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
        "allow_headers": ["*"]
    }
})

app = NexiosApp(config=config)

# Access nested configuration
print(f"Server host: {app.config.server.host}")
print(f"Database pool size: {app.config.database.pool_size}")
print(f"CSRF enabled: {app.config.security.csrf_enabled}")

Best Practices

  1. Never commit .env files - Add them to .gitignore
  2. Use different .env files for different environments (.env.development, .env.production)
  3. Validate configuration at startup to catch errors early
  4. Use strong secret keys in production
  5. Document all environment variables in your README
  6. Provide sensible defaults for all configuration options
  7. Use type conversion for numeric and boolean values
  8. Test configuration loading in your test suite

Example Project Structure

myapp/
├── .env                    # Environment variables
├── .env.example           # Example environment file
├── .gitignore             # Git ignore file
├── main.py                # Main application
├── config.py              # Configuration module
├── requirements.txt        # Dependencies
└── README.md              # Documentation

.gitignore Entry

Make sure to add .env files to your .gitignore:

gitignore
# Environment files
.env
.env.local
.env.development
.env.production
.env.test