The application runs as a non-root user (appuser) for security:
RUN useradd --create-home --shell /bin/bash appuser
USER appuserBenefits:
- If container is compromised, attacker has limited privileges
- Prevents privilege escalation attacks
- Follows security best practices
docker-compose.ymlcontains hardcoded development passwords (acceptable for local development only)postgres_passwordandpgadmin_passwordare placeholder credentials
- Production runs on Vercel + Neon; secrets are configured as Vercel project environment variables and GitHub Actions secrets
.env.productionremains in.gitignoreto prevent committing secrets locally- Strong secrets must be generated with:
openssl rand -base64 32
Best Practices:
- Never commit
.env.productionto version control - Use different passwords for development and production
- Rotate secrets regularly
- Use strong, randomly generated secrets (32+ bytes)
- Uses official
python:3.14-slimimage - Slim variants reduce attack surface by excluding unnecessary packages
- Minimal system packages installed (
libpq5,curl) aptcache cleaned after installation- Multi-stage build reduces final image size
Internet → Vercel edge (TLS termination) → FastAPI API function → Neon PostgreSQL
Security Features:
- TLS termination handled by the Vercel platform
- Security headers applied by application middleware (
app/middleware/security_headers.py) - Rate limiting enforced at the application layer (
app/middleware/rate_limit.py) - Database reachable only through the configured Neon connection URL
TLS certificates are provisioned and renewed automatically by the Vercel platform;
no certificate files are stored in this repository. Application responses also declare
HSTS via SecurityHeadersMiddleware
(max-age=63072000; includeSubDomains; preload in production environments).
The FastAPI application sets security headers through SecurityHeadersMiddleware
(app/middleware/security_headers.py):
Content-Security-Policy: default-src 'self'; ...
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()Purpose:
- CSP: Restricts resource loading origins
- HSTS: Forces HTTPS connections
- X-Frame-Options: Prevents clickjacking
- X-Content-Type-Options: Prevents MIME sniffing
- X-XSS-Protection: XSS protection
- Referrer-Policy: Controls referrer information
- Permissions-Policy: Disables sensitive browser capabilities
API endpoints are rate-limited in the application using slowapi
(app/middleware/rate_limit.py, registered in app/main.py):
Configuration:
- Limits are applied per endpoint via the shared limiter
- Requests are keyed by client IP address
- Rate limiting responses return HTTP 429
All services have health checks:
App Container:
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1Database Container:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U comicpile"]
interval: 10s
timeout: 5s
retries: 5✅ Implemented:
- Non-root user
- Minimal base image (slim)
- Multi-stage build
- Health checks on containers
- Secrets in environment variables (not code)
- .env.production in .gitignore
- TLS terminated by the Vercel platform
- Security headers in application middleware
- Rate limiting on API (slowapi)
- No direct database exposure
- Read-only file system where possible
Run vulnerability scans before deployment:
# Scan Docker image
docker scout cves comic-pile:latest
# Scan base image
docker scout cves python:3.14-slim
# Check for exposed secrets
git-secrets --scan
# Check for dependencies with known vulnerabilities
# (Requires setup of tools like Snyk or Dependabot)Before deploying to production:
- Generate strong secrets with
openssl rand -base64 32 - Update Vercel project environment variables with production values
- Run vulnerability scan on Docker image
- Test health checks locally
- Verify no secrets in git history
- Review .gitignore includes all sensitive files
- Backup database before migration
- Test rollback procedure
If secrets are leaked:
- Immediately rotate all secrets
- Rotate the affected Vercel project environment variables and GitHub Actions secrets
- Check audit logs for unauthorized access
- Redeploy so services pick up the new secrets
If container is compromised:
- Stop affected containers immediately
- Review container logs for indicators of compromise
- Rotate all secrets
- Update to latest base images with security patches
- Rebuild and redeploy containers
- Monitor container logs for suspicious activity
- Set up alerts for health check failures
- Track rate limit violations
- Regular security audits (quarterly)