Unifi and MongoDB 4.0

It seems this is a much discussed topic.

Gentoo forced me to solve this.

Unifi normally uses an embedded MongoDB server. Gentoo has a policy against this for various reasons. As such the Gentoo build carves out this embedded MongoDB instance and substitutes it with appropriate symbolic links to the system-maintained MongoDB instance, and wrapper scripts where required.

As of writing this we’re running Unifi 5.12.35 with MongoDB 4.0.12.

You can for the most part follow the usual upgrade instructions. But you need to connect to the unifi instance of MongoDB when updating the compatibility versions:

mongo --host localhost --port 27117

If you don’t do this properly you will get messages such as these in unifi’s mongodb.log:

IMPORTANT: UPGRADE PROBLEM: The data files need to be fully upgraded to version 3.6 before attempting an upgrade to 4.0; see http://dochub.mongodb.org/core/4.0-upgrade-fcv for more details.

We blew this up initially, system upgrade to 4.0 and Unifi controller stopped functioning. So we learned this the hard way. Had to pull a few stunts to get mongodb 3.4 back on the system, so hopefully this warning will safe a few people some headaches.

Detailed steps:

  1. Using MongoDB version 3.4 (if you’ve still got it), explicitly do
    mongo --host localhost --port 27117 --quiet --eval "db.adminCommand( { setFeatureCompatibilityVersion: "3.4" } )"
  2. Remove everything which is MongoDB from the Unifi installation, other than the MongoDB data files (/usr/lib/unifi/bin/mongod). Gentoo has replaced this with a shell script in newer versions to accomodate the MongoDB upgrade past 3.4):
    #!/bin/sh
    
    # Remove --nohttpinterface argument, since it does not exist on MongoDB >= 3.6.x anymore
    # See https://community.ubnt.com/t5/UniFi-Routing-Switching/MongoDB-3-6/td-p/2195435
    remove_nohttpinterface_arg=$(echo $* | sed -e 's/--nohttpinterface//')
    /usr/bin/mongod ${remove_nohttpinterface_arg}

    That really aught to be exec on the last line. And dealing with other issues regarding $* and the sed, I propose rather using this which will deal with it more comprehensively:

    #!/bin/sh
    
    # Remove --nohttpinterface argument, since it does not exist on MongoDB >= 3.6.x anymore
    # See https://community.ubnt.com/t5/UniFi-Routing-Switching/MongoDB-3-6/td-p/2195435
    for arg do
        shift
        [ "${arg}" = "--nohttpinterface" ] && continue
        set -- "$@" "${arg}"
    done
    
    exec /usr/bin/mongod "$@"

    This could potentially do with some further improvements to detect the version and not strip out –nohttpinterface if mongodb is <3.6. I'm not going to bother since I don't have need for that currently (probably never). Update the path in the final line as per your requirements.

  3. Upgrade your system mongodb to version 3.6

  4. Restart unifi controller, if it’s mongdb.log file still moans about stuff, fix that (probably you missed step 1 so you’ll need a MongoDB version 3.4 again to sort that out).
  5. Set compat to 3.6:
    mongo --host localhost --port 27117 --quiet --eval "db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )"
  6. Verify:
    mongo --host localhost --port 27117 --quiet --eval "db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )"
  7. Restart Unifi controller. Test that it works.
  8. Repeat from step 2 replacing 3.6 with 4.0 as you go through.

This way we upgraded all the way to 4.0 and still have a working controller.

You can do nasty things with the wrapper there – in particular you can modify arguments to mongod, to for example do things like adjust the arguments in order to listen on ANY instead of localhost :).

Comments are closed.