From f795ffa250e3cc3a0af0c83c67caa4060daa863b Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Sun, 23 Aug 2026 17:59:37 -0500 Subject: [PATCH] Disable bandwidth stats gracefully when not running as root --- frigate/test/test_bandwidth_stats.py | 26 ++++++++++++++++++++++++++ frigate/util/services.py | 15 +++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 frigate/test/test_bandwidth_stats.py diff --git a/frigate/test/test_bandwidth_stats.py b/frigate/test/test_bandwidth_stats.py new file mode 100644 index 0000000000..6402e41666 --- /dev/null +++ b/frigate/test/test_bandwidth_stats.py @@ -0,0 +1,26 @@ +"""Tests for bandwidth stats privilege handling.""" + +import unittest +from unittest.mock import MagicMock, patch + +from frigate.util import services + + +class TestBandwidthStatsPrivileges(unittest.TestCase): + def setUp(self): + services._bandwidth_warning_logged = False + + @patch("frigate.util.services.sp.run") + @patch("frigate.util.services.os.geteuid", return_value=1000) + def test_returns_empty_and_warns_once_without_root(self, _, sp_run): + config = MagicMock() + with self.assertLogs("frigate.util.services", level="WARNING") as logs: + assert services.get_bandwidth_stats(config) == {} + assert services.get_bandwidth_stats(config) == {} + sp_run.assert_not_called() + warnings = [m for m in logs.output if "require root" in m] + assert len(warnings) == 1 + + +if __name__ == "__main__": + unittest.main() diff --git a/frigate/util/services.py b/frigate/util/services.py index 3336c59ba1..3bfeaf9a8a 100644 --- a/frigate/util/services.py +++ b/frigate/util/services.py @@ -187,8 +187,23 @@ def get_physical_interfaces(interfaces) -> list: return physical_interfaces +_bandwidth_warning_logged = False + + def get_bandwidth_stats(config) -> dict[str, dict]: """Get bandwidth usages for each ffmpeg process id""" + global _bandwidth_warning_logged + + if os.geteuid() != 0: + if not _bandwidth_warning_logged: + logger.warning( + "Network bandwidth stats require root (nethogs needs CAP_NET_ADMIN/CAP_NET_RAW) " + "and are disabled; set FRIGATE_RUN_AS_ROOT=true or disable " + "telemetry.stats.network_bandwidth to silence this warning" + ) + _bandwidth_warning_logged = True + return {} + usages = {} top_command = ["nethogs", "-t", "-v0", "-c5", "-d1"] + get_physical_interfaces( config.telemetry.network_interfaces