🚀 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
- Never commit
.env
files - Add them to.gitignore
- Use different
.env
files for different environments (.env.development
,.env.production
) - Validate configuration at startup to catch errors early
- Use strong secret keys in production
- Document all environment variables in your README
- Provide sensible defaults for all configuration options
- Use type conversion for numeric and boolean values
- 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