From a2ae2903cf84822703a06f1c2ab54fbedcc36197 Mon Sep 17 00:00:00 2001 From: Eric Work Date: Wed, 28 Jan 2026 06:27:46 -0800 Subject: [PATCH] Add networking options for configuring listening ports (#21779) --- Makefile | 3 +- .../etc/s6-overlay/s6-rc.d/certsync/run | 7 ++- .../rootfs/etc/s6-overlay/s6-rc.d/nginx/run | 12 ++-- .../rootfs/usr/local/nginx/get_base_path.py | 11 ---- .../usr/local/nginx/get_listen_settings.py | 35 ----------- .../usr/local/nginx/get_nginx_settings.py | 62 +++++++++++++++++++ .../local/nginx/templates/base_path.gotmpl | 2 +- .../usr/local/nginx/templates/listen.gotmpl | 61 ++++++++---------- docs/docs/configuration/advanced.md | 41 ++++++------ docs/docs/configuration/reference.md | 10 ++- frigate/api/auth.py | 22 ++++--- frigate/config/__init__.py | 1 + frigate/config/network.py | 18 +++++- frigate/const.py | 1 - frigate/record/export.py | 9 ++- web/public/locales/en/config/networking.json | 15 ++++- web/src/components/auth/ProtectedRoute.tsx | 2 +- web/src/hooks/use-allowed-cameras.ts | 2 +- 18 files changed, 183 insertions(+), 131 deletions(-) delete mode 100644 docker/main/rootfs/usr/local/nginx/get_base_path.py delete mode 100644 docker/main/rootfs/usr/local/nginx/get_listen_settings.py create mode 100644 docker/main/rootfs/usr/local/nginx/get_nginx_settings.py diff --git a/Makefile b/Makefile index 1226a9e01..3800399ea 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,8 @@ push: push-boards --push run: local - docker run --rm --publish=5000:5000 --volume=${PWD}/config:/config frigate:latest + docker run --rm --publish=5000:5000 --publish=8971:8971 \ + --volume=${PWD}/config:/config frigate:latest run_tests: local docker run --rm --workdir=/opt/frigate --entrypoint= frigate:latest \ diff --git a/docker/main/rootfs/etc/s6-overlay/s6-rc.d/certsync/run b/docker/main/rootfs/etc/s6-overlay/s6-rc.d/certsync/run index 4ce1c133f..b834c09bb 100755 --- a/docker/main/rootfs/etc/s6-overlay/s6-rc.d/certsync/run +++ b/docker/main/rootfs/etc/s6-overlay/s6-rc.d/certsync/run @@ -10,7 +10,8 @@ echo "[INFO] Starting certsync..." lefile="/etc/letsencrypt/live/frigate/fullchain.pem" -tls_enabled=`python3 /usr/local/nginx/get_listen_settings.py | jq -r .tls.enabled` +tls_enabled=`python3 /usr/local/nginx/get_nginx_settings.py | jq -r .tls.enabled` +listen_external_port=`python3 /usr/local/nginx/get_nginx_settings.py | jq -r .listen.external_port` while true do @@ -34,7 +35,7 @@ do ;; esac - liveprint=`echo | openssl s_client -showcerts -connect 127.0.0.1:8971 2>&1 | openssl x509 -fingerprint 2>&1 | grep -i fingerprint || echo 'failed'` + liveprint=`echo | openssl s_client -showcerts -connect 127.0.0.1:$listen_external_port 2>&1 | openssl x509 -fingerprint 2>&1 | grep -i fingerprint || echo 'failed'` case "$liveprint" in *Fingerprint*) @@ -55,4 +56,4 @@ do done -exit 0 \ No newline at end of file +exit 0 diff --git a/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run b/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run index 8bd9b5250..a3c7b3248 100755 --- a/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run +++ b/docker/main/rootfs/etc/s6-overlay/s6-rc.d/nginx/run @@ -80,14 +80,14 @@ if [ ! \( -f "$letsencrypt_path/privkey.pem" -a -f "$letsencrypt_path/fullchain. fi # build templates for optional FRIGATE_BASE_PATH environment variable -python3 /usr/local/nginx/get_base_path.py | \ +python3 /usr/local/nginx/get_nginx_settings.py | \ tempio -template /usr/local/nginx/templates/base_path.gotmpl \ - -out /usr/local/nginx/conf/base_path.conf + -out /usr/local/nginx/conf/base_path.conf -# build templates for optional TLS support -python3 /usr/local/nginx/get_listen_settings.py | \ - tempio -template /usr/local/nginx/templates/listen.gotmpl \ - -out /usr/local/nginx/conf/listen.conf +# build templates for additional network settings +python3 /usr/local/nginx/get_nginx_settings.py | \ + tempio -template /usr/local/nginx/templates/listen.gotmpl \ + -out /usr/local/nginx/conf/listen.conf # Replace the bash process with the NGINX process, redirecting stderr to stdout exec 2>&1 diff --git a/docker/main/rootfs/usr/local/nginx/get_base_path.py b/docker/main/rootfs/usr/local/nginx/get_base_path.py deleted file mode 100644 index 2e78a7de9..000000000 --- a/docker/main/rootfs/usr/local/nginx/get_base_path.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Prints the base path as json to stdout.""" - -import json -import os -from typing import Any - -base_path = os.environ.get("FRIGATE_BASE_PATH", "") - -result: dict[str, Any] = {"base_path": base_path} - -print(json.dumps(result)) diff --git a/docker/main/rootfs/usr/local/nginx/get_listen_settings.py b/docker/main/rootfs/usr/local/nginx/get_listen_settings.py deleted file mode 100644 index d879db56e..000000000 --- a/docker/main/rootfs/usr/local/nginx/get_listen_settings.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Prints the tls config as json to stdout.""" - -import json -import sys -from typing import Any - -from ruamel.yaml import YAML - -sys.path.insert(0, "/opt/frigate") -from frigate.util.config import find_config_file - -sys.path.remove("/opt/frigate") - -yaml = YAML() - -config_file = find_config_file() - -try: - with open(config_file) as f: - raw_config = f.read() - - if config_file.endswith((".yaml", ".yml")): - config: dict[str, Any] = yaml.load(raw_config) - elif config_file.endswith(".json"): - config: dict[str, Any] = json.loads(raw_config) -except FileNotFoundError: - config: dict[str, Any] = {} - -tls_config: dict[str, any] = config.get("tls", {"enabled": True}) -networking_config = config.get("networking", {}) -ipv6_config = networking_config.get("ipv6", {"enabled": False}) - -output = {"tls": tls_config, "ipv6": ipv6_config} - -print(json.dumps(output)) diff --git a/docker/main/rootfs/usr/local/nginx/get_nginx_settings.py b/docker/main/rootfs/usr/local/nginx/get_nginx_settings.py new file mode 100644 index 000000000..79cda3686 --- /dev/null +++ b/docker/main/rootfs/usr/local/nginx/get_nginx_settings.py @@ -0,0 +1,62 @@ +"""Prints the nginx settings as json to stdout.""" + +import json +import os +import sys +from typing import Any + +from ruamel.yaml import YAML + +sys.path.insert(0, "/opt/frigate") +from frigate.util.config import find_config_file + +sys.path.remove("/opt/frigate") + +yaml = YAML() + +config_file = find_config_file() + +try: + with open(config_file) as f: + raw_config = f.read() + + if config_file.endswith((".yaml", ".yml")): + config: dict[str, Any] = yaml.load(raw_config) + elif config_file.endswith(".json"): + config: dict[str, Any] = json.loads(raw_config) +except FileNotFoundError: + config: dict[str, Any] = {} + +tls_config: dict[str, Any] = config.get("tls", {}) +tls_config.setdefault("enabled", True) + +networking_config: dict[str, Any] = config.get("networking", {}) +ipv6_config: dict[str, Any] = networking_config.get("ipv6", {}) +ipv6_config.setdefault("enabled", False) + +listen_config: dict[str, Any] = networking_config.get("listen", {}) +listen_config.setdefault("internal", 5000) +listen_config.setdefault("external", 8971) + +# handle case where internal port is a string with ip:port +internal_port = listen_config["internal"] +if type(internal_port) is str: + internal_port = int(internal_port.split(":")[-1]) +listen_config["internal_port"] = internal_port + +# handle case where external port is a string with ip:port +external_port = listen_config["external"] +if type(external_port) is str: + external_port = int(external_port.split(":")[-1]) +listen_config["external_port"] = external_port + +base_path = os.environ.get("FRIGATE_BASE_PATH", "") + +result: dict[str, Any] = { + "tls": tls_config, + "ipv6": ipv6_config, + "listen": listen_config, + "base_path": base_path, +} + +print(json.dumps(result)) diff --git a/docker/main/rootfs/usr/local/nginx/templates/base_path.gotmpl b/docker/main/rootfs/usr/local/nginx/templates/base_path.gotmpl index ace4443ee..ca945ba1f 100644 --- a/docker/main/rootfs/usr/local/nginx/templates/base_path.gotmpl +++ b/docker/main/rootfs/usr/local/nginx/templates/base_path.gotmpl @@ -7,7 +7,7 @@ location ^~ {{ .base_path }}/ { # remove base_url from the path before passing upstream rewrite ^{{ .base_path }}/(.*) /$1 break; - proxy_pass $scheme://127.0.0.1:8971; + proxy_pass $scheme://127.0.0.1:{{ .listen.external_port }}; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; diff --git a/docker/main/rootfs/usr/local/nginx/templates/listen.gotmpl b/docker/main/rootfs/usr/local/nginx/templates/listen.gotmpl index 066f872cb..628784b60 100644 --- a/docker/main/rootfs/usr/local/nginx/templates/listen.gotmpl +++ b/docker/main/rootfs/usr/local/nginx/templates/listen.gotmpl @@ -1,45 +1,36 @@ - # Internal (IPv4 always; IPv6 optional) -listen 5000; -{{ if .ipv6 }}{{ if .ipv6.enabled }}listen [::]:5000;{{ end }}{{ end }} - +listen {{ .listen.internal }}; +{{ if .ipv6.enabled }}listen [::]:{{ .listen.internal_port }};{{ end }} # intended for external traffic, protected by auth -{{ if .tls }} - {{ if .tls.enabled }} - # external HTTPS (IPv4 always; IPv6 optional) - listen 8971 ssl; - {{ if .ipv6 }}{{ if .ipv6.enabled }}listen [::]:8971 ssl;{{ end }}{{ end }} +{{ if .tls.enabled }} + # external HTTPS (IPv4 always; IPv6 optional) + listen {{ .listen.external }} ssl; + {{ if .ipv6.enabled }}listen [::]:{{ .listen.external_port }} ssl;{{ end }} - ssl_certificate /etc/letsencrypt/live/frigate/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/frigate/privkey.pem; + ssl_certificate /etc/letsencrypt/live/frigate/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/frigate/privkey.pem; - # generated 2024-06-01, Mozilla Guideline v5.7, nginx 1.25.3, OpenSSL 1.1.1w, modern configuration, no OCSP - # https://ssl-config.mozilla.org/#server=nginx&version=1.25.3&config=modern&openssl=1.1.1w&ocsp=false&guideline=5.7 - ssl_session_timeout 1d; - ssl_session_cache shared:MozSSL:10m; # about 40000 sessions - ssl_session_tickets off; + # generated 2024-06-01, Mozilla Guideline v5.7, nginx 1.25.3, OpenSSL 1.1.1w, modern configuration, no OCSP + # https://ssl-config.mozilla.org/#server=nginx&version=1.25.3&config=modern&openssl=1.1.1w&ocsp=false&guideline=5.7 + ssl_session_timeout 1d; + ssl_session_cache shared:MozSSL:10m; # about 40000 sessions + ssl_session_tickets off; - # modern configuration - ssl_protocols TLSv1.3; - ssl_prefer_server_ciphers off; + # modern configuration + ssl_protocols TLSv1.3; + ssl_prefer_server_ciphers off; - # HSTS (ngx_http_headers_module is required) (63072000 seconds) - add_header Strict-Transport-Security "max-age=63072000" always; + # HSTS (ngx_http_headers_module is required) (63072000 seconds) + add_header Strict-Transport-Security "max-age=63072000" always; - # ACME challenge location - location /.well-known/acme-challenge/ { - default_type "text/plain"; - root /etc/letsencrypt/www; - } - {{ else }} - # external HTTP (IPv4 always; IPv6 optional) - listen 8971; - {{ if .ipv6 }}{{ if .ipv6.enabled }}listen [::]:8971;{{ end }}{{ end }} - {{ end }} + # ACME challenge location + location /.well-known/acme-challenge/ { + default_type "text/plain"; + root /etc/letsencrypt/www; + } {{ else }} - # (No tls section) default to HTTP (IPv4 always; IPv6 optional) - listen 8971; - {{ if .ipv6 }}{{ if .ipv6.enabled }}listen [::]:8971;{{ end }}{{ end }} + # (No tls) default to HTTP (IPv4 always; IPv6 optional) + listen {{ .listen.external }}; + {{ if .ipv6.enabled }}listen [::]:{{ .listen.external_port }};{{ end }} {{ end }} - diff --git a/docs/docs/configuration/advanced.md b/docs/docs/configuration/advanced.md index 8cd368144..b8dbffd62 100644 --- a/docs/docs/configuration/advanced.md +++ b/docs/docs/configuration/advanced.md @@ -155,34 +155,33 @@ services: ### Enabling IPv6 -IPv6 is disabled by default, to enable IPv6 listen.gotmpl needs to be bind mounted with IPv6 enabled. For example: +IPv6 is disabled by default, to enable IPv6 modify your Frigate configuration as follows: -``` -{{ if not .enabled }} -# intended for external traffic, protected by auth -listen 8971; -{{ else }} -# intended for external traffic, protected by auth -listen 8971 ssl; - -# intended for internal traffic, not protected by auth -listen 5000; +```yaml +networking: + ipv6: + enabled: True ``` -becomes +### Listen on different ports -``` -{{ if not .enabled }} -# intended for external traffic, protected by auth -listen [::]:8971 ipv6only=off; -{{ else }} -# intended for external traffic, protected by auth -listen [::]:8971 ipv6only=off ssl; +You can change the ports Nginx uses for listening using Frigate's configuration file. The internal port (unauthenticated) and external port (authenticated) can be changed independently. You can also specify an IP address using the format `ip:port` if you wish to bind the port to a specific interface. This may be useful for example to prevent exposing the internal port outside the container. -# intended for internal traffic, not protected by auth -listen [::]:5000 ipv6only=off; +For example: + +```yaml +networking: + listen: + internal: 127.0.0.1:5000 + external: 8971 ``` +:::warning + +This setting is for advanced users. For the majority of use cases it's recommended to change the `ports` section of your Docker compose file or use the Docker `run` `--publish` option instead, e.g. `-p 443:8971`. Changing Frigate's ports may break some integrations. + +::: + ## Base path By default, Frigate runs at the root path (`/`). However some setups require to run Frigate under a custom path prefix (e.g. `/frigate`), especially when Frigate is located behind a reverse proxy that requires path-based routing. diff --git a/docs/docs/configuration/reference.md b/docs/docs/configuration/reference.md index 6101d2915..b318bd7f0 100644 --- a/docs/docs/configuration/reference.md +++ b/docs/docs/configuration/reference.md @@ -73,11 +73,19 @@ tls: # Optional: Enable TLS for port 8971 (default: shown below) enabled: True -# Optional: IPv6 configuration +# Optional: Networking configuration networking: # Optional: Enable IPv6 on 5000, and 8971 if tls is configured (default: shown below) ipv6: enabled: False + # Optional: Override ports Frigate uses for listening (defaults: shown below) + # An IP address may also be provided to bind to a specific interface, e.g. ip:port + # NOTE: This setting is for advanced users and may break some integrations. The majority + # of users should change ports in the docker compose file + # or use the docker run `--publish` option to select a different port. + listen: + internal: 5000 + external: 8971 # Optional: Proxy configuration proxy: diff --git a/frigate/api/auth.py b/frigate/api/auth.py index cae80dc5b..52c04f3af 100644 --- a/frigate/api/auth.py +++ b/frigate/api/auth.py @@ -26,7 +26,7 @@ from frigate.api.defs.request.app_body import ( AppPutRoleBody, ) from frigate.api.defs.tags import Tags -from frigate.config import AuthConfig, ProxyConfig +from frigate.config import AuthConfig, NetworkingConfig, ProxyConfig from frigate.const import CONFIG_DIR, JWT_SECRET_ENV_VAR, PASSWORD_HASH_ALGORITHM from frigate.models import User @@ -41,7 +41,7 @@ def require_admin_by_default(): endpoints require admin access unless explicitly overridden with allow_public(), allow_any_authenticated(), or require_role(). - Port 5000 (internal) always has admin role set by the /auth endpoint, + Internal port always has admin role set by the /auth endpoint, so this check passes automatically for internal requests. Certain paths are exempted from the global admin check because they must @@ -130,7 +130,7 @@ def require_admin_by_default(): pass # For all other paths, require admin role - # Port 5000 (internal) requests have admin role set automatically + # Internal port requests have admin role set automatically role = request.headers.get("remote-role") if role == "admin": return @@ -148,7 +148,7 @@ def _is_authenticated(request: Request) -> bool: Helper to determine if a request is from an authenticated user. Returns True if the request has a valid authenticated user (not anonymous). - Port 5000 internal requests are considered anonymous despite having admin role. + Internal port requests are considered anonymous despite having admin role. """ username = request.headers.get("remote-user") return username is not None and username != "anonymous" @@ -176,18 +176,18 @@ def allow_any_authenticated(): Override dependency to allow any authenticated user (bypass admin requirement). Allows: - - Port 5000 internal requests (have admin role despite anonymous user) + - Internal port requests (have admin role despite anonymous user) - Any authenticated user with a real username (not "anonymous") Rejects: - - Port 8971 requests with anonymous user (auth disabled, no proxy auth) + - External port requests with anonymous user (auth disabled, no proxy auth) Example: @router.get("/authenticated-endpoint", dependencies=[Depends(allow_any_authenticated())]) """ async def auth_checker(request: Request): - # Port 5000 requests have admin role and should be allowed + # Internal port requests have admin role and should be allowed role = request.headers.get("remote-role") if role == "admin": return @@ -558,12 +558,18 @@ def resolve_role( def auth(request: Request): auth_config: AuthConfig = request.app.frigate_config.auth proxy_config: ProxyConfig = request.app.frigate_config.proxy + networking_config: NetworkingConfig = request.app.frigate_config.networking success_response = Response("", status_code=202) + # handle case where internal port is a string with ip:port + internal_port = networking_config.listen.internal + if type(internal_port) is str: + internal_port = int(internal_port.split(":")[-1]) + # dont require auth if the request is on the internal port # this header is set by Frigate's nginx proxy, so it cant be spoofed - if int(request.headers.get("x-server-port", default=0)) == 5000: + if int(request.headers.get("x-server-port", default=0)) == internal_port: success_response.headers["remote-user"] = "anonymous" success_response.headers["remote-role"] = "admin" return success_response diff --git a/frigate/config/__init__.py b/frigate/config/__init__.py index c6ff535b0..88f7b79f9 100644 --- a/frigate/config/__init__.py +++ b/frigate/config/__init__.py @@ -8,6 +8,7 @@ from .config import * # noqa: F403 from .database import * # noqa: F403 from .logger import * # noqa: F403 from .mqtt import * # noqa: F403 +from .network import * # noqa: F403 from .proxy import * # noqa: F403 from .telemetry import * # noqa: F403 from .tls import * # noqa: F403 diff --git a/frigate/config/network.py b/frigate/config/network.py index c8b3cfd1c..ab4e5b83e 100644 --- a/frigate/config/network.py +++ b/frigate/config/network.py @@ -1,13 +1,27 @@ +from typing import Union + from pydantic import Field from .base import FrigateBaseModel -__all__ = ["IPv6Config", "NetworkingConfig"] +__all__ = ["IPv6Config", "ListenConfig", "NetworkingConfig"] class IPv6Config(FrigateBaseModel): enabled: bool = Field(default=False, title="Enable IPv6 for port 5000 and/or 8971") +class ListenConfig(FrigateBaseModel): + internal: Union[int, str] = Field( + default=5000, title="Internal listening port for Frigate" + ) + external: Union[int, str] = Field( + default=8971, title="External listening port for Frigate" + ) + + class NetworkingConfig(FrigateBaseModel): - ipv6: IPv6Config = Field(default_factory=IPv6Config, title="Network configuration") + ipv6: IPv6Config = Field(default_factory=IPv6Config, title="IPv6 configuration") + listen: ListenConfig = Field( + default_factory=ListenConfig, title="Listening ports configuration" + ) diff --git a/frigate/const.py b/frigate/const.py index ac8144c2c..4d427d21d 100644 --- a/frigate/const.py +++ b/frigate/const.py @@ -14,7 +14,6 @@ RECORD_DIR = f"{BASE_DIR}/recordings" TRIGGER_DIR = f"{CLIPS_DIR}/triggers" BIRDSEYE_PIPE = "/tmp/cache/birdseye" CACHE_DIR = "/tmp/cache" -FRIGATE_LOCALHOST = "http://127.0.0.1:5000" PLUS_ENV_VAR = "PLUS_API_KEY" PLUS_API_HOST = "https://api.frigate.video" diff --git a/frigate/record/export.py b/frigate/record/export.py index afaed1a2a..c1c478ef4 100644 --- a/frigate/record/export.py +++ b/frigate/record/export.py @@ -184,8 +184,13 @@ class RecordingExporter(threading.Thread): def get_record_export_command( self, video_path: str, use_hwaccel: bool = True ) -> list[str]: + # handle case where internal port is a string with ip:port + internal_port = self.config.networking.listen.internal + if type(internal_port) is str: + internal_port = int(internal_port.split(":")[-1]) + if (self.end_time - self.start_time) <= MAX_PLAYLIST_SECONDS: - playlist_lines = f"http://127.0.0.1:5000/vod/{self.camera}/start/{self.start_time}/end/{self.end_time}/index.m3u8" + playlist_lines = f"http://127.0.0.1:{internal_port}/vod/{self.camera}/start/{self.start_time}/end/{self.end_time}/index.m3u8" ffmpeg_input = ( f"-y -protocol_whitelist pipe,file,http,tcp -i {playlist_lines}" ) @@ -217,7 +222,7 @@ class RecordingExporter(threading.Thread): for page in range(1, num_pages + 1): playlist = export_recordings.paginate(page, page_size) playlist_lines.append( - f"file 'http://127.0.0.1:5000/vod/{self.camera}/start/{float(playlist[0].start_time)}/end/{float(playlist[-1].end_time)}/index.m3u8'" + f"file 'http://127.0.0.1:{internal_port}/vod/{self.camera}/start/{float(playlist[0].start_time)}/end/{float(playlist[-1].end_time)}/index.m3u8'" ) ffmpeg_input = "-y -protocol_whitelist pipe,file,http,tcp -f concat -safe 0 -i /dev/stdin" diff --git a/web/public/locales/en/config/networking.json b/web/public/locales/en/config/networking.json index 0f8d9cc54..592ea9477 100644 --- a/web/public/locales/en/config/networking.json +++ b/web/public/locales/en/config/networking.json @@ -2,12 +2,23 @@ "label": "Networking configuration", "properties": { "ipv6": { - "label": "Network configuration", + "label": "IPv6 configuration", "properties": { "enabled": { "label": "Enable IPv6 for port 5000 and/or 8971" } } + }, + "listen": { + "label": "Listening ports configuration", + "properties": { + "internal": { + "label": "Internal listening port for Frigate" + }, + "external": { + "label": "External listening port for Frigate" + } + } } } -} \ No newline at end of file +} diff --git a/web/src/components/auth/ProtectedRoute.tsx b/web/src/components/auth/ProtectedRoute.tsx index 55edc60bd..0090a5dd9 100644 --- a/web/src/components/auth/ProtectedRoute.tsx +++ b/web/src/components/auth/ProtectedRoute.tsx @@ -39,7 +39,7 @@ export default function ProtectedRoute({ return ; } - // Authenticated mode (8971): require login + // Authenticated mode (external port): require login if (!auth.user) { return ( diff --git a/web/src/hooks/use-allowed-cameras.ts b/web/src/hooks/use-allowed-cameras.ts index 9eae59fc2..05941922a 100644 --- a/web/src/hooks/use-allowed-cameras.ts +++ b/web/src/hooks/use-allowed-cameras.ts @@ -12,7 +12,7 @@ export function useAllowedCameras() { if ( auth.user?.role === "viewer" || auth.user?.role === "admin" || - !auth.isAuthenticated // anonymous port 5000 + !auth.isAuthenticated // anonymous internal port ) { // return all cameras return config?.cameras ? Object.keys(config.cameras) : [];