1334 Commits

Author SHA1 Message Date
Nicolas Mowen
ab20815584
Fix NPU turbo key and priviledges set (#24138) 2026-08-30 12:15:49 -05:00
Josh Hawkins
890512b054
Container security hardening (phase 3, breaking) (#24081)
* Run the frigate service as the frigate user

* Run go2rtc as its own restricted user

* Run nginx as the frigate user with writable state in /tmp/nginx

* Disable bandwidth stats gracefully when not running as root

* Hand TensorRT model cache ownership to the runtime user

* Document non-root operation and per-hardware device access

* Create /media/frigate after the ownership sweep

* Assert non-root services, JWT migration, and escape hatch in CI

* only write the sweep sentinel when a media volume is mounted

* tolerate homekit config chown failures in the go2rtc run script

* chown the s6 log pipe so non-root nginx can reopen /dev/stdout

* set HOME to /config for non-root services

* run smoke nginx -t and the write probe as the runtime user

* re-own the nginx shm cache on service restart

* discard stdout for the unprivileged smoke nginx -t

* unwrap hard-wrapped prose in the installation docs

* report progress during the ownership sweep

* document EXTRA_GROUPS as the only device access path for dropped services

* expand the non-root device access docs with diagnosis steps and udev rules

* document network storage ownership and the remaining detector hardware

* skip lost+found during the ownership sweep

* hand /tmp/cache to the runtime user before services start

* make bundled models readable by the runtime user

* reload nginx by signaling the master instead of parsing its config as root

* harden root writes into unprivileged-owned paths

Restrict the sweep sentinel to a mount at or below /media/frigate so a
parent /media mount cannot bless a later-shadowed volume. Rebuild
/tmp/nginx root-owned each start so root's cp and tempio writes cannot
follow a symlink an unprivileged nginx planted in the previous run.

* collapse the duplicated sentinel comment

* add a service-runs-as-root helper for granular root services

* validate FRIGATE_ROOT_SERVICES and fail fast on unknown names

* let services listed in FRIGATE_ROOT_SERVICES skip the privilege drop

* record the root-services mode in the sentinel and sweep small trees each boot

* cache the runtime ids in the ownership helper

* chown recordings, previews, and exports to the runtime user at create

* chown the database files after init

* recommend FRIGATE_ROOT_SERVICES in the bandwidth stats warning

* assert granular root services in CI

* document FRIGATE_ROOT_SERVICES

* own every directory level created for a recording segment

* clear the cached runtime ids when ownership tests finish

* skip missing media paths in the per-boot ownership sweep

* clarify granular root services docs

* clean up

* install acl for device access grants

* grant runtime users access to mapped device nodes at boot

* assert device access grants in CI

* document automatic device access grants

* stop telling users device access needs host side setup

* clarify the non-root docs

* link the migration script to the repo

* group the manual device setup under one section

* harden against symlink attacks

/config is owned by the unprivileged runtime user after the ownership sweep, so root operations on files there could be redirected by a planted symlink.

- go2rtc HomeKit setup: replace the root yq/jq normalization and chown with an O_NOFOLLOW helper (prepare_homekit.py), so a symlink at go2rtc_homekit.yml can't redirect a root write or chown onto another file
- go2rtc binary override: ignore /config/go2rtc whenever the service runs as root, so a planted binary can't exec as root under FRIGATE_ROOT_SERVICES
- sweep sentinel: read and write it through safe-sentinel, which trusts only a root-owned regular file and never follows a symlink, so it can't be forged to skip the migration or symlinked to clobber a root file
- ownership sweep: chown with -execdir so a parent directory swapped for a symlink mid-walk can't redirect the chown out of the volume
- validate inputs: restrict DEVICE_ACL_PATHS to /dev, require nonzero numeric EXTRA_GROUPS, and reject PUID/PGID that collide with the go2rtc ids
- docs: correct the TLS key ownership note to match what actually happens

* tweak docs

* stop the ownership sweep chasing entries other mechanisms own

* keep custom binaries out of root services only under granular root
2026-08-30 08:14:43 -06:00
Josh Hawkins
bb1e556ba9 Add onboarding wizard for new installations (#24102)
* add onboarding wizard for new users

* resolve hwaccel per camera and clarify recording retention

The hwaccel step listed every preset Frigate ships, so an Intel box was offered Raspberry Pi and Rockchip decoding, and the codec specific presets (`preset-intel-qsv-h264` vs `-h265`) were offered as global values that break as soon as two cameras use different codecs. `/hardware/hwaccel` now returns the decoding families the probed hardware can actually use, each carrying a preset per codec, and the wizard resolves the family against the detect stream codec the camera wizard already probed: one global `ffmpeg.hwaccel_args` when every camera agrees, per-camera `cameras.<name>.ffmpeg.hwaccel_args` when they don't. The global stays on `auto` in that case so cameras added later still resolve at startup. A gen13+ Intel machine keeps its QuickSync recommendation with mixed h264 and h265 cameras instead of dropping to vaapi.

The recording step's "Days to retain recordings" only wrote alert and detection retention, and the storage estimate under it assumed continuous recording. It now asks what to record in plain language, writes `record.continuous.days` to match, shows the estimate only for continuous, and drops the spinner arrows on the number input.

* clean up

* add light/dark mode icon switcher

* use yml as default config file extension when not found

* i18n tweaks

* gate the setup wizard on cameras instead of a config key

* render setup wizard steps by key

* share the setup wizard e2e helpers and mock users

* add an account step to the setup wizard

* add setup wizard account step e2e coverage

* cover the account step's restart behavior

* button consistency

* fix test

* docs

* fixes
2026-08-27 20:30:36 -05:00
Josh Hawkins
194e9bef69 Recording fixes (#24072)
* pin genai review frames to the main stream

* retain previews as long as either stream has recordings

* watch sub stream recording health separately from main

* reject record_sub on the same input as record and document the role

* derive recording paths from the cache segment timestamp

Recording paths carry one second of resolution, but since sub stream recording start times are resolved to fractional wall clock, anchored to the cache file mtime and chained to the previous segment's end. A stream cutting segments faster than once a second resolves consecutive segments into the same second, so two rows collide on the unique path index and the batch insert fails. The cache segment name is unique per camera stream and second by construction because ffmpeg names segments with strftime, so the recording path is now built from that timestamp while the row keeps the resolved start time. This also restores the path semantics from before sub stream recording, when start times came straight from the cache filename.

Nothing derives times from recording paths: playback offsets, stream switching, and export all use the row's start time, which is unchanged, and the recordings sync matches files by exact path string.

* keep the rest of a recording batch when one row conflicts

* only publish record_sub status when a sub stream is configured

* don't shadow camera_cfg when publishing empty cache streams

* back off restarts when a recording stream goes stale

* give the shared sub stream grace on any capture thread reset

* include segment details in recording discard warnings
2026-08-27 20:30:35 -05:00
Josh Hawkins
dcda458a82 Container security hardening (phase 1) (#24061)
* Verify s6-overlay downloads against pinned checksums

* Verify go2rtc download against pinned checksums

The v1.9.14 release publishes no checksums file, just the bare per-platform binaries, so these digests come from a one-time fetch rather than upstream. That pins the artifact against later substitution, which is the realistic threat for a version we stay on for months, but it does not verify the original download. The stage moves from `ADD --link` to a script because `ADD --checksum` can't express an architecture-dependent URL.

* Verify main image downloads against pinned checksums

Covers everything the main image downloads on the default path: tempio, the hailort runtime tarball and wheel, the six ffmpeg builds, the libedgetpu deb, and the thirteen Intel driver debs. The hailort tarball was streamed straight into `tar`, which can't be verified before extraction, so it downloads to `/tmp` first. The three ffmpeg blocks per arch collapse into one `install_ffmpeg` helper since they only differed by URL and install dir, and the Intel debs go through a `fetch_intel_deb` helper for the same reason.

The Intel debs are the ones that mattered most here. They're installed as root with `dpkg` on the default amd64 path and had no verification at all. compute-runtime publishes a `ww<week>.sum` asset with every release and npu-driver published `checksum.sha256` on v1.19.0, so those eight digests came from upstream rather than from us. intel-graphics-compiler and level-zero publish none, so those five and everything else here come from a one-time fetch, which pins the artifact against later substitution but doesn't verify the original download. The comment above the map says which is which and how to refresh them, since npu-driver has stopped publishing sums since v1.19.0 and that provenance won't survive the next bump.

Still unpinned: `get-pip.py`, which is a rolling URL where a digest would just break the build on pypa's next edit, and the per-variant artifacts for Axera, Synaptics, and Jetson. apt repositories are out of scope since apt already verifies signatures.

* Restrict generated TLS key permissions

OpenSSL 3.x already writes the key at 600 on its own, so this pins the guarantee rather than fixing an observed leak: the mode no longer depends on the openssl version or the umask the service happens to start with. Only the generated pair is touched. User-mounted certs take the other branch and are never chmod'd, which matters when they're mounted read-only.

* Add security headers and server_tokens off

Adds `X-Content-Type-Options: nosniff` and `Referrer-Policy: strict-origin-when-cross-origin`, and turns off nginx version disclosure.

No `X-Frame-Options` and no CSP `frame-ancestors`. HA's Webpage card and iframe panels frame Frigate's own address cross-origin, and either header would break them silently with nothing in Frigate's logs to explain it. Ingress is same-origin and would survive `SAMEORIGIN`, but Frigate can't tell the two apart from inside the container. `security_headers.conf` is a plain file in the image rather than a generated one, so anyone who does want framing restrictions can bind-mount it.

`add_header` doesn't inherit into a block that declares its own, so the include goes in per block, all nine of them, including the four nested static-asset locations that serve the JS bundles. Those are the ones nosniff actually matters for.

The run script now reads `get_nginx_settings.py` once into a variable instead of shelling out per template. That script imports the frigate config machinery, which is noticeable on an SBC.

Not fixed here: `listen.conf` is included at server level and carries `Strict-Transport-Security`, so those same nine blocks already drop HSTS under TLS today. Folding it into this file would change existing TLS behavior on nine paths, so it needs its own PR.

* Restrict go2rtc config file permissions

* Log failed login attempts with source address

Failed logins returned a bare 401 and left nothing behind, so credential stuffing was invisible unless you were already watching nginx access logs. Both failure branches now log a warning with the attempted username and the client address.

The address comes from `get_remote_addr()`, the same helper the login rate limiter keys on, so the two agree on who the client is and the trusted-proxy handling is consistent. Logging a raw `x-forwarded-for` instead would let an attacker forge the source address in the very log line meant to catch them.

The response is unchanged and identical either way. Which factor failed is only visible in the log, never to the client, and the password is never logged.

* Recommend least-privilege container options in install docs

The compose generator pushed `privileged: true` into every file it produced, no matter what hardware you picked, and it's the default tab on the install page so it's what most people copy. It now emits `security_opt: no-new-privileges:true` instead, and only adds `privileged: true` for hardware that actually needs it, with the reason inline. MemryX is the only one today, since it needs to reach the max-manager. Rockchip and Synaptics only want privileged during initial setup and their documented end state is device mappings, so neither gets it.

`no-new-privileges` merges into the same `security_opt` block as any device-specific entries, so Rockchip still gets its `apparmor=unconfined` and `systempaths=unconfined` without a duplicate key.

The static example now has `privileged` commented out, and there's a short section on the options worth adding, with a note that `cap_drop: ALL` breaks `telemetry.stats.network_bandwidth` since nethogs needs NET_ADMIN/NET_RAW.

* Add amd64 container smoke test to CI

Boots the built amd64 image against a minimal config and asserts the two security headers, that the Server header no longer carries a version, that no frame-ancestors is present, that nginx accepts its own config, and the two file modes. This is also the harness the rest of the hardening work extends.

The two negative assertions are written as `if grep; then exit 1; fi` rather than `! grep`. Bash exempts a negated command from `set -e`, so the `!` form would have passed even with the version and frame-ancestors both present, which is the opposite of what a regression net is for.
2026-08-27 20:30:35 -05:00
Josh Hawkins
3ce3217db2 Add secrets.yaml and unify variable substitution sources (#24044)
* add secrets.yaml and merge substitution sources by precedence

FRIGATE_ENV_VARS was built once at import from container env and /run/secrets, and the environment_vars validator overwrote it unconditionally, so the block beat the deployment and nothing could be re-read. Sources are now separate dicts merged lowest to highest (environment_vars, secrets.yaml, container env, credentials directory), re-read at the top of every parse, and a collision warns once naming the winner. An undefined {FRIGATE_*} raises a ValueError subclass so pydantic reports the field instead of a KeyError traceback.

* use the shared substitution namespace in go2rtc config

The generator rebuilt the namespace itself from os.environ and a hardcoded /run/secrets, so it never saw environment_vars or CREDENTIALS_DIRECTORY, and str.format made any stray brace fatal. It now installs the FRIGATE_ names from environment_vars and substitutes streams the same way every other field does.

* read the exec override from an import time snapshot

environment_vars is exported into os.environ, and is_go2rtc_arbitrary_exec_allowed read os.environ live, so the config file could enable exec sources. Snapshot the variable at import, which runs before any config is loaded.

* docs

* clarify docs
2026-08-27 20:30:35 -05:00
Josh Hawkins
fec73c887e Add import/export for camera group layouts and per-camera streaming settings (#24025)
* add import/export for camera group layouts and streaming settings

Camera group layouts and per-camera streaming settings are stored in the browser's IndexedDB, so they are tied to a single browser on a single device. Users with more than one device have to rebuild every group layout and re-pick every camera's stream settings by hand, and clearing browser data loses the work.

Add a Backup & Restore card to Settings > UI Settings that exports these settings to a JSON file and imports that file on another device. Import shows a confirmation dialog with per-section counts, switches for layouts, streaming settings, and UI preferences, and warnings about camera groups or cameras in the file that are not on this server.

Server-side storage is deliberately avoided. These are per-device presentation settings: a layout arranged for a desktop is wrong on a tablet, and continuous full-resolution streams that are free on a wired LAN are not on a phone. An explicit file moves settings only when the user chooses to move them.

Implementation notes:

- web/src/utils/uiSettingsTransfer.ts owns a registry of transferable IndexedDB keys. Each entry records whether the key is user-namespaced, matching which persistence hook wrote it, plus a zod schema for its value.
- Only registry-known keys are ever written, and only when their value passes that schema. The file format deliberately lets unknown keys survive parsing, so this filter is what prevents a hand-edited file from writing arbitrary storage keys or out-of-range values.
- Export falls back to the legacy un-namespaced key, because the username migration runs lazily on first mount of each owning hook.
- Streaming settings merge per group rather than replacing the whole map, so groups configured only on the receiving device survive.
- Import writes storage and then reloads, because useUserPersistence reads a key only on mount and StreamingSettingsProvider would otherwise write its stale in-memory state back over the import.
- playbackBandwidthEstimate, frigate-search-history, and live-layout are excluded: the first two are measurements and user data rather than preferences, and live-layout's default is derived from the device.

* merge imported streaming settings per camera instead of per group
2026-08-27 20:30:35 -05:00
Nicolas Mowen
da135da0fb Implement UI for managing multiple models (#24023)
* Implement hardware detection and UI management

* Cleanup Frigate+ detection

* Don't count model as changed

* Fixes for audio map error

* Add descriptions

* Enforce that all model must exist

* Fix hardware picking

* Docs fixes

* WebUI cleanup

* Cleanup handling of scenes

* UI refinement

* Cleanup recommended UI

* test fixews
2026-08-27 20:30:35 -05:00
Nicolas Mowen
2dd700aa5a Refactor detector and model management (#23995)
* Refactor detector and model management

* Fix model resolution field
2026-08-27 20:30:35 -05:00
Ersa Oktavian Ramadan
378fbec416 Add audio labelmap grouping (#24004)
Allow audio classes to be grouped under a shared configured label.

Keep audio overrides separate from object labels and retain only the highest-scoring grouped detection.

Refs #23967
2026-08-27 20:30:35 -05:00
Josh Hawkins
91a93167d2 Show main and sub stream usage separately in Storage Metrics (#24015)
* backend

* frontend

* docs

* test

* report null instead of 0 for a stream with no cached bandwidth sample
2026-08-27 20:30:35 -05:00
Josh Hawkins
5e37b2c5c2 Refactor birdseye activity modes as a list and add alerts/detections (#24012)
* backend

* tests

* frontend and i18n

* e2e test schema

* docs
2026-08-27 20:30:35 -05:00
Josh Hawkins
5d807587ab Add sub stream recording with adaptive quality playback (#24009)
* add sub stream recording with adaptive quality playback

Optionally record a second, lower bitrate stream alongside the main
recording stream via a `record_sub` input role and `record.sub` config block, with its own retention windows.
Recordings rows now carry the stream type plus the media details needed to serve both streams from one manifest: video codec, audio presence, audio codec and rate, and a record-time keyframe index.

Playback resolves coverage across both streams and merges them into a single VOD sequence, falling back to a discontinuity manifest with per-clip init segments when the media signatures differ. The player exposes a quality selector, and an auto governor picks the stream from stall time, bandwidth, codec support, and the save-data hint.

* fix tests and i18n
2026-08-27 20:30:35 -05:00
Ersa Oktavian Ramadan
a83219af56 Refactor Birdseye activity types as composable booleans (#23940)
* Add combined motion and object Birdseye mode

Add a motion_objects mode that keeps Birdseye active when motion is detected or a confirmed tracked object is present, including stationary objects.

Wire the mode through configuration, runtime commands, API schemas, documentation, and UI labels. Exclude false-positive trackers and add regression coverage for Birdseye activation and MQTT validation.

* Refactor Birdseye activity types as booleans

Replace combination-specific Birdseye modes with composable boolean activity types for motion, active objects, stationary objects, and continuous display.

Preserve legacy single-mode configuration and MQTT inputs, support canonical comma-separated MQTT combinations, and allow scalar YAML values to be replaced by nested settings through the config API.

* Preserve OpenVINO config translations

Regenerate the configuration translations with the OpenVINO detector schema available so the unrelated production detector labels remain intact.

* Preserve partial Birdseye mode overrides

Allow an empty activity selection with a canonical NONE MQTT state so partial camera and profile overrides can disable inherited flags without failing validation.

Add regression coverage for camera and profile inheritance, document the NONE contract, and keep the generated schema fixture scoped to Birdseye.

* Address Birdseye activity review feedback

Move scalar mode compatibility into the 0.18-1 config migration and reject empty activity selections instead of publishing a NONE state.

Pass activity signals through a frozen dataclass, preserve existing active-object tracker behavior, and require confirmed stationary objects. Revert the generic YAML mutation and cover migration, inheritance, MQTT, and activation regressions.

* Move Birdseye migration to 0.19

Use the 0.19-0 configuration revision for converting scalar Birdseye modes to composable activity flags, and update the migration regression coverage accordingly.

* Remove Birdseye migration test

Drop the dedicated config migration test as requested during review while retaining the 0.19-0 migration implementation.
2026-08-27 20:30:35 -05:00
Nicolas Mowen
f486f7d57e GenAI Chat Prompt Refinements (#23864)
* Prompt refactoring and optimization

* Update spec
2026-08-27 20:30:35 -05:00
Josh Hawkins
5197881ef7
Add more vehicle types to default attribute map (#24097)
* run lpr on more vehicle types by default

before, a config change to attribute_map was required

* logging tweaks

* remove arg

* use attributes for frontend check

* docs

* only check thumbnail attributes the object can have
2026-08-26 08:23:15 -06:00
Josh Hawkins
18c77faea5
fix classification attribute access for viewers (not custom roles) (#24092) 2026-08-25 14:40:26 -05:00
Josh Hawkins
0254a11874
Docs tweaks (#24074)
* add recording validation message explanations to docs

* tweaks
2026-08-24 06:04:40 -06:00
Nicolas Mowen
ad79e666eb
API Consistency / Security Fixes (#24057)
* Make review user read status consistent with other APIs

* Validate URLs for web push endpoint

* Validate the role for a custom viewer, rate limit password changing

* Cleanup
2026-08-22 11:08:24 -05:00
Nicolas Mowen
fc79aeab5e
Fix review summary report analysis creation to be scoped for users with full camera access only (#24056)
* Fix review summary analysis

* Add ability to scope based on full camera access
2026-08-22 11:06:01 -05:00
Josh Hawkins
036bae4ea9
Return a specific 404 when starting a debug replay with no recordings in range (#24024) 2026-08-18 10:08:52 -05:00
Josh Hawkins
77fc2ce174
Miscellaneous fixes (0.18 beta) (#24016)
* fix classification drawer closing instead of scrolling when list is long on mobile

* add qwen3.8 to genai docs

* add titles to more clearly separate model types
2026-08-18 07:01:22 -06:00
Josh Hawkins
8425a76558
Miscellaneous fixes (0.18 beta) (#23993)
* subscribe to add in webpush

* add docs for detector cpu usage

* rebuild notification camera access when a camera is added at runtime

* document how frigate shows CPU usage metrics

* add faq about version key in config
2026-08-16 12:39:28 -06:00
Josh Hawkins
812e5308a3
fix notification suspend state lost on page reload (#23989)
<camera>/notifications/suspended arrives as a string over the live connection but as a number in the camera_activity snapshot, and the truthiness guard dropped the numeric 0, so a camera with notifications off rendered as active after a reload. Normalize to a string and derive isSuspended instead of storing it.
2026-08-13 16:51:44 -06:00
Josh Hawkins
fd98977506
Categorize manual events as alerts when their label is an alert label (#23981)
* Categorize manual events as alerts when their label is an alert label

* tweak docs
2026-08-13 11:16:02 -06:00
Josh Hawkins
0735a8ac75
Docs updates (#23947)
* misc docs updates

* add warning about proxies to 5000 for notifications
2026-08-10 15:54:41 -06:00
Josh Hawkins
2599795ab0
add faq to notifications docs (#23939) 2026-08-08 11:12:13 -06:00
Josh Hawkins
344efb6bc1
Miscellaneous fixes (0.18 beta) (#23934)
* add host npu requirements to docs

* allow toggling live audio transcription via mqtt

* improve spacing consistency on mobile drawers

* fix clearing the region grid not surviving a restart
2026-08-08 07:20:09 -06:00
Josh Hawkins
e73a14db5d
Miscellaneous fixes (0.18 beta) (#23898)
* update homekit docs

* update dictionary

* preserve function names in production builds

adds only 162kb gzipped/450k unzipped to the bundle

* margin tweak

* fix maximum update depth exceeded when dragging the timeline handlebar

Dragging the handlebar, especially quickly or with fast direction changes, could exceed React's nested update limit and unmount the whole app, leaving a blank screen. Motion search was worst affected.

The drag loop committed a new time into React state on every animation frame. Edge auto-scrolling mutates scrollTop each iteration, so the value always differed and React's same-value bail-out never engaged, letting the update chain run to the limit of 50. Pace those commits to one per 100ms and flush the pending value on release, so the drop position is still exact. The handlebar position and label are written to the DOM directly and remain at frame rate.

useUserInteraction dispatched state on every scroll and touchmove event; only commit on the leading edge.

Motion search also passed fresh array literals for the timeline's events, motion events and unavailable ranges, giving the segment memo and the drag effect new dependencies on every render. Both views also passed an inline arrow for onHandlebarDraggingChange, which is an effect dependency that calls setState.

* Verify motion search jobs belong to the requested camera

* Apply persisted profile and runtime overrides before workers start

Worker processes are handed a copy of the config when they start and only learn about later changes from the config_updater broadcast, which is plain ZMQ PUB/SUB with no queue, ack, or retained value, so a message published before a subscriber has connected is dropped and never re-sent. The persisted profile and the runtime camera toggles were restored only by that broadcast, at the very end of startup, so a worker that lost the race kept its yaml values for the rest of the session: audio detection kept running on a camera whose audio had been toggled off, even though /api/config, the UI, and the runtime state file all showed it disabled. Split both restores into a config half and a publish half. ProfileManager.restore_persisted_profile_to_config() and Dispatcher.reapply_runtime_state_to_config() now run right after init_profile_manager(), before the first worker starts, so every worker is handed a config that already carries both layers. ProfileManager.restore_persisted_profile() and Dispatcher.restore_runtime_state() still run at the end of startup: the recording, review, and embeddings processes start before the dispatcher exists, so the broadcast remains their only channel, and MQTT needs the retained switch states. Both config passes have to stay after init_profile_manager(), which snapshots the config as the no-profile base that deactivation resets to.

* End timeline drags on touchcancel
2026-08-05 07:40:24 -05:00
Josh Hawkins
4883e20898
Pin the internal auth port to the value nginx bound at startup (#23909)
/auth grants anonymous admin to any request whose X-Server-Port matches networking.listen.internal, but it read that port off the live config while nginx binds its listeners once at container start and never reloads them, so any path that swaps the running config could move the trusted port without nginx moving with it. Saving networking.listen.internal equal to the external port applied immediately despite the restart-required warning, which handed unauthenticated admin to everything reaching the external port. Snapshot the port at app creation and compare against that instead, and reject a config whose two listeners share a port number, which nginx would refuse to start with anyway.
2026-08-05 07:39:56 -05:00
Josh Hawkins
3b14ec0c87
Miscellaneous fixes (0.18 beta) (#23892)
* update network requirements docs for keras weights download

* fix manual PTZ relative moves permanently stopping object detection

* document available camera set features and link profiles docs to the API

* fix stale stream name field when switching cameras

The live streams and known plates fields rendered the map key as an uncontrolled input, so switching cameras left the previous camera's stream name on screen and would rename the wrong key if that stale text was committed. Both now use a shared MapKeyInput that resyncs with the form data and commits per keystroke, except while the typed name belongs to another entry, so the section is marked modified without waiting for blur.
2026-08-03 08:18:28 -05:00
Josh Hawkins
4f2a297745
remove all references to degirum in frigate (#23882)
the company ceased operations on 1 Aug 2026
2026-08-01 08:00:36 -06:00
Josh Hawkins
f1cc0e49d4
Miscellaneous fixes (0.18 beta) (#23873)
* improve display of gpu graphs in system metrics

* docs tweaks

* Only hide cameras with ui.dashboard disabled from the All Cameras dashboard

The settings camera selector and zone editor also filtered on ui.dashboard, so hiding a camera from the dashboard made its zones and masks uneditable in the UI (GH 23870). Drop those filters and correct the field title, help text, and reference docs to describe what the option actually does

* hide cameras with ui.review disabled from the Motion tab and the review summaries

The Motion tab built its own camera list that never checked ui.review, so a hidden camera still got a preview tile, and its motion and overlap queries fell back to every allowed camera. The review and recordings summaries had the same gap: they are aggregate day counts that can't be filtered client side, so a hidden camera kept contributing to the severity tab counts and calendar indicators while its items were absent from the list. Filter the motion camera list on ui.review and query all four endpoints with the visible camera list instead of letting the backend default to all, and skip the summary queries until the config resolves so the counts don't briefly render as zero.

* Scope every review page query to the cameras visible in review

The segments and the summary counts were derived from different camera sets: the list was fetched for all cameras and filtered client side, while the summaries were fetched for the visible cameras only when no explicit camera filter was set. A ?cameras= link can name a camera hidden from review, which left the count above zero with an empty list, pinning the new items to review popover open and making the auto refresh effect loop. Intersect an explicit camera selection with the visible list rather than trusting it, pass that to the segment and summary queries alike, and drop the now redundant client side filter, which the raw segments handed to the history view were bypassing anyway.
2026-07-30 17:20:41 -05:00
Josh Hawkins
860772f9f4
Miscellaneous fixes (0.18 beta) (#23828)
* widen the logger name field in the per-process log level settings

* add details to timestamp error faq

* tweak genai docs

* tweak vector language

* Combine Qwen3.5 and Qwen3.6 listings

* fix openvino yolox detector crashing on every detection

The intermediate (N, 7) array in the yolox branch shadowed the pre-allocated (20, 6) detections buffer, so writing a detection into it raised "could not broadcast input array from shape (6,) into shape (7,)" on the first frame with anything above the confidence threshold. An empty frame also returned a (0, 7) array instead of the (20, 6) buffer.

Regressed in #13794, which renamed the intermediate from dets to detections as part of a cspell cleanup. Broken since 0.15.0.

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2026-07-28 11:02:15 -06:00
Josh Hawkins
9f918362e9
Miscellaneous fixes (0.18 beta) (#23790)
* recreate review thumbnail directory before writing and log write failures

cleanup's remove_empty_directories() can rmdir an empty clips/review, after which thumbnail writes silently fail. Ensure the directory exists before both cv2.imwrite calls and check their return value

* add docs for add camera wizard

* Handle indefinite events when a segment needs to forcibly be ended for a ceamera

* update keyframe interval article link

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2026-07-24 10:08:21 -06:00
Josh Hawkins
168cbea9ea
Docs tweaks (#23787)
* docs fixes

* backend tweaks

* regenerate i18n

* tweak genai

* add config overrides section

* add common errors

* add suggestions for rebuilding a corrupt database
2026-07-22 11:13:58 -05:00
Josh Hawkins
c0cf08ab4a
Miscellaneous fixes (0.18 beta) (#23763) 2026-07-21 06:44:33 -06:00
Josh Hawkins
6f80bcd19f
Miscellaneous fixes (0.18 beta) (#23755)
* resolve saved credential sentinel to the stored api_key in the GenAI probe

* add profile faq

* center the multi-camera export time range on the current playback position

* add faq about preview restart cache

* clarify exports bulk download
2026-07-18 11:19:37 -06:00
Josh Hawkins
d02a1156b7
Miscellaneous fixes (0.18 beta) (#23736)
* Catch faces that become empty after cropping

* don't drop batched camera add/remove config updates

TrackedObjectProcessor drained all pending camera config updates at once but handled them in a mutually exclusive if/elif on enabled/add/remove, so only one topic was processed per drain. When an add arrived in the same batch as an enabled update, the add was skipped and the new camera never got a camera state. Adding a camera reliably produced that batch: config_set now re-applies runtime overrides, which republishes an enabled update for every previously toggled camera immediately before the add, in the same request. The dashboard and camera capture still saw the camera (the maintainer does not subscribe to enabled, so it got a clean add-only batch), but object_processing did not, and disabling the camera then crashed with a KeyError on the unguarded camera_states lookup.

Handle add and remove independently instead of as exclusive branches so a batched add is no longer dropped, and guard the remove lookup so a missing state is skipped rather than raising. Drop the enabled branch entirely: it only ever set prev_enabled when it was None, but prev_enabled is seeded to a bool at camera state creation and is never None (mypy flags the body as unreachable), and the actual enable/disable transition is already driven by the disabled-state loop from config.enabled.

* Don't stay on motion search page when user cancels flow

* fix notification test button being blocked by websocket auth

* fix overflowing model names in settings genai widget

* add note about auth debugging

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2026-07-17 08:00:15 -06:00
Josh Hawkins
c406a93d3d
Miscellaneous fixes (0.18 beta) (#23725) 2026-07-15 18:49:05 -06:00
Nicolas Mowen
775ce22204
Miscellaneous Fixes (#23709) 2026-07-13 19:55:00 -08:00
Josh Hawkins
fcd05ec7bc
UI improvements and fixes (#23690)
* add ability to edit enabled and save_attempts for classification models in the UI

* add state motion and interval configs to edit dialog

* fix preview playback rate for motion previews

* add docs note about environment vars and go2rtc

* update live view faq
2026-07-13 06:30:15 -06:00
Josh Hawkins
da4037eb52
UI tweaks (#23679)
* lock saved GenAI provider keys and add labels/validation to config map-key fields

* fix docs
2026-07-11 16:30:40 -06:00
Martin Weinelt
f3c09ae169
Typo fixes (#23669)
* Fix typos

With help from https://github.com/crate-ci/typos

* Fix repeated article "the"

* Fix repeated "changed"
2026-07-10 08:10:13 -05:00
Josh Hawkins
f6596ac7b0
Miscellaneous fixes (#23661)
* update face recognition docs

* clarify

* improve faq grouping

* add faqitem component

* add enable http link for reolinks

* update plus docs

* update autotracking faq

* fix typos
2026-07-10 07:09:15 -06:00
Josh Hawkins
20c2be4368
Template tweaks (#23659)
* template tweaks

* change home assistant add-on to app

* add proxmox via vm
2026-07-08 13:20:43 -06:00
Josh Hawkins
8b72c7aa1f
bump go2rtc to 1.9.14 (#23657) 2026-07-08 12:09:31 -05:00
Josh Hawkins
e6cac50250
Miscellaneous fixes (#23651) 2026-07-08 08:27:38 -05:00
Josh Hawkins
c99d6b0dcf
Miscellaneous fixes (#23648)
* sort preview cameras in history by ui order

* sort cameras by UI order in various components for consistent display

* add no recordings faq

* fix link

* recording cache faq

* add link

* improve anchor naming in object detector docs

rather than #configuration-1, #configuration-2, etc

* use yaml instead of json for object detector docs

* fix anchor
2026-07-07 10:56:43 -06:00
Josh Hawkins
455b8687e8
Tweaks (#23638)
* docs tweaks

* show reolink warning when using probe path in camera wizard

* note ffmpeg 8 default

* update links

* add faq about false positives

* tweak plus language

* Recommend OpenVINO uses YOLOv9 by default

* add mse/rtc live view faq

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
2026-07-06 09:28:12 -06:00