diff --git a/Dockerfile b/Dockerfile index b1fd91d..c91a0ee 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,8 +15,9 @@ COPY reset_password.py . COPY templates/ templates/ COPY static/ static/ -# Create data directory -RUN mkdir -p /app/data +# Create data and session directories +RUN mkdir -p /app/data /app/data/flask_sessions && \ + chmod 777 /app/data/flask_sessions # Copy entrypoint script and make scripts executable COPY docker-entrypoint.sh . diff --git a/app.py b/app.py index 4e14e5f..fade4dc 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,5 @@ from flask import Flask, render_template, request, jsonify, redirect, url_for, session +from flask_session import Session from functools import wraps from werkzeug.middleware.proxy_fix import ProxyFix from datetime import timedelta @@ -8,7 +9,7 @@ import argparse import sys app = Flask(__name__) -app.secret_key = os.urandom(24) # Secret key for session management +app.secret_key = os.getenv('SECRET_KEY', os.urandom(24).hex()) # Secret key for session management # Configure for reverse proxy (Authelia, Zoraxy, Nginx, etc.) # This fixes HTTPS detection and redirects when behind a proxy @@ -24,24 +25,30 @@ app.wsgi_app = ProxyFix( malias_w.init_database() # Session configuration for reverse proxy -# Critical: Session cookies must work through proxy (Authelia, Zoraxy, etc.) +# Use server-side sessions stored in filesystem (works with multiple Gunicorn workers) app.config.update( - # Session cookie settings - SESSION_COOKIE_NAME='malias_session', # Custom name to avoid conflicts - SESSION_COOKIE_SECURE=False, # Must be False - backend connection is HTTP - SESSION_COOKIE_HTTPONLY=True, # Security: prevent JavaScript access - SESSION_COOKIE_SAMESITE='Lax', # Allow same-site requests (needed for redirects) - SESSION_COOKIE_PATH='/', # Available for entire application + # Server-side session storage + SESSION_TYPE='filesystem', # Store sessions on disk (shared across workers) + SESSION_FILE_DIR='/app/data/flask_sessions', # Session storage directory + SESSION_PERMANENT=True, # Sessions persist + PERMANENT_SESSION_LIFETIME=timedelta(hours=24), # 24 hour sessions - # Permanent session (survives browser restarts) - PERMANENT_SESSION_LIFETIME=86400, # 24 hours in seconds - SESSION_REFRESH_EACH_REQUEST=True, # Extend session on each request + # Session cookie settings + SESSION_COOKIE_NAME='malias_session', # Custom name to avoid conflicts + SESSION_COOKIE_SECURE=False, # Must be False - backend connection is HTTP + SESSION_COOKIE_HTTPONLY=True, # Security: prevent JavaScript access + SESSION_COOKIE_SAMESITE='Lax', # Allow same-site requests (needed for redirects) + SESSION_COOKIE_PATH='/', # Available for entire application + SESSION_COOKIE_DOMAIN=None, # Let browser decide # URL generation - PREFERRED_URL_SCHEME='https', # Generate HTTPS URLs when behind proxy - APPLICATION_ROOT='/', # Application root path + PREFERRED_URL_SCHEME='https', # Generate HTTPS URLs when behind proxy + APPLICATION_ROOT='/', # Application root path ) +# Initialize Flask-Session +Session(app) + def login_required(f): """Decorator to require login for routes""" @wraps(f) diff --git a/requirements.txt b/requirements.txt index d1ce881..7352b26 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,5 @@ httpx==0.27.0 rich==13.7.0 bcrypt==4.1.2 gunicorn==21.2.0 +Flask-Session==0.6.0 +cachelib==0.10.2