Files
digiserver-v2/app/config.py
root 21eb63659a feat: complete nginx migration from caddy
- Replace Caddy reverse proxy with Nginx (nginx:alpine)
- Add nginx.conf with HTTP/HTTPS, gzip, and proxy settings
- Add nginx-custom-domains.conf template for custom domains
- Update docker-compose.yml to use Nginx service
- Add ProxyFix middleware to Flask app for proper header handling
- Create nginx_config_reader.py utility to read Nginx configuration
- Update admin blueprint to display Nginx status in https_config page
- Add Nginx configuration display to https_config.html template
- Generate self-signed SSL certificates for localhost
- Add utility scripts: generate_nginx_certs.sh
- Add documentation: NGINX_SETUP_QUICK.md, PROXY_FIX_SETUP.md
- All containers now running, HTTPS working, HTTP redirects to HTTPS
- Session cookies marked as Secure
- Security headers properly configured
2026-01-15 22:15:11 +02:00

127 lines
3.5 KiB
Python
Executable File

"""
Configuration settings for DigiServer v2
Environment-based configuration with sensible defaults
"""
import os
from datetime import timedelta
class Config:
"""Base configuration"""
# Basic Flask config
SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')
# Database
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = False
# File Upload - use absolute paths
MAX_CONTENT_LENGTH = 2048 * 1024 * 1024 # 2GB
_basedir = os.path.abspath(os.path.dirname(__file__))
UPLOAD_FOLDER = os.path.join(_basedir, 'static', 'uploads')
UPLOAD_FOLDERLOGO = os.path.join(_basedir, 'static', 'resurse')
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'mp4', 'avi', 'mkv', 'mov', 'webm', 'pdf', 'ppt', 'pptx'}
# Session
PERMANENT_SESSION_LIFETIME = timedelta(minutes=30)
SESSION_COOKIE_SECURE = False # Set to True in production with HTTPS
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
# Reverse proxy trust (for Nginx/Caddy with ProxyFix middleware)
# These are set by werkzeug.middleware.proxy_fix
TRUSTED_PROXIES = os.getenv('TRUSTED_PROXIES', '127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16')
PREFERRED_URL_SCHEME = os.getenv('PREFERRED_URL_SCHEME', 'https')
# Cache
SEND_FILE_MAX_AGE_DEFAULT = 300 # 5 minutes for static files
# Server Info
SERVER_VERSION = "2.0.0"
BUILD_DATE = "2025-11-12"
# Pagination
ITEMS_PER_PAGE = 20
# Admin defaults
DEFAULT_ADMIN_USER = os.getenv('ADMIN_USER', 'admin')
DEFAULT_ADMIN_PASSWORD = os.getenv('ADMIN_PASSWORD', 'Initial01!')
class DevelopmentConfig(Config):
"""Development configuration"""
DEBUG = True
TESTING = False
# Database - construct absolute path
_basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
SQLALCHEMY_DATABASE_URI = os.getenv(
'DATABASE_URL',
f'sqlite:///{os.path.join(_basedir, "instance", "dev.db")}'
)
# Cache (simple in-memory for development)
CACHE_TYPE = 'simple'
CACHE_DEFAULT_TIMEOUT = 60
# Security (relaxed for development)
WTF_CSRF_ENABLED = True
WTF_CSRF_TIME_LIMIT = None
class ProductionConfig(Config):
"""Production configuration"""
DEBUG = False
TESTING = False
TEMPLATES_AUTO_RELOAD = True # Force template reload
# Database - construct absolute path
_basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
SQLALCHEMY_DATABASE_URI = os.getenv(
'DATABASE_URL',
f'sqlite:///{os.path.join(_basedir, "instance", "dashboard.db")}'
)
# Cache - use simple cache instead of Redis
CACHE_TYPE = 'simple'
CACHE_DEFAULT_TIMEOUT = 300
# Security
SESSION_COOKIE_SECURE = True
WTF_CSRF_ENABLED = True
class TestingConfig(Config):
"""Testing configuration"""
DEBUG = True
TESTING = True
# Database (in-memory for tests)
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
# Cache (simple for tests)
CACHE_TYPE = 'simple'
# Security (disabled for tests)
WTF_CSRF_ENABLED = False
# Configuration dictionary
config = {
'development': DevelopmentConfig,
'production': ProductionConfig,
'testing': TestingConfig,
'default': DevelopmentConfig
}
def get_config(env=None):
"""Get configuration based on environment"""
if env is None:
env = os.getenv('FLASK_ENV', 'development')
return config.get(env, config['default'])