CodebaseAi commited on
Commit
d58a19f
·
1 Parent(s): 5182442

Docker added

Browse files
Files changed (3) hide show
  1. backend/Dockerfile +29 -0
  2. backend/app.py +27 -34
  3. backend/requirements.txt +4 -1
backend/Dockerfile ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 1. Use a standard Python image
2
+ FROM python:3.9-slim
3
+
4
+ # 2. Install system-level tools needed for Scapy and Network monitoring
5
+ RUN apt-get update && apt-get install -y \
6
+ libpcap-dev \
7
+ gcc \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ # 3. Create a non-root user for security (Hugging Face requirement)
11
+ RUN useradd -m -u 1000 user
12
+ USER user
13
+ ENV PATH="/home/user/.local/bin:${PATH}"
14
+
15
+ # 4. Set the working directory
16
+ WORKDIR /home/user/app
17
+
18
+ # 5. Copy and install requirements
19
+ COPY --chown=user requirements.txt .
20
+ RUN pip install --no-cache-dir --user -r requirements.txt
21
+
22
+ # 6. Copy the rest of your code
23
+ COPY --chown=user . .
24
+
25
+ # 7. Hugging Face uses port 7860 by default
26
+ EXPOSE 7860
27
+
28
+ # 8. Start the server using Gunicorn + Eventlet (Best for SocketIO)
29
+ CMD ["gunicorn", "--worker-class", "eventlet", "-w", "1", "--bind", "0.0.0.0:7860", "app:app"]
backend/app.py CHANGED
@@ -1,64 +1,57 @@
1
- # =============================================================
2
- # FILE: app.py
3
- # Optimized Flask + SocketIO entry (threading mode, no debug)
4
- # =============================================================
5
  import logging
6
  from flask import Flask, jsonify
7
  from flask_cors import CORS
8
  from flask_socketio import SocketIO
9
- import os # <-- ADDED: For reading environment variables
10
-
11
 
12
  # lightweight logging
13
  logging.getLogger('werkzeug').setLevel(logging.ERROR)
14
  logging.getLogger('socketio').setLevel(logging.ERROR)
15
 
16
-
17
  app = Flask(__name__)
18
- CORS(app, resources={r"/api/*": {"origins": "*"}})
19
 
 
 
20
 
21
- # Use threading mode to avoid eventlet monkey-patch issues with Scapy/IO
22
  socketio = SocketIO(app, cors_allowed_origins="*", async_mode="threading")
23
 
24
-
25
- # Mail initialization is left as-is but keep credentials out of source in production
26
  try:
27
  from extensions import mail
28
  app.config.update(
29
  MAIL_SERVER="smtp.gmail.com",
30
  MAIL_PORT=587,
31
  MAIL_USE_TLS=True,
32
- # --- SECURITY FIX: Fetch credentials from environment variables ---
33
  MAIL_USERNAME=os.environ.get("MAIL_USERNAME"),
34
  MAIL_PASSWORD=os.environ.get("MAIL_PASSWORD"),
35
- # -----------------------------------------------------------------
36
  MAIL_DEFAULT_SENDER=("Adaptive AI NIDS", os.environ.get("MAIL_USERNAME"))
37
  )
38
  mail.init_app(app)
39
-
40
  except Exception:
41
- # If mail is not available in dev/test, continue gracefully
42
  pass
43
 
44
-
45
- # lazy import of sniffer so import side-effects are minimal
46
  sniffer = None
47
 
48
-
49
  def _get_sniffer():
50
  global sniffer
51
  if sniffer is None:
52
- from capture.live_manager import sniffer as _s
53
- sniffer = _s
 
 
 
 
 
 
 
 
 
 
54
  return sniffer
55
 
56
-
57
- # Register blueprints lazily to avoid heavy imports at startup
58
  def register_blueprints(app):
59
  from importlib import import_module
60
-
61
-
62
  routes = [
63
  ("routes.live_route", "live_bp", "/api/live"),
64
  ("routes.logs_route", "logs_bp", "/api/logs"),
@@ -83,26 +76,26 @@ def register_blueprints(app):
83
  bp = getattr(mod, varname)
84
  app.register_blueprint(bp, url_prefix=prefix)
85
  print(f"✅ Registered route: {module_name} -> {prefix}")
86
-
87
  except Exception as e:
88
  print(f"⚠️ Skipping {module_name}: {e}")
89
 
90
  register_blueprints(app)
91
 
92
-
93
  @app.route("/")
94
  def home():
 
 
95
  s = _get_sniffer()
 
96
  return jsonify({
97
- "status": "✅ Backend Active",
98
- "capture_running": s.is_running() if s else False,
99
- "tip": "Use /api/live/start and /api/live/stop to control capture"
 
 
100
  })
101
 
102
-
103
- # --- REMOVED: The local run block is removed. Gunicorn will handle startup on Render. ---
104
  if __name__ == "__main__":
105
- print("🚀 Starting Adaptive AI NIDS Backend (threading mode)...")
106
- # # Run without debug — debug spawns extra processes and uses more CPU
107
- socketio.run(app, host="0.0.0.0", port=5000, debug=False)
108
 
 
 
 
 
 
1
  import logging
2
  from flask import Flask, jsonify
3
  from flask_cors import CORS
4
  from flask_socketio import SocketIO
5
+ import os
6
+ import socket
7
 
8
  # lightweight logging
9
  logging.getLogger('werkzeug').setLevel(logging.ERROR)
10
  logging.getLogger('socketio').setLevel(logging.ERROR)
11
 
 
12
  app = Flask(__name__)
 
13
 
14
+ # UPDATED: More robust CORS for deployment
15
+ CORS(app, resources={r"/api/*": {"origins": "*"}})
16
 
 
17
  socketio = SocketIO(app, cors_allowed_origins="*", async_mode="threading")
18
 
19
+ # Mail initialization
 
20
  try:
21
  from extensions import mail
22
  app.config.update(
23
  MAIL_SERVER="smtp.gmail.com",
24
  MAIL_PORT=587,
25
  MAIL_USE_TLS=True,
 
26
  MAIL_USERNAME=os.environ.get("MAIL_USERNAME"),
27
  MAIL_PASSWORD=os.environ.get("MAIL_PASSWORD"),
 
28
  MAIL_DEFAULT_SENDER=("Adaptive AI NIDS", os.environ.get("MAIL_USERNAME"))
29
  )
30
  mail.init_app(app)
 
31
  except Exception:
 
32
  pass
33
 
 
 
34
  sniffer = None
35
 
 
36
  def _get_sniffer():
37
  global sniffer
38
  if sniffer is None:
39
+ try:
40
+ # CLOUD GUARD: Don't import sniffer if on a cloud server that blocks raw sockets
41
+ # Render and Hugging Face usually set specific env variables
42
+ if os.environ.get("RENDER") or os.environ.get("SPACE_ID"):
43
+ print("⚠️ Cloud environment detected. Skipping sniffer initialization.")
44
+ return None
45
+
46
+ from capture.live_manager import sniffer as _s
47
+ sniffer = _s
48
+ except Exception as e:
49
+ print(f"⚠️ Could not initialize sniffer: {e}")
50
+ return None
51
  return sniffer
52
 
 
 
53
  def register_blueprints(app):
54
  from importlib import import_module
 
 
55
  routes = [
56
  ("routes.live_route", "live_bp", "/api/live"),
57
  ("routes.logs_route", "logs_bp", "/api/logs"),
 
76
  bp = getattr(mod, varname)
77
  app.register_blueprint(bp, url_prefix=prefix)
78
  print(f"✅ Registered route: {module_name} -> {prefix}")
 
79
  except Exception as e:
80
  print(f"⚠️ Skipping {module_name}: {e}")
81
 
82
  register_blueprints(app)
83
 
 
84
  @app.route("/")
85
  def home():
86
+ # Detect environment for frontend awareness
87
+ is_cloud = os.environ.get("RENDER") or os.environ.get("SPACE_ID")
88
  s = _get_sniffer()
89
+
90
  return jsonify({
91
+ "status": "✅ Backend Active",
92
+ "env": "cloud" if is_cloud else "local",
93
+ "capture_capability": "limited" if is_cloud else "full",
94
+ "capture_running": s.is_running() if s else False,
95
+ "tip": "Live sniffing requires local deployment."
96
  })
97
 
 
 
98
  if __name__ == "__main__":
99
+ print("🚀 Starting Adaptive AI NIDS Backend...")
100
+ socketio.run(app, host="0.0.0.0", port=5000, debug=False)
 
101
 
backend/requirements.txt CHANGED
@@ -39,4 +39,7 @@ Flask-SocketIO
39
  fpdf
40
  requests
41
  psutil
42
- groq
 
 
 
 
39
  fpdf
40
  requests
41
  psutil
42
+ groq
43
+ gunicorn
44
+ eventlet
45
+ huggingface_hub