File size: 6,740 Bytes
8dd2df5
7bfcdc2
aa9d504
563f9b6
2a61894
7bb08cb
e69fcaa
7bfcdc2
91e3d95
 
 
 
 
7bfcdc2
e69fcaa
 
 
 
 
7bfcdc2
16781b9
e76908e
 
 
 
 
 
 
 
 
802decb
e76908e
 
 
 
 
 
 
 
 
 
 
 
 
 
8faf0f7
 
e76908e
 
 
 
 
 
 
 
 
 
 
 
 
 
802decb
 
e76908e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8faf0f7
 
 
 
 
 
 
802decb
e76908e
 
8faf0f7
e76908e
 
802decb
8faf0f7
e76908e
 
8faf0f7
e76908e
 
 
 
 
 
802decb
8faf0f7
 
 
 
e76908e
 
 
 
802decb
e76908e
8faf0f7
e76908e
8faf0f7
e76908e
 
 
e69fcaa
7bfcdc2
e69fcaa
7bfcdc2
 
e69fcaa
56e9088
 
 
 
 
 
e69fcaa
 
 
 
 
b03d607
 
 
 
 
 
16781b9
 
 
 
 
 
 
 
 
 
 
 
 
553a626
 
 
 
56e9088
 
 
 
 
 
1ac3a12
b03d607
 
1ac3a12
e985de5
d4fee68
e985de5
 
 
 
d4fee68
56e9088
d4fee68
1ac3a12
7bfcdc2
e69fcaa
5b80172
aa9d504
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/bin/bash
echo "πŸš€ Starting Dify All-in-One..."
set -x

cd /app/api

# 1. Database Migration (with timeout)
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"

# 2. Start Nginx FIRST (port 7860)
echo "🚦 Starting Nginx..."
nginx

# 3. Start API (port 5001)
echo "🧠 Starting API..."

# ULTIMATE FIX: Disable CSRF and patch cookies at app level
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

# Set environment variables BEFORE importing Flask app
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()

# Now import the Flask app
from app import app as flask_app

# Patch Flask config directly
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 to disable Flask-WTF CSRF if it exists
try:
    from flask_wtf.csrf import CSRFProtect
    # Find and disable any CSRF protection instance
    for key in list(flask_app.extensions.keys()):
        if 'csrf' in key.lower():
            sys.stderr.write(f"πŸ”§ Found CSRF extension: {key}\n")
    # Disable CSRF for all views
    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 to find and patch Flask-Login cookie settings
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()

# Cookie patching middleware for responses
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
                    # Remove HttpOnly (so JS can read CSRF token)
                    value = value.replace('; HttpOnly', '').replace(';HttpOnly', '')
                    # Force SameSite=None
                    value = re.sub(r'SameSite=\w+', 'SameSite=None', value)
                    if 'SameSite=' not in value:
                        value += '; SameSite=None'
                    # Add Secure flag (required for SameSite=None)
                    if '; Secure' not in value:
                        value += '; Secure'
                    # CRITICAL: __Host- prefix requires Path=/
                    if '__Host-' in value and 'Path=' not in value:
                        value += '; Path=/'
                    # Remove any Domain attribute (__Host- prefix requirement)
                    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)

# Wrap the app
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!"

# Run Gunicorn with the patched app
gunicorn --bind 127.0.0.1:5001 --workers 1 --timeout 360 --forwarded-allow-ips='*' app_wrapper:app &
API_PID=$!
API_PID=$!

# 4. Start Web (port 3000) with correct API URLs
echo "🌐 Starting Web..."
cd /app/web

# Critical: Set environment
export NODE_ENV=production
export PORT=3000
export HOSTNAME=0.0.0.0

# API URLs
export NEXT_PUBLIC_API_PREFIX=/console/api
export NEXT_PUBLIC_PUBLIC_API_PREFIX=/api
export NEXT_PUBLIC_SENTRY_DSN=
export NEXT_TELEMETRY_DISABLED=1

# Edition and deploy env
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}

# Security / Cookies (Critical for HF Spaces)
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"

# Fix for invalid or missing user-agent in some environments
export FLASK_RUN_EXTRA_FILES=""

# Console URLs - must be set!
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"}

# Server-side access to URLs (just in case)
export NEXT_PUBLIC_API_URL=${CONSOLE_API_URL}

# Fix for standalone mode (Required for 1.10.x and 1.11.x)
export NEXT_SHARP_PATH=/app/web/node_modules/sharp
export __NEXT_PRIVATE_STANDALONE_CONFIG=true

# Ensure internal API URL is set for SSR
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