Production Hardening
Security hardening for production deployments — secret rotation, CORS, cookies, API schema protection.
Production Hardening
FastCMS includes several security hardening features that activate automatically in production (ENVIRONMENT=production).
Secret Key Rotation
Rotating SECRET_KEY invalidates all existing JWT tokens, logging out every user. To avoid this, FastCMS supports a previous key for a smooth transition.
Rotation Steps
- Copy your current
SECRET_KEYtoSECRET_KEY_PREVIOUS - Generate a new
SECRET_KEY:openssl rand -hex 32 - Deploy with both keys set
- Wait for old tokens to expire (max 30 days for refresh tokens)
- Remove
SECRET_KEY_PREVIOUS
Configuration
SECRET_KEY=your-new-secret-key-here
SECRET_KEY_PREVIOUS=your-old-secret-key-hereDuring the rotation period:
- New tokens are always signed with
SECRET_KEY - Old tokens validate against
SECRET_KEY_PREVIOUSas a fallback - This applies to access tokens, refresh tokens, file access tokens, and impersonation tokens
API Schema Protection
In production, the OpenAPI schema and documentation UIs are completely disabled:
| Route | Development | Production |
|---|---|---|
/docs (Swagger UI) | Available | Disabled (404) |
/redoc (ReDoc) | Available | Disabled (404) |
/openapi.json (Schema) | Available | Disabled (404) |
This is controlled by the DEBUG flag:
# Development
DEBUG=true
# Production
DEBUG=falseCORS Configuration
CORS is restricted to specific methods and headers:
Allowed methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Allowed headers: Authorization, Content-Type, X-API-Key, X-Requested-With, Accept
Configure allowed origins in .env:
# Single origin
CORS_ORIGINS=https://your-app.com
# Multiple origins (comma-separated)
CORS_ORIGINS=https://your-app.com,https://admin.your-app.comCookie Security
All cookies enforce security attributes based on environment:
| Cookie | HttpOnly | Secure | SameSite |
|---|---|---|---|
fastcms_session | Yes | Production only | Lax |
oauth_collection | Yes | Production only | Lax |
- HttpOnly prevents JavaScript access (XSS protection)
- Secure ensures cookies are only sent over HTTPS
- SameSite=Lax prevents CSRF while allowing top-level navigation
Security Headers
All responses include security headers automatically. See Security Headers for details.
Recommended Production Settings
ENVIRONMENT=production
DEBUG=false
SECRET_KEY=<generated-with-openssl-rand-hex-32>
# Restrict CORS to your frontend domain
CORS_ORIGINS=https://your-app.com
# Enable rate limiting
RATE_LIMIT_ENABLED=true
RATE_LIMIT_PER_MINUTE=100
RATE_LIMIT_PER_HOUR=1000
# Enable account lockout
ACCOUNT_LOCKOUT_ENABLED=true
ACCOUNT_LOCKOUT_ATTEMPTS=5
ACCOUNT_LOCKOUT_DURATION=1800
# Strong password policy
PASSWORD_MIN_LENGTH=10
PASSWORD_REQUIRE_UPPERCASE=true
PASSWORD_REQUIRE_LOWERCASE=true
PASSWORD_REQUIRE_DIGIT=true
PASSWORD_REQUIRE_SPECIAL=trueChecklist
Before deploying to production:
- Set
ENVIRONMENT=productionandDEBUG=false - Generate a strong
SECRET_KEYwithopenssl rand -hex 32 - Restrict
CORS_ORIGINSto your frontend domain(s) - Configure SMTP for security notification emails
- Use PostgreSQL instead of SQLite
- Put FastCMS behind a reverse proxy (nginx, Caddy) for TLS termination
- Enable rate limiting and account lockout
- Review IP filtering rules if needed