# Snacks Automated video library encoder with hardware acceleration (NVENC, QSV, VAAPI, AMF). ## Purpose Snacks batch-transcodes video libraries using FFmpeg with hardware acceleration. It monitors directories, skips already-encoded files, retries with fallbacks, and supports distributed cluster encoding across multiple ZimaOS nodes. ## Port - `6767/tcp` — Web UI at `http://localhost:6767` ## Volumes | Host path | Container path | Description | |---|---|---| | `/DATA/AppData/$AppID/media` | `/app/work/uploads` | Media library — source files to encode | | `/DATA/AppData/$AppID/logs` | `/app/work/logs` | Transcoding logs | | `/DATA/AppData/$AppID/config` | `/app/work/config` | Settings and SQLite database | ## Hardware Acceleration Snacks uses GPU encoding via `/dev/dri`: | Driver | Codecs | Devices | |---|---|---| | VAAPI (Linux) | H.265, H.264 | Intel iHD/i965, AMD VAAPI | | QSV (Intel) | H.265, H.264 | Intel Quick Sync Video | | NVENC (NVIDIA) | H.265, H.264 | NVIDIA GPUs via CUDA | | AMF (AMD) | H.265, H.264 | AMD GPUs | Auto-detection runs on first encode and picks the best available encoder. ## Cluster Mode Snacks supports distributed encoding across multiple ZimaOS nodes. - Nodes discover each other via UDP broadcast on the LAN - One instance acts as coordinator; others are workers - Jobs are assigned automatically; failed nodes are re-assigned - A shared secret authenticates intra-cluster communication **UDP broadcast requirement**: Cluster mode requires `network_mode: host` — bridge mode blocks LAN broadcast discovery, making nodes invisible to each other. ## Health Check `http://localhost:6767/Home/Health` — returns HTTP 200 when the backend is ready. ## Privilegier och säkerhet Aktiva säkerhetsinställningar i denna app: - `security_opt: ["no-new-privileges:true"]` - `cap_drop: ["ALL"]` - `privileged: true` - `network_mode: host` - Device mount: `/dev/dri:/dev/dri` Motivering: - `no-new-privileges:true` och `cap_drop: ["ALL"]` kompenserar med lägsta möjliga capability-yta. - Isolerad data-path under `/DATA/AppData/$AppID/...`. ## Säkerhetsavvikelser ### 1. `network_mode: host` **Varför det behövs:** - Snacks cluster nodes discover each other via UDP broadcast on the local network. - Bridge mode only forwards unicast traffic; broadcast packets never reach other nodes. - Without host networking, cluster mode is non-functional. **Alternativ som utvärderats:** - Bridge mode with port exposure: broadcasts are not forwarded by the Docker bridge. - Static IP configuration: requires manual node addressing and is error-prone. - Multicast DNS (mDNS): not supported by Docker bridge in all deployments. **Risker:** - Container has full access to all host ports. - No network isolation between Snacks and other services on the host. - If the container is compromised, the attacker has host network access. **Riskreducering:** - `cap_drop: ["ALL"]` minimizes syscall surface. - `no-new-privileges:true` prevents privilege escalation. - No sensitive host directories are mounted beyond the app-specific volumes. --- ### 2. `privileged: true` **Varför det behävs:** - `/dev/dri` (Direct Rendering Infrastructure) is required for VAAPI/QSV hardware acceleration. - On standard Linux, this device is accessible without privileged mode if the user is in the `video` or `render` group. - ZimaOS does not reliably provide these groups in the container runtime context, making `privileged: true` the only reliable way to grant device access. **Alternativ som utvärderats:** - `security_opt: ["apparmor:..."]` with specific `/dev/dri` access: not reliably portable across ZimaOS kernel configurations. - Pre-create device nodes with specific permissions: does not work dynamically when the device appears. - Skip hardware acceleration (software encoding only): defeats the primary purpose of the app. **Risker:** - Container has full root capabilities on the host. - If container is compromised, attacker has theoretical access to all host resources. - Hardware acceleration devices can be accessed directly. **Riskreducering:** - `cap_drop: ["ALL"]` drops all capabilities even when privileged. - Only the specific `/dev/dri` device is mounted; no other host devices. - Data volumes are scoped to `/DATA/AppData/$AppID/...`. --- ### 3. Device mount: `/dev/dri:/dev/dri` **Varför det behövs:** - VAAPI and QSV hardware encoding require direct access to the GPU render nodes in `/dev/dri`. - Without this mount, FFmpeg falls back to software encoding which is 10–50x slower on 4K content. **Alternativ som utvärderats:** - Specific device nodes (e.g., `/dev/dri/renderD128`): device names can vary by driver version and host kernel. - No hardware acceleration: software fallback is too slow for practical use. **Risker:** - The container can enumerate and use all graphics devices on the host. - On multi-user systems, other users' GPU resources may be accessible. **Riskreducering:** - `privileged: true` combined with `cap_drop: ["ALL"]` ensures the container cannot load additional kernel modules or escalate privileges. - Only the render nodes are exposed; no other host devices are passed through.