1b35702b1b
Co-authored-by: Joachim Friberg <joachim.friberg@ip-solutions.se> Reviewed-on: phirna/zima-apps#6
143 lines
5.1 KiB
Markdown
143 lines
5.1 KiB
Markdown
# 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. |