Running UniFi OS Server in Docker
Update (July 2026): we open-sourced this. Everything described in this post is now packaged as unihosted/unifi-os-server-docker — a prebuilt Docker image with a ready-to-run compose file, built by a fully transparent GitHub Actions pipeline. Skip to the Quick Start below to get UniFi OS Server running with a single docker compose up -d.
UniFi OS Server is Ubiquiti's network management platform that orchestrates UniFi Network, UniFi Identity, and other services. Ubiquiti only ships it as an OCI image embedded inside a proprietary installer designed for Podman — you can't simply pull it from a registry.
At Unihosted we were already running everything else in Docker, so we extracted that image and repackaged it to run cleanly under Docker. This post covers both the quick way (our open-source image) and the full technical journey of how we got there.
Quick Start
Save the compose below as docker-compose.yaml, set UOS_SYSTEM_IP to your public IP, and run docker compose up -d. The Web UI will be at https://localhost:11443 once the container is ready. Every port and environment variable is documented inline — the compose is the reference.
services:
unifi-os-server:
container_name: unifi-os-server
image: ghcr.io/unihosted/unifi-os-server-docker:latest
cgroup: host
restart: unless-stopped
cap_add:
- NET_RAW
- NET_ADMIN
ports:
- "8080:8080" # HTTP inform / redirect
- "8443:8443" # UniFi Controller API
- "8444:8444" # Secure Portal for Hotspot
- "8880-8882:8880-8882" # Hotspot portal redirection (HTTP)
- "10003:10003/udp" # UniFi discovery (Only needed on local network)
- "11443:443" # UniFi Web UI (HTTPS)
- "3478:3478/udp" # STUN used for device poking
- "5514:5514/udp" # Syslog
- "6789:6789" # Speed test
# Network App bypass — skips UOS SSO, direct access to the controller
# API on 127.0.0.1:8081. Bind to localhost ONLY; never expose publicly.
- "127.0.0.1:7443:7443"
- "127.0.0.1:5432:5432" # PostgreSQL (localhost only)
extra_hosts:
- "host.docker.internal:host-gateway"
- "host.containers.internal:host-gateway"
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
- ./docker/uos:/var/lib/uosserver
- ./docker/uos:/var/lib/unifi
- ./docker/data/:/data
tmpfs:
- /run:exec
- /run/lock
- /tmp:exec
- /var/lib/journal
- /var/opt/unifi/tmp:size=64m
- /data/unifi-core/config/http
networks:
- unifi-os-server-network
depends_on:
- unifi-os-server-mongodb
environment:
TZ: Europe/Amsterdam
UOS_SYSTEM_IP: "127.0.0.1"
# SSO bypass for the Network App (port 7443). Used by UniHosted for
# debugging and direct API access. NOT for production — the port is
# bound to localhost above and must stay that way.
EXPOSE_NETWORK_APP: "true"
MONGO_INTERNAL: "false" # Defaults to false → uses the external MongoDB service below.
# Set to "true" and remove the unifi-network-mongodb service + depends_on
# to let the UniFi Network App run its own mongod (port 27117).
unifi-os-server-mongodb:
container_name: unifi-os-server-mongodb
image: mongo:4.4
networks:
- unifi-os-server-network
volumes:
- ./docker/mongodb:/data/db
networks:
unifi-os-server-network:
A few things worth knowing:
- MongoDB runs as a separate service by default. The internal mongod is disabled by default; set
MONGO_INTERNAL: "true"(and drop the MongoDB service) if you prefer the bundled one (port 27117). - No full privileged mode. The container runs with scoped capabilities (
NET_RAW,NET_ADMIN) plus host cgroup access for systemd, instead ofprivileged: true. - The Network App bypass ports must stay bound to localhost. They skip UOS SSO and exist for debugging and direct API access.
The image, entrypoint, and the entire build pipeline live in the GitHub repository. If you'd rather use Ubiquiti's official Podman-based installer instead, see our UniFi OS Server download links post.
The rest of this post is the technical journey: how the image is extracted from Ubiquiti's installer and what it took to make it run under Docker.
The Challenge
UniFi OS Server comes packaged as a binary installer that embeds a container image. The installer is designed for Podman, not Docker, and the image format is OCI (Open Container Initiative) rather than Docker's native format. Additionally, UniFi OS Server has several unique requirements:
- Systemd dependency: The platform relies on systemd for service management
- Elevated network access: Requires extra capabilities for network configuration
- Complex initialization: Multiple services need proper initialization and configuration
- Persistent state: Extensive data directories that must survive container restarts
Step 1: Extracting the Base Image
The first challenge was extracting the container image from Ubiquiti's installer binary. The installer (e.g. unifi-os-server-download-506-x64) contains an embedded archive that we needed to extract.
Using Binwalk for Extraction
We used binwalk, a firmware analysis tool, to extract the embedded filesystem from the installer:
binwalk --run-as=root -e unifi-os-server-download-506-x64
This extracts the contents to a directory (typically _unifi-os-server-download-506-x64.extracted/), revealing the embedded image.tar file containing the OCI-formatted container image.
Step 2: Converting OCI to Docker Format
The extracted image is in OCI format, which Docker can't directly load. We needed to convert it to Docker's format. While Docker and Podman share compatibility, the image format needed explicit conversion.
Podman as a Conversion Tool
Podman can handle both OCI and Docker formats, making it the perfect tool for conversion:
# Load the OCI image into Podman
podman load -i image.tar
# Save it in Docker format
podman save --format docker-archive -o uosserver-0.0.54-docker.tar <image-name>
This creates a Docker-compatible image that can be loaded with docker load.
Step 3: Building the Docker Image
With the base image converted, we created a Dockerfile that extends it and adds our customizations:
FROM uosserver:0.0.54
ENV UOS_SERVER_VERSION="5.0.6"
ENV FIRMWARE_PLATFORM="linux-x64"
STOPSIGNAL SIGRTMIN+3
Key points:
- STOPSIGNAL SIGRTMIN+3: This is systemd's shutdown signal, required for graceful service shutdown
- Environment variables: Set the version and platform that UniFi OS Server expects
Step 4: From Manual Steps to an Automated Pipeline
Everything above started as manual work. Today it runs as a transparent GitHub Actions pipeline: the workflow downloads the official Ubiquiti installer, extracts the embedded OCI image, flattens its layers into a rootfs Docker can consume, and layers our own entrypoint on top. Nothing happens behind a curtain — you can inspect exactly what goes into the image at every step.
At runtime, the entrypoint configures MongoDB, wires up networking (a macvlan eth0 alias), exposes PostgreSQL, and hands off to systemd.
Key Configuration Points
Capabilities instead of privileged mode: Earlier iterations ran with privileged: true. The published image instead uses scoped capabilities (NET_RAW, NET_ADMIN) together with host cgroup access (cgroup: host and /sys/fs/cgroup mounted read-write) so systemd can function — a smaller attack surface than full privileged mode.
Volume Mounts: Persistence is required for /var/lib/uosserver and /var/lib/unifi (UniFi OS Server and Network configuration) and /data (application data for all services), plus a separate volume for MongoDB's data directory.
Port Mappings: UniFi OS Server exposes many ports — 443 for the web UI, 8080 for device inform, 8443 for the controller API, 3478/udp for STUN, plus hotspot portal, syslog, discovery, and speed-test ports. The Quick Start compose documents each one inline.
Architecture Insights
UniFi OS Server is a complex microservices architecture running multiple components:
- UniFi Core: The core management service
- UniFi Identity (UID): User identity and authentication
- UniFi Link Platform (ULP): Service orchestration
- UniFi Directory: Directory services
- UCS Agent: Cloud services agent
- MongoDB: Primary database
- RabbitMQ: Message broker
- PostgreSQL: Additional database backend
- Nginx: Reverse proxy and web server
All these services are managed by systemd within the container, which is why the container needs host cgroup access and systemd-aware configuration.
Challenges and Solutions
Challenge 1: Systemd in Docker
Problem: Docker containers don't run systemd by default, but UniFi OS Server requires it.
Solution: Run /sbin/init as PID 1 with host cgroup access (cgroup: host, /sys/fs/cgroup mounted read-write) and tmpfs mounts for /run and /tmp, so systemd can manage its services without full privileged mode.
Challenge 2: Network Interface Expectations
Problem: UniFi OS Server expects eth0 to exist, but Docker creates differently named interfaces.
Solution: Create a macvlan interface alias to eth0 in the container startup configuration — this is why the container needs the NET_ADMIN capability.
Challenge 3: Persistent UUID
Problem: UniFi OS Server generates a UUID on first boot and expects it to persist.
Solution: Store the UUID in a persistent volume (/data/uos_uuid) and read it on subsequent starts.
Production Considerations
Security
The container needs elevated network capabilities and host cgroup access. Consider:
- Keep the Network App bypass ports (7443, 5432) bound to localhost only
- Network isolation and firewall rules in front of the exposed ports
- Regular image updates
- Monitoring and logging
Resource Requirements
UniFi OS Server is resource-intensive:
- CPU: Multi-core recommended
- Memory: At least 4GB, 8GB+ for production
- Storage: Significant space needed for logs, databases, and firmware
Backup Strategy
Critical data to back up:
/var/lib/unifiand/var/lib/uosserver: UniFi configuration- MongoDB's data directory
/data: All service data
Updates
When Ubiquiti releases a new UniFi OS Server version, the build pipeline extracts and repackages it — updating means pulling the new image tag and recreating the container. As with any controller upgrade: back up first, and test in a non-production environment before rolling it out to infrastructure that manages real devices.
Conclusion
Running UniFi OS Server in Docker required solving several technical challenges: extracting the embedded image, converting formats, handling systemd, and managing complex initialization. The result is a containerized UniFi OS Server that can be deployed, scaled, and managed like any other Docker service — and it's now open source at unihosted/unifi-os-server-docker. Issues and pull requests are welcome; if it saves you a parallel Podman setup, a star helps others find it.
This approach is what enables us at Unihosted to provide UniFi OS Server as a managed service, with all the benefits of containerization: portability, version control, easy deployment, and infrastructure as code.
Don't want to run this yourself? Unihosted offers fully managed, hosted UniFi OS Server — no Docker, no binwalk, no systemd wrangling required. Get started with Unihosted and have your UniFi OS Server running in minutes.