Architecting UniFi Protect via Docker: A Comprehensive Implementation Guide for ARM64 and x86_64 Hardware

The deployment of UniFi Protect within a Dockerized environment represents a sophisticated approach to decoupling Ubiquiti's proprietary surveillance software from its native hardware constraints. While UniFi Protect is traditionally bundled with specific hardware such as the Cloud Key Gen2 or the UniFi Next-Generation Video Recorder (UNVR), the utilization of containerization allows system administrators and enthusiasts to leverage existing server hardware, specifically ARM64 architectures like the Raspberry Pi or standard x86_64 Linux servers. This architectural shift enables greater flexibility in storage management, hardware resource allocation, and integration with broader home automation ecosystems. However, transitioning a system designed for a proprietary appliance into a portable container introduces significant technical complexities, ranging from kernel-level cgroup requirements to strict network interface dependencies and storage permission hurdles. Achieving a stable installation requires a precise sequence of configuration steps to prevent the software from triggering automatic updates that can destabilize the containerized environment.

Hardware Requirements and Resource Allocation

The operational stability of UniFi Protect is heavily dependent on the underlying hardware resources. Because the software is designed to process high-bandwidth video streams and manage complex databases, it possesses a high baseline for system memory.

  • RAM Requirements: Protect requires at least 4 GB of RAM in order to boot and run correctly.

The technical necessity for 4 GB of RAM stems from the memory-intensive nature of the UniFi Core and the Protect application, which must handle simultaneous video recording, indexing, and playback. In an ARM64 environment, such as a Raspberry Pi 4 Model B, this requirement is critical. If the system is under-provisioned, the container may enter a crash loop or fail to initialize the database, leading to an incomplete boot sequence.

The impact on the user is a strict hardware limitation; users attempting to run this on devices with 2 GB of RAM will likely face catastrophic failure during the boot process. Consequently, it is recommended to run Protect as a standalone service without other competing containers when operating on limited hardware. This ensures that the CPU and RAM are dedicated entirely to the video pipeline, preventing frame drops or system instability.

Deployment Strategies for ARM64 Architectures

Implementing UniFi Protect on ARM64 hardware requires a strategic approach to image acquisition and system configuration. There are several community-driven paths to achieve this, most notably through the projects maintained by dciancu and markdegroot.

The dciancu Implementation Path

This method focuses on mimicking the UNVR hardware environment. A critical aspect of this deployment is the build process, as prebuilt images are not provided.

  • Build Process: Users must build the image using the provided build.sh script or the Dockerfile.

The technical requirement to build from source ensures that the image is optimized for the specific ARM64 variant being used. For those utilizing macOS, a specific configuration file named docker-compose.macos.yml is provided to handle the architectural differences between Linux and macOS Docker engines.

The markdegroot Implementation Path

This approach provides a more direct execution path via Docker Hub, specifically utilizing the markdegroot/unifi-protect-arm64 image.

  • Daemon Execution: The container is typically run as a daemon using the following command:

bash docker run -d --name unifi-protect \ --privileged \ --tmpfs /run \ --tmpfs /run/lock \ --tmpfs /tmp \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -v /storage/srv:/srv \ -v /storage/data:/data \ -v /storage/persistent:/persistent \ --network host \ -e STORAGE_DISK=/dev/sda1 \ markdegroot/unifi-protect-arm64

This specific command string employs several advanced Docker flags:
- --privileged: Grants the container root access to the host, which is necessary for managing hardware disks and network interfaces.
- --tmpfs: Mounts temporary filesystems in RAM for /run, /run/lock, and /tmp to reduce disk I/O and increase performance.
- -v /sys/fs/cgroup:/sys/fs/cgroup:ro: Maps the host's control groups in read-only mode, which is essential for systemd to operate inside the container.
- --network host: Bypasses the Docker bridge and allows the container to use the host's network stack directly.

Storage Management and Persistence

UniFi Protect is a data-heavy application. The most common point of failure in these installations is incorrect volume mapping or insufficient disk space.

Storage Capacity Requirements

Protect will fail to start if there is not at least 100 GB of disk space available. This is a hard-coded check within the software to ensure that the system does not crash immediately upon filling a small partition.

  • Implementation Detail: Users must ensure that Docker volumes are mapped to a physical disk with sufficient capacity (e.g., /storage in the markdegroot configuration).
  • Disk Usage Tracking: The environment variable STORAGE_DISK can be updated (e.g., -e STORAGE_DISK=/dev/sda1) to allow the UniFi Protect interface to accurately report disk usage statistics.

Volume Mapping and Permissions

A critical distinction exists between mapping a host directory and using a Docker volume. In x86_64 deployments, such as those by iamjamestl, it is explicitly warned not to simply map a host directory into the container.

  • Technical Reason: Docker may not initialize a simple host-mapped directory with the correct permissions, which frequently results in UniFi Protect lacking the necessary write permissions to save configurations or recordings.
  • Recommended Action: Use the docker volume create command to initialize managed volumes.

For x86_64 systems, the following volume creation sequence is required:

bash docker volume create unifi-protect docker volume create unifi-protect-postgresql

These volumes are typically accessible on the host at /var/lib/docker/volumes/unifi-protect/_data. If bulk video data needs to be stored on an external large-capacity device, a bind-mount volume should be created:

bash docker volume create -o type=none -o o=bind -o device=/path/to/some/empty/dir unifi-protect

Network Configuration and Connectivity

Network setup is the most complex variable in a UniFi Protect Docker deployment, as the software expects to be on a primary network interface to communicate with the Ubiquiti cloud and cameras.

Macvlan Configuration for x86_64

For users who do not wish to use host networking, a macvlan network is the preferred method to give the container its own IP address on the local network.

  • Network Creation: If the video network is on VLAN 100 with subnet 192.168.100.0/24 and the host interface is eth0, the network is created as follows:

bash docker network create \ --driver macvlan \ --subnet 192.168.100.0/24 \ --gateway 192.168.100.1 \ --opt parent=eth0.100 \ video

The container is then launched with this network and a specific IP:

bash docker run \ --name unifi-protect \ --net video \ --ip 192.168.100.2 \ -v unifi-protect:/srv/unifi-protect \ -v unifi-protect-postgresql:/var/lib/postgresql \ --tmpfs /tmp \ iamjamestl/unifi-protect

STUN and Firewall Considerations

UniFi Protect utilizes STUN (Session Traversal Utilities for NAT) to establish connections through firewalls. This is essential for remote access.

  • Technical Conflict: Firewalls like pfSense may break STUN by altering UDP ports during the NAT process.
  • Solution: Create a static port rule for the UniFi Protect container to ensure the UDP ports remain consistent, allowing the STUN "hole punching" to succeed.

The Remote Access Interface Constraint

A known limitation in the ARM64 builds is the requirement for specific network interface naming for cloud connectivity. Remote access via the Ubnt cloud will not function unless the primary network interface is named enp0s2. If the interface is named differently, the container can operate locally, but the cloud-based remote management will fail.

Initial Setup and Stability Precautions

The first boot of a UniFi Protect container is the most volatile phase. If not handled correctly, the software may attempt to update itself, which often leads to the corruption of the containerized environment.

The "Offline Setup" Protocol

To prevent the container from breaking during the initial boot, the following sequence must be followed:

  1. Disconnect the Docker host from the internet.
  2. Start the container and navigate to the host IP (e.g., http://<host-ip>:7080/).
  3. Complete the initial console setup in "offline mode".
  4. Navigate to the console settings and explicitly disable the "auto update" feature for both the console and the applications.
  5. Reconnect the internet.

Failure to follow this protocol often results in the container attempting to fetch an update from Ubiquiti servers that is incompatible with the Docker wrapper, leading to a boot failure.

Resolving "Device Updating" Loops

Following the initial setup, some users may encounter a blue loading bar with the message "Device Updating". This is a common glitch during the first-time initialization.

  • Resolution: Execute the following command inside the container:

bash systemctl restart unifi-core

Alternatively, restarting the entire container will resolve the state and allow the UI to load properly.

Advanced Troubleshooting and System Diagnostics

When the container fails to start or behaves erratically, administrators must dive into the logs and kernel parameters.

Systemd and Cgroup Errors

A frequent error encountered during the boot of the container is:
Failed to create /init.scope control group: Read-only file system
Failed to allocate manager object: Read-only file system

This occurs because systemd requires specific access to the cgroup hierarchy of the host. To resolve this, the host system must be booted with the following kernel parameter:

systemd.unified_cgroup_hierarchy=0

Log Analysis

Depending on the build used, logs are located in different paths.

  • General Container Logs: Use docker compose logs -f or check /var/log inside the container.
  • Systemd Logs: Run journalctl -f inside the container.
  • UniFi Protect Specific Logs: Located at /srv/unifi-protect/logs.
  • UniFi Core Logs: Located at /data/unifi-core/logs.
  • Storage Debugging: If the DEBUG_STORAGE variable is enabled, logs are output to /var/log/storage_disk_debug.log.

Integration with Third-Party Cameras

A significant evolution in UniFi Protect (version 5.0 and later) is the introduction of support for third-party cameras via the ONVIF protocol. This expands the ecosystem beyond Ubiquiti-branded hardware.

The UniFi Cam Proxy Method

For those using older versions of Protect or seeking more advanced integration, the unifi-cam-proxy (developed by keshavdv) allows non-UniFi cameras, such as those from Reolink or Nanit, to be brought into the UniFi Protect interface.

  • Functionality: The proxy acts as a translator, making a third-party RTSP/ONVIF stream appear as a native UniFi camera.
  • Compatibility Note: Some users have reported that this proxy is broken on the most recent versions of Protect. However, switching to the "dev branch" of the proxy has been reported to resolve these issues.
  • Specific Integration: Integrating Nanit cameras may require an intermediate layer like Scrypted to handle authentication before the proxy can ingest the stream.

Comparison of Deployment Methods

The following table summarizes the different available paths for deploying UniFi Protect in Docker.

Feature dciancu (ARM64) markdegroot (ARM64) iamjamestl (x86_64)
Architecture ARM64 ARM64 x86_64
Image Source Build from source Docker Hub Docker Hub
Networking Bridge/MACVLAN Host Network MACVLAN
Key Requirement 4GB RAM 100GB+ Disk Docker Volume
Focus UNVR Mimicry Ease of Deployment Generic Linux Host
Remote Access Requires enp0s2 Requires enp0s2 STUN Port Rules

Conclusion

Deploying UniFi Protect via Docker is a high-reward but high-complexity undertaking. The transition from a dedicated hardware appliance to a containerized service requires meticulous attention to the Linux kernel's cgroup management and the specific network interface naming conventions required by Ubiquiti's cloud services. By adhering to the "Offline Setup" protocol and ensuring that the 4 GB RAM and 100 GB storage thresholds are met, users can create a powerful, flexible surveillance hub. The ability to integrate non-UniFi cameras via ONVIF or specialized proxies like unifi-cam-proxy further enhances the system, transforming it from a closed ecosystem into an open, interoperable security platform. The success of the installation ultimately relies on the ability to manipulate the host environment to satisfy the proprietary expectations of the Protect software, specifically regarding privileged access and network transparency.

Sources

  1. dciancu/unifi-protect-unvr-docker-arm64
  2. iamjamestl/unifi-protect
  3. markdegrootnl/unifi-protect-arm64
  4. Home Assistant Community - UniFi Cam Proxy
  5. Docker Hub - markdegroot/unifi-protect-arm64

Related Posts