The Problem
Within an article on their website, LinuxServer.io have announced that they will be deprecating the current linuxserver/unifi-controller
public image as of 2024/01/01. Happy New Year! The README on the current tooling that I imagine most are using mentions a direct upgrade if you were using the mongoless
tag which, due to what’s colloquially known as “Sod’s Law”, I am not.
On the new repo as well as the DockerHub page, the docs currently have a brief mentioning of requiring an external MongoDB instance but the code snippits don’t actuall have one… This seemed a little problematic, and after migrating my setup last night, figured I’d include a quick walkthrough.
The Solution
Unfortunately, there’s no one and done migration to just switch images and bring the container back up, but it’s not exactly a difficult process.
I’ve included the docker-compose.yml
in the section below, just copy pasta, change the passwords (anywhere you see SUPERSTRONGPASSWORD
), and you’re good (also create a init-mongo.js
using the below file too as this will automatically create the correct user, db, and permissions).
DO NOT copy across the current Unifi config
folder, restoring from the backup will create this in a safer way.
The newest supported MongoDB version currently is 4.4 so that’s what I’m using in my stack, if that changes I’ll likely see about migrating to newer, and will update this post if I do.
Manual backup of current configuration
- Settings > System > Backups > Download (in the new UI, anyway)
- I’d set the export time to ‘No Limit’ to keep stats, etc, but you do you
Stop the current container
- Just do a
docker compose down
on the current stack - Unless you’re migrating to another box you need to stop the current stack because the new one is going to need the same ports :upside_down_face:
- Just do a
Start the new container
- I said it above, but just in case, copy the compose file into the new location (I’d just make a different folder for this new controller)
- You guessed it,
docker compose up -d
- I’d recommend watching the logs with
docker compose logs -f
because you’ll see a final log line from the MongoDB container related to Authentication, and as long as that’s not an error that’s when you’ll know that the container is up and ready
Restore from the backup
- Go to https://container-host-name-or-ip:8443
- Start the process, until you see a link allowing you to resore from a backup
- Click that link
- Select the backup you just downloaded from the old controller
- Wait a couple of minues, you’ll see the MongoDB logs going crazy and then the controller will reboot
- Reload, log in, and check all your APs still report in
- Breathe a sigh of relief
- You can now remove the volume binding for the
init-mongo.js
file and restart the stack for purity’s sake if you like
Don’t touch it for another 6 months :wink:
And the best bit is that if it breaks in some way and you need to roll back, just start the old stack and you’re back in business :partying_face:.
Docker-Compose File
NB: You can also use a proper Docker volume
instead of a local folder in the unifi-db
container
version: "2.1"
services:
unifi-db:
image: mongo:4.4
restart: always
volumes:
- ./db:/data/db
- ./init-mongo.js:/docker-entrypoint-initdb.d/init-mongo.js:ro
unifi-network-application:
image: lscr.io/linuxserver/unifi-network-application:latest
container_name: unifi-network-application
environment:
- PUID=1000
- PGID=1000
- TZ=Europe/London
- MONGO_USER=unifi
- MONGO_PASS=SUPERSTRONGPASSWORD
- MONGO_HOST=unifi-db
- MONGO_PORT=27017
- MONGO_DBNAME=unifi
- MEM_LIMIT=1024 #optional
- MEM_STARTUP=1024 #optional
volumes:
- ./config:/config
ports:
- 8443:8443
- 3478:3478/udp
- 10001:10001/udp
- 8080:8080
- 8843:8843 #optional
- 8880:8880 #optional
- 6789:6789 #optional
- 5514:5514/udp #optional
restart: always
depends_on:
- unifi-db
init-mongo.js File
db.getSiblingDB("unifi").createUser({
user: "unifi",
pwd: "SUPERSTRONGPASSWORD",
roles: [{ role: "readWrite", db: "unifi" }],
});
db.getSiblingDB("unifi_stat").createUser({
user: "unifi",
pwd: "SUPERSTRONGPASSWORD",
roles: [{ role: "readWrite", db: "unifi_stat" }],
});