- Apps/snacks/: docker-compose.yaml (2.3.1, host networking, privileged, /dev/dri) and README.md with full security exception documentation for: network_mode:host, privileged:true, device mount /dev/dri - apps.md: converted to agent-readable table backlog with instructions for future apps - Jellyfin-ffmpeg paths as defaults, 1G memory reservation, amd64 only (single-arch image) - Validation: ./scripts/validate-appstore.sh passes
5.1 KiB
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 athttp://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: truenetwork_mode: host- Device mount:
/dev/dri:/dev/dri
Motivering:
no-new-privileges:trueochcap_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:trueprevents 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
videoorrendergroup. - ZimaOS does not reliably provide these groups in the container runtime context, making
privileged: truethe only reliable way to grant device access.
Alternativ som utvärderats:
security_opt: ["apparmor:..."]with specific/dev/driaccess: 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/dridevice 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: truecombined withcap_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.