martynka commited on
Commit
ecfbb6a
·
verified ·
1 Parent(s): 37c0dcf

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +37 -63
Dockerfile CHANGED
@@ -158,7 +158,7 @@ EOF
158
 
159
  # ===== Fixed Combined Server =====
160
  COPY <<"EOF" /app/combined_server.py
161
- from flask import Flask, request, jsonify, render_template, make_response
162
  from werkzeug.middleware.proxy_fix import ProxyFix
163
  from werkzeug.security import generate_password_hash
164
  import os
@@ -171,8 +171,9 @@ import threading
171
  import time
172
 
173
  app = Flask(__name__,
174
- template_folder='/app/admin/templates',
175
- static_folder='/app/admin/static')
 
176
  app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
177
  app.secret_key = os.getenv("FLASK_SECRET")
178
 
@@ -187,106 +188,79 @@ def get_db():
187
  return db
188
 
189
  # ===== Admin Routes =====
 
190
  @app.route('/sudo')
191
  def admin_home():
192
  return render_template('login.html')
193
 
 
194
  @app.route('/sudo/login', methods=['POST'])
195
  def login():
196
  if request.json.get('sudo_secret') == os.getenv("SUDO_SECRET"):
197
- return jsonify({"status": "success", "token": os.getenv("SUDO_SECRET")})
 
 
 
 
198
  return jsonify({"error": "Invalid secret"}), 403
199
 
 
200
  @app.route('/sudo/dashboard')
201
  def dashboard():
202
  return render_template('dashboard.html')
203
 
204
- @app.route('/sudo/add_user', methods=['POST'])
205
- def add_user():
206
- if request.headers.get('X-Sudo-Secret') != os.getenv("SUDO_SECRET"):
207
- return jsonify({"error": "Unauthorized"}), 403
208
-
209
- db = get_db()
210
- try:
211
- db.execute("INSERT INTO users VALUES (?,?,?)", [
212
- request.json["username"],
213
- generate_password_hash(request.json["password"]),
214
- "user"
215
- ])
216
- db.commit()
217
- return jsonify({"status": "User added"})
218
- except sqlite3.IntegrityError:
219
- return jsonify({"error": "User exists"}), 400
220
-
221
- @app.route('/sudo/list_users', methods=['GET'])
222
- def list_users():
223
- if request.headers.get('X-Sudo-Secret') != os.getenv("SUDO_SECRET"):
224
- return jsonify({"error": "Unauthorized"}), 403
225
-
226
- db = get_db()
227
- return jsonify([
228
- {"username": row[0]} for row in db.execute("SELECT username FROM users")
229
- ])
230
 
231
- @app.route('/sudo/remove_user', methods=['POST'])
232
- def remove_user():
233
- if request.headers.get('X-Sudo-Secret') != os.getenv("SUDO_SECRET"):
234
- return jsonify({"error": "Unauthorized"}), 403
235
-
236
- db = get_db()
237
- db.execute("DELETE FROM users WHERE username=?", [request.json["username"]])
238
- db.commit()
239
- return jsonify({"status": "User removed"})
240
 
241
  # ===== LibreChat Proxy =====
242
  def is_librechat_ready():
243
  try:
244
- return requests.get('http://localhost:3080', timeout=1).status_code < 500
245
  except:
246
  return False
247
 
248
  @app.route('/', defaults={'path': ''})
249
- @app.route('/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'])
250
  def proxy(path):
251
  # Don't proxy admin routes
252
- if path.startswith('sudo/') or path == 'sudo':
253
- return make_response("Not Found", 404)
254
 
255
- # Wait for LibreChat to be ready
256
- for _ in range(30): # 30 second timeout
257
- if is_librechat_ready():
258
- break
259
- time.sleep(1)
260
- else:
261
- return make_response("LibreChat backend not ready", 503)
262
 
263
- # Forward request to LibreChat
264
  resp = requests.request(
265
  method=request.method,
266
  url=f"http://localhost:3080/{path}",
267
- headers={key: value for (key, value) in request.headers if key.lower() != 'host'},
268
  data=request.get_data(),
269
  cookies=request.cookies,
270
- allow_redirects=False,
271
- timeout=30
272
  )
273
 
274
- # Create response
275
- response = make_response(resp.content, resp.status_code)
276
- for key, value in resp.headers.items():
277
- if key.lower() not in ['content-encoding', 'content-length', 'transfer-encoding']:
278
- response.headers[key] = value
279
  return response
280
 
281
  def start_librechat():
282
- subprocess.run(["npm", "run", "backend"], cwd="/app")
283
 
284
  if __name__ == "__main__":
285
- # Start LibreChat in background
286
  threading.Thread(target=start_librechat, daemon=True).start()
287
 
288
- # Start combined server
289
- serve(app, host='0.0.0.0', port=7860, threads=4, ident="LibreChat Proxy")
 
290
  EOF
291
 
292
  # Startup script
 
158
 
159
  # ===== Fixed Combined Server =====
160
  COPY <<"EOF" /app/combined_server.py
161
+ from flask import Flask, request, jsonify, render_template, send_from_directory
162
  from werkzeug.middleware.proxy_fix import ProxyFix
163
  from werkzeug.security import generate_password_hash
164
  import os
 
171
  import time
172
 
173
  app = Flask(__name__,
174
+ static_url_path='/admin/static',
175
+ static_folder='/app/admin/static',
176
+ template_folder='/app/admin/templates')
177
  app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
178
  app.secret_key = os.getenv("FLASK_SECRET")
179
 
 
188
  return db
189
 
190
  # ===== Admin Routes =====
191
+ @app.route('/admin')
192
  @app.route('/sudo')
193
  def admin_home():
194
  return render_template('login.html')
195
 
196
+ @app.route('/admin/login', methods=['POST'])
197
  @app.route('/sudo/login', methods=['POST'])
198
  def login():
199
  if request.json.get('sudo_secret') == os.getenv("SUDO_SECRET"):
200
+ return jsonify({
201
+ "status": "success",
202
+ "token": os.getenv("SUDO_SECRET"),
203
+ "redirect": "/admin/dashboard"
204
+ })
205
  return jsonify({"error": "Invalid secret"}), 403
206
 
207
+ @app.route('/admin/dashboard')
208
  @app.route('/sudo/dashboard')
209
  def dashboard():
210
  return render_template('dashboard.html')
211
 
212
+ # [Keep other admin routes...]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
 
214
+ # Serve admin static files
215
+ @app.route('/admin/static/<path:filename>')
216
+ def admin_static(filename):
217
+ return send_from_directory('/app/admin/static', filename)
 
 
 
 
 
218
 
219
  # ===== LibreChat Proxy =====
220
  def is_librechat_ready():
221
  try:
222
+ return requests.get('http://localhost:3080/api', timeout=1).status_code < 500
223
  except:
224
  return False
225
 
226
  @app.route('/', defaults={'path': ''})
227
+ @app.route('/<path:path>')
228
  def proxy(path):
229
  # Don't proxy admin routes
230
+ if path.startswith(('admin/', 'sudo/', 'admin', 'sudo')):
231
+ return "Route not found", 404
232
 
233
+ # Wait for backend
234
+ if not is_librechat_ready():
235
+ return "LibreChat backend starting...", 503
 
 
 
 
236
 
237
+ # Forward request
238
  resp = requests.request(
239
  method=request.method,
240
  url=f"http://localhost:3080/{path}",
241
+ headers={k: v for k, v in request.headers if k.lower() != 'host'},
242
  data=request.get_data(),
243
  cookies=request.cookies,
244
+ allow_redirects=False
 
245
  )
246
 
247
+ # Build response
248
+ response = app.make_response((resp.content, resp.status_code))
249
+ for k, v in resp.headers.items():
250
+ if k.lower() not in ['content-length', 'transfer-encoding']:
251
+ response.headers[k] = v
252
  return response
253
 
254
  def start_librechat():
255
+ subprocess.Popen(["npm", "run", "backend"], cwd="/app")
256
 
257
  if __name__ == "__main__":
258
+ # Start LibreChat
259
  threading.Thread(target=start_librechat, daemon=True).start()
260
 
261
+ # Start server
262
+ print("Starting combined server on port 7860")
263
+ serve(app, host='0.0.0.0', port=7860, threads=4)
264
  EOF
265
 
266
  # Startup script