diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de01fcdd37..9c072417f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -301,7 +301,7 @@ jobs: # /run must allow exec: S6_READ_ONLY_ROOT has s6 copy its service # scripts there and run them, and --tmpfs defaults to noexec docker run -d --name frigate-ro --shm-size 256m \ - --read-only --tmpfs /tmp:rw,size=1g --tmpfs /run:exec,mode=0755 \ + --read-only --tmpfs /tmp:rw,size=1g --tmpfs /run:exec,nosuid,nodev,mode=0755 \ --user 1000:1000 \ --security-opt no-new-privileges:true \ -v /tmp/frigate-config-ro:/config \ @@ -331,7 +331,7 @@ jobs: - name: Assert PUID with read-only fails fast with clear error run: | docker run -d --name frigate-ro-puid --shm-size 256m \ - --read-only --tmpfs /tmp:rw,size=1g --tmpfs /run:exec,mode=0755 \ + --read-only --tmpfs /tmp:rw,size=1g --tmpfs /run:exec,nosuid,nodev,mode=0755 \ -e PUID=1500 -e PGID=1500 \ -v /tmp/frigate-config-ro:/config \ ${{ steps.setup.outputs.image-name }}-amd64 @@ -347,7 +347,7 @@ jobs: - name: Assert EXTRA_GROUPS with read-only fails fast with clear error run: | docker run -d --name frigate-ro-groups --shm-size 256m \ - --read-only --tmpfs /tmp:rw,size=1g --tmpfs /run:exec,mode=0755 \ + --read-only --tmpfs /tmp:rw,size=1g --tmpfs /run:exec,nosuid,nodev,mode=0755 \ -e EXTRA_GROUPS=44 \ -v /tmp/frigate-config-ro:/config \ -v /tmp/frigate-media-ro:/media/frigate \ diff --git a/docs/docs/configuration/non_root.md b/docs/docs/configuration/non_root.md index b1053a7746..0d0ba2c47f 100644 --- a/docs/docs/configuration/non_root.md +++ b/docs/docs/configuration/non_root.md @@ -291,7 +291,7 @@ services: tmpfs: - /tmp:size=256m - /tmp/cache:size=1000000000 # recording segments, sized as before - - /run:exec,mode=0755,size=16m + - /run:exec,nosuid,nodev,mode=0755,size=16m ports: - "8971:8971" - "8554:8554" # RTSP feeds @@ -299,7 +299,7 @@ services: - "8555:8555/udp" # WebRTC over udp ``` -`/run` has to allow `exec`. With a read-only root filesystem s6 copies its service scripts into `/run` and runs them from there, and tmpfs mounts default to `noexec`. The equivalent for `docker run` is `--tmpfs /run:exec,mode=0755`. +`/run` has to allow `exec`. With a read-only root filesystem s6 copies its service scripts into `/run` and runs them from there, and tmpfs mounts default to `noexec`. The equivalent for `docker run` is `--tmpfs /run:exec,nosuid,nodev,mode=0755`. Spelling out `nosuid` and `nodev` matters: passing any tmpfs options replaces Docker's defaults instead of adjusting them, so asking for `exec` alone would drop those two as well. Size `/tmp` deliberately. It now carries nginx's config copy and its five proxy temp directories as well as the recording cache. Keeping `/tmp/cache` as its own nested tmpfs, as above, leaves your existing [cache sizing](/frigate/installation#storage) untouched and adds a small allowance for nginx. If you'd rather use one tmpfs over all of `/tmp`, size it as your cache budget plus roughly 50MB, or recordings begin failing once the cache fills.