How to Run Unifi Network Application via LinuxServer.io’s Docker Image

The LinuxServer.io organization is deprecating their Unifi Controller image for maintenance reasons as we head into 2024. The organization is now recommending its new Unifi Network Application image instead of the prior image. Below, I’ll describe how I setup the new container and how I migrated from the old one.

Unifi logo.
Image credit : Ubiquiti

This is my sixteenth post documenting images I use at home. You can also read about how I run the legacy Unifi controller, how I run Plex, how I update DuckDNS, how I run Duplicacy, how I run Heimdall, how I run Librespeed, how I run Home Assistant, how I run NetBox, how I run Scrutiny, how I run OpenVSCode Server, how I run QDirStat, how I run WireGuard, how I run Z-Wave JS UI, how I run netboot.xyz, and how I run Scrypted.

About LinuxServer.io

LinuxServer.io describes their organization as:

A group of like-minded enthusiasts from across the world who build and maintain the largest collection of Docker images on the web. At our core are the principles behind Free and Open Source Software. Our primary goal is to provide easy-to-use and streamlined Docker images with clear and concise documentation.

I’ve been using LinuxServer.io images for a couple of years. That’s because they’re easy to use, and they’re clearly and concisely documented. I tend to check here first when I need a new image.

Configuring and running the containers via docker compose

LinuxServer.io only officially supports running the image via docker run or, preferably, docker compose. Here’s what the relevant section of my compose.yml file looks like:

networks:
  unifi-network-application

unifi-network-application:
  container_name: unifi-network-application
  image: lscr.io/linuxserver/unifi-network-application:8.1.113-ls36
  restart: unless-stopped

  depends_on:
    - unifi-network-application-db
  env_file:
    - ./common.env
    - ./secret.env
  environment:
    - MONGO_HOST=unifi-network-application-db
    - MONGO_PORT=27017
    - MONGO_DBNAME=unifi
  networks:
    - unifi-network-application
  ports:
    - 1900:1900/udp # Required for 'Make controller discoverable on L2 network' option
    - 3478:3478/udp # Unifi STUN port
    - 5514:5514/udp # Remote syslog port
    - 6789:6789 # For mobile throughput test
    - 8080:8080 # Required for device communication
    - 8443:8443 # Unifi web admin, guest portal HTTPS redirect port
    - 8843:8843 # Unifi guest portal HTTPS redirect port
    - 8880:8880 # Unifi guest portal HTTP redirect port
    - 10001:10001/udp # Required for AP discovery
  volumes:
    - ${SERVICE_DATA_DIR}/unifi-network-application:/config

unifi-network-application-db:
  container_name: unifi-network-application-db
  image: mongo:4.4.25-focal
  restart: unless-stopped
  user: ${PUID}:${PGID}

  env_file:
    - ./common.env
    - ./secret.env
  networks:
    - unifi-network-application
  volumes:
    - ${SERVICE_DATA_DIR}/unifi-network-application-db/data:/data/db
    - ${SERVICE_DATA_DIR}/unifi-network-application-db/docker-entrypoint-initdb.d/init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro

 

Unifi Network Application Container Configuration

First we define the network and image to use for this container. I always prefer to pin to specific versions when possible.

Next I include the depends_on stanza to indicate this container depends on the unifi-network-application-db container to be running first. More on that later.

Then in the env_file stanza I include a file named secret.env; this file includes MONGO_USER and MONGO_PASS secret configuration values. I have this file sitting on the filesystem adjacent to the compose.yml and it has all the secret configuration for my containers. And of course, this file is not checked into source control. Its data exists only locally and in my private information management application.

In the environment stanza I specify three environment variables: MONGO_HOST, MONGO_PORT, and MONGO_DBNAME. These three variables define the identifying information about the Mongo database we’ll be connecting to.

Next I specify the container’s port mappings; in this case there are nine. Several of them are optional, but I went ahead and enabled all of them because those ports are available anyway. Please see the list of required and optional ports here.

Lastly I have my volume mapping. In this case there is only one — the typical /config directory required by LinuxServer.io images, which I have mapped to the directory with all of my service data.

Mongo Database Container Configuration

LinuxServer.io’s Unifi Network Application image requires a supporting Mongo database image — in this case I’ll be using the latest 4.4 version of Mongo running on Ubuntu.

There are two interesting bits to point out in this container configuration. The first is that the database container uses the same network as the main application. This will set up Docker’s networking such that the main application can talk to the database, but processes outside the main application container cannot communicate with the database (since it has no external ports mapped).

The second thing worth pointing out is the second volume mapping. This maps a special database setup script that will be run the first time the container is run. Following LinuxServer.io’s setup instructions, we’ll create the file ${SERVICE_DATA_DIR}/unifi-network-application-db/docker-entrypoint-initdb.d/init-mongo.js with this content similar to this:

db.getSiblingDB("unifi").createUser({user: "MONGO_USER", pwd: "MONGO_PASS", roles: [{role: "dbOwner", db: "unifi"}, {role: "dbOwner", db: "unifi_stat"}]});

I’ve elided my specific values for MONGO_HOST and MONGO_PORT, so you’ll need to substitute those two values with the same secrets as filled into secret.env.

Ensure you’ve created the above script before the first time you launch the two containers! Otherwise the network application will not have a database instance to save data into.

Running the Containers

We are now ready to boot the containers. I suggest running the database container once in isolation first (via docker compose up unifi-network-application-db) and visually inspect its log output to confirm the init script ran and created the user & databases as expected. Assuming that worked, we can now bring up the main application via docker compose up unifi-network-application.

Lastly, if you’re like myself and migrating from the legacy unifi-controller image, you’ll need to go to the Backups section of the System settings, download a backup (including history if you want), and then restore that backup into the new Unifi Network Application. In my case, it took two or three minutes for the backup to be restored and the application to restart itself. The migration was then complete for me!

As always, thanks to the LinuxServer.io team for the great image and ongoing support over the years!

Conversation
  • Tim says:

    I’m a lost, rank amateur about all this (barely got Unifi running in Portainer in the first place), but in your yml example, why is the image version 7.5.x instead of the new version 8.0.x?

  • Join the conversation

    Your email address will not be published. Required fields are marked *