| #!/bin/bash |
| echo "π Starting Dify All-in-One..." |
| set -x |
|
|
| cd /app/api |
|
|
| |
| echo "ποΈ Database migration..." |
| echo "π DB_TYPE=${DB_TYPE:-'not set'}" |
| echo "π DB_HOST=${DB_HOST:-'not set'}" |
| echo "π SQLALCHEMY_DATABASE_URI is $([ -n \"$SQLALCHEMY_DATABASE_URI\" ] && echo 'SET' || echo 'NOT SET')" |
| flask db upgrade 2>&1 || echo "β οΈ Migration failed or already done" |
| echo "ποΈ Migration attempt complete" |
|
|
| |
| echo "π¦ Starting Nginx..." |
| nginx |
|
|
| |
| echo "π§ Starting API..." |
|
|
| |
| cat << 'APPWRAPPER_EOF' > /app/api/app_wrapper.py |
| """ |
| Ultimate HF Spaces Fix: Disable CSRF validation entirely and patch cookie settings. |
| CSRF isn't needed on HF Spaces because: |
| 1. It's a single-user deployment |
| 2. The proxy already handles some security |
| 3. We need the app to work! |
| """ |
| import sys |
| import os |
|
|
| |
| os.environ['WTF_CSRF_ENABLED'] = 'false' |
| os.environ['CSRF_ENABLED'] = 'false' |
| os.environ['WTF_CSRF_CHECK_DEFAULT'] = 'false' |
| os.environ['SESSION_COOKIE_SAMESITE'] = 'None' |
| os.environ['SESSION_COOKIE_SECURE'] = 'true' |
| os.environ['CSRF_COOKIE_HTTPONLY'] = 'false' |
|
|
| sys.stderr.write("π§ CSRF DISABLE: Environment variables set\n") |
| sys.stderr.flush() |
|
|
| |
| from app import app as flask_app |
|
|
| |
| flask_app.config.update( |
| WTF_CSRF_ENABLED=False, |
| WTF_CSRF_CHECK_DEFAULT=False, |
| CSRF_ENABLED=False, |
| SESSION_COOKIE_SAMESITE='None', |
| SESSION_COOKIE_SECURE=True, |
| SESSION_COOKIE_HTTPONLY=True, |
| CSRF_COOKIE_HTTPONLY=False, |
| REMEMBER_COOKIE_SAMESITE='None', |
| REMEMBER_COOKIE_SECURE=True, |
| ) |
|
|
| sys.stderr.write("π§ CSRF DISABLE: Flask config patched\n") |
| sys.stderr.flush() |
|
|
| |
| try: |
| from flask_wtf.csrf import CSRFProtect |
| |
| for key in list(flask_app.extensions.keys()): |
| if 'csrf' in key.lower(): |
| sys.stderr.write(f"π§ Found CSRF extension: {key}\n") |
| |
| flask_app.config['WTF_CSRF_ENABLED'] = False |
| sys.stderr.write("π§ CSRF DISABLE: Flask-WTF disabled\n") |
| except Exception as e: |
| sys.stderr.write(f"β οΈ Flask-WTF not found or error: {e}\n") |
| sys.stderr.flush() |
|
|
| |
| try: |
| if hasattr(flask_app, 'login_manager'): |
| flask_app.login_manager.session_protection = None |
| sys.stderr.write("π§ Flask-Login: session_protection disabled\n") |
| except Exception as e: |
| sys.stderr.write(f"β οΈ Flask-Login patch error: {e}\n") |
| sys.stderr.flush() |
|
|
| |
| class CookieFixMiddleware: |
| def __init__(self, app): |
| self.app = app |
| |
| def __call__(self, environ, start_response): |
| def custom_start_response(status, headers, exc_info=None): |
| new_headers = [] |
| for name, value in headers: |
| if name.lower() == 'set-cookie': |
| import re |
| |
| value = value.replace('; HttpOnly', '').replace(';HttpOnly', '') |
| |
| value = re.sub(r'SameSite=\w+', 'SameSite=None', value) |
| if 'SameSite=' not in value: |
| value += '; SameSite=None' |
| |
| if '; Secure' not in value: |
| value += '; Secure' |
| |
| if '__Host-' in value and 'Path=' not in value: |
| value += '; Path=/' |
| |
| value = re.sub(r'; Domain=[^;]+', '', value) |
| sys.stderr.write(f"πͺ Cookie: {value[:80]}...\n") |
| sys.stderr.flush() |
| new_headers.append((name, value)) |
| return start_response(status, new_headers, exc_info) |
| return self.app(environ, custom_start_response) |
|
|
| |
| app = CookieFixMiddleware(flask_app) |
|
|
| sys.stderr.write("β
APP WRAPPER READY: CSRF disabled + Cookie patching active!\n") |
| sys.stderr.flush() |
| APPWRAPPER_EOF |
|
|
| echo "π§ App wrapper with CSRF disable created!" |
|
|
| |
| gunicorn --bind 127.0.0.1:5001 --workers 1 --timeout 360 --forwarded-allow-ips='*' app_wrapper:app & |
| API_PID=$! |
| API_PID=$! |
|
|
| |
| echo "π Starting Web..." |
| cd /app/web |
|
|
| |
| export NODE_ENV=production |
| export PORT=3000 |
| export HOSTNAME=0.0.0.0 |
|
|
| |
| export NEXT_PUBLIC_API_PREFIX=/console/api |
| export NEXT_PUBLIC_PUBLIC_API_PREFIX=/api |
| export NEXT_PUBLIC_SENTRY_DSN= |
| export NEXT_TELEMETRY_DISABLED=1 |
|
|
| |
| export NEXT_PUBLIC_EDITION=${NEXT_PUBLIC_EDITION:-"SELF_HOSTED"} |
| export NEXT_PUBLIC_DEPLOY_ENV=${NEXT_PUBLIC_DEPLOY_ENV:-"PRODUCTION"} |
| export EDITION=${NEXT_PUBLIC_EDITION} |
| export DEPLOY_ENV=${NEXT_PUBLIC_DEPLOY_ENV} |
|
|
| |
| export SECRET_KEY=${SECRET_KEY:-"dify-secret-key-random-123456"} |
| export SESSION_COOKIE_SAMESITE="None" |
| export SESSION_COOKIE_SECURE="true" |
| export COOKIE_HTTPONLY="false" |
| export SESSION_COOKIE_HTTPONLY="true" |
| export CSRF_COOKIE_HTTPONLY="false" |
| export REMEMBER_COOKIE_SAMESITE="None" |
| export REMEMBER_COOKIE_SECURE="true" |
| export REMEMBER_COOKIE_HTTPONLY="true" |
| export REFRESH_TOKEN_COOKIE_SAMESITE="None" |
| export REFRESH_TOKEN_COOKIE_SECURE="true" |
| export REFRESH_TOKEN_COOKIE_HTTPONLY="true" |
|
|
| |
| export FLASK_RUN_EXTRA_FILES="" |
|
|
| |
| export CONSOLE_API_URL=${CONSOLE_API_URL:-"https://pommsn-dify.hf.space"} |
| export CONSOLE_WEB_URL=${CONSOLE_WEB_URL:-"https://pommsn-dify.hf.space"} |
| export APP_API_URL=${APP_API_URL:-"https://pommsn-dify.hf.space"} |
| export APP_WEB_URL=${APP_WEB_URL:-"https://pommsn-dify.hf.space"} |
| export SERVICE_API_URL=${SERVICE_API_URL:-"https://pommsn-dify.hf.space"} |
|
|
| |
| export NEXT_PUBLIC_API_URL=${CONSOLE_API_URL} |
|
|
| |
| export NEXT_SHARP_PATH=/app/web/node_modules/sharp |
| export __NEXT_PRIVATE_STANDALONE_CONFIG=true |
|
|
| |
| export NEXT_PUBLIC_API_URL=${CONSOLE_API_URL} |
|
|
| echo "π CONSOLE_API_URL=${CONSOLE_API_URL}" |
| echo "π NODE_ENV=${NODE_ENV}" |
|
|
| node server.js & |
| WEB_PID=$! |
|
|
| echo "β
All services started!" |
| wait |