 tail -f /var/log/ids/ml_backend.log
[HYBRID] Mode: Hybrid (IF + Ensemble)
[ML] ✓ Hybrid detector models loaded and ready
 Starting IDS API on http://0.0.0.0:8000
 Docs available at http://0.0.0.0:8000/docs
INFO:     127.0.0.1:45342 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:49754 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:50634 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:39232 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:35736 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:37462 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:59676 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:34256 - "GET /health HTTP/1.1" 200 OK
INFO:     127.0.0.1:34256 - "GET /services/status HTTP/1.1" 200 OK
INFO:     127.0.0.1:34256 - "GET /stats HTTP/1.1" 200 OK
INFO:     127.0.0.1:34264 - "POST /train HTTP/1.1" 200 OK
[TRAIN] Inizio training...
INFO:     127.0.0.1:34264 - "GET /stats HTTP/1.1" 200 OK
[TRAIN] Trovati 100000 log per training
[TRAIN] Addestramento modello...
[TRAIN] Using Hybrid ML Detector
[HYBRID] Training hybrid model on 100000 logs...
INFO:     127.0.0.1:41612 - "GET /stats HTTP/1.1" 200 OK
Traceback (most recent call last):
  File "/opt/ids/python_ml/main.py", line 201, in do_training
    result = ml_detector.train_unsupervised(df)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/ids/python_ml/ml_hybrid_detector.py", line 467, in train_unsupervised
    self.save_models()
  File "/opt/ids/python_ml/ml_hybrid_detector.py", line 658, in save_models
    joblib.dump(self.ensemble_classifier, self.model_dir / "ensemble_classifier_latest.pkl")
  File "/opt/ids/python_ml/venv/lib64/python3.11/site-packages/joblib/numpy_pickle.py", line 552, in dump
    with open(filename, 'wb') as f:
         ^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied: 'models/ensemble_classifier_latest.pkl'
[HYBRID] Extracted features for 1430 unique IPs
[HYBRID] Pre-training Isolation Forest for feature selection...
[HYBRID] Generated 43 pseudo-anomalies from pre-training IF
[HYBRID] Feature selection: 25 → 18 features
[HYBRID] Selected features: total_packets, total_bytes, conn_count, avg_packet_size, bytes_per_second... (+13 more)
[HYBRID] Normalizing features...
[HYBRID] Training Extended Isolation Forest (contamination=0.03)...
[HYBRID] Generating pseudo-labels from Isolation Forest...
[HYBRID] Pseudo-labels: 43 anomalies, 1387 normal
[HYBRID] Training ensemble classifier (DT + RF + XGBoost)...
[HYBRID] Class distribution OK: [0 1] (counts: [1387   43])
[HYBRID] Ensemble .fit() completed successfully
[HYBRID] ✅ Ensemble verified: produces 2 class probabilities
[HYBRID] Ensemble training completed and verified!
[TRAIN ERROR] ❌ Errore durante training: [Errno 13] Permission denied: 'models/ensemble_classifier_latest.pkl'
INFO:     127.0.0.1:45694 - "GET /stats HTTP/1.1" 200 OK
^C
(venv) [root@ids python_ml]# ls models/
ensemble_classifier_20251124_185541.pkl  feature_names.json                       feature_selector_latest.pkl              isolation_forest_20251125_183830.pkl     scaler_20251124_192122.pkl
ensemble_classifier_20251124_185920.pkl  feature_selector_20251124_185541.pkl     isolation_forest.joblib                  isolation_forest_latest.pkl              scaler_20251125_090356.pkl
ensemble_classifier_20251124_192109.pkl  feature_selector_20251124_185920.pkl     isolation_forest_20251124_185541.pkl     metadata_20251124_185541.json            scaler_20251125_092703.pkl
ensemble_classifier_20251124_192122.pkl  feature_selector_20251124_192109.pkl     isolation_forest_20251124_185920.pkl     metadata_20251124_185920.json            scaler_20251125_120016.pkl
ensemble_classifier_20251125_090356.pkl  feature_selector_20251124_192122.pkl     isolation_forest_20251124_192109.pkl     metadata_20251124_192109.json            scaler_20251125_181945.pkl
ensemble_classifier_20251125_092703.pkl  feature_selector_20251125_090356.pkl     isolation_forest_20251124_192122.pkl     metadata_20251124_192122.json            scaler_20251125_182742.pkl
ensemble_classifier_20251125_120016.pkl  feature_selector_20251125_092703.pkl     isolation_forest_20251125_090356.pkl     metadata_20251125_092703.json            scaler_20251125_183049.pkl
ensemble_classifier_20251125_181945.pkl  feature_selector_20251125_120016.pkl     isolation_forest_20251125_092703.pkl     metadata_latest.json                     scaler_20251125_183830.pkl
ensemble_classifier_20251125_182742.pkl  feature_selector_20251125_181945.pkl     isolation_forest_20251125_120016.pkl     scaler.joblib                            scaler_latest.pkl
ensemble_classifier_20251125_183049.pkl  feature_selector_20251125_182742.pkl     isolation_forest_20251125_181945.pkl     scaler_20251124_185541.pkl
ensemble_classifier_20251125_183830.pkl  feature_selector_20251125_183049.pkl     isolation_forest_20251125_182742.pkl     scaler_20251124_185920.pkl
ensemble_classifier_latest.pkl           feature_selector_20251125_183830.pkl     isolation_forest_20251125_183049.pkl     scaler_20251124_192109.pkl
(venv) [root@ids python_ml]#                                                                                                                                 