Pragmatism in the real world

Run the UniFi Controller headless on Mac

I’m running a UniFi network here with wireless access points, the Security Gateway and a PoE switch. It seems to be a robust system and is almost certainly overkill, but reliability is high on my lists after bad experiences with a NetGear WiFi router.

The UniFi system software is called the Controller and runs on a various operating systems. As I have a Mac mini here, I decided to run it on there. Weirdly, however it runs as a GUI application which means that I have to be logged in. There’s no need for that though as by scouring the Internet I discovered that we can run it headless via launchd.

Firstly we create /Library/LaunchDaemons/com.unifi.controller.service.plist. This file has to be owned by root with group of wheel:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>EnvironmentVariables</key>
    <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/sbin</string>
    </dict>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>com.unifi.controller.service.plist</string>
    <key>EnableGlobbing</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/bash</string>
        <string>-c</string>
        <string>exec "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" -Djava.awt.headless=true -Xmx1024M -jar /Applications/UniFi.app/Contents/Resources/lib/ace.jar start</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>WorkingDirectory</key>
    <string>/Applications/UniFi.app/Contents/Resources/</string>
</dict>
</plist>

This is a fairly standard launchd plist file file. However, the controller software is written in Java, but as Ubiquiti no longer bundle a copy of Java, we need to install our own copy of Java 8:

<key>ProgramArguments</key>
<array>
    <string>/bin/bash</string>
    <string>-c</string>
    <string>exec "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" -Djava.awt.headless=true -Xmx1024M -jar /Applications/UniFi.app/Contents/Resources/lib/ace.jar start</string>
</array>

(You may need change the path to where your Java 8 is installed.)

This means that when Ubiquiti updates the bundled Java, our service continues to work. We also need to set the working directory to the Resources directory of the app bundle as it doesn’t work otherwise…

Update: Since this post was written, Ubiquiti no longer bundle Java, I have updated appropriately based on the comment from Wade Gibson.

Secondly, we install the service:

$ sudo launchctl load -w com.unifi.controller.service.plist

Now, the Controller is always running and we can access it on https://localhost:8443 and manage our UniFi network to our heart’s content!

37 thoughts on “Run the UniFi Controller headless on Mac

  1. Hi Rob….

    What an amazing article….. I have read pages and pages worth of complex solutions and articles on Unifi forum but your methos got me up and running less than 2min.

    Thanks million for this post

  2. Forgive a silly question:
    First install and get the controller working, as gui, no?
    Does it matter the controller version?

    Thank You!

  3. Hello all,
    it indeed worked.
    Just to add, maybe it will help somebody –
    to create plist owned by root and with group wheel you have to manually create plist file with that name (lets say on desktop), copy it to LaunchDaemons and use terminal:

    sudo chown root:wheel /Library/LaunchDaemons/com.unifi.controller.service.plist 

    and then start service

    sudo launchctl load -w /Library/LaunchDaemons/com.unifi.controller.service.plist 

    Thanks rob for quick help.

  4. Hi all, I have rolled the above including Raul’s comments. Only difference is using folder LaunchAgents.

    Does not load on reboot, but wors when I sign in, I don’t have to launch app.

    I would like it to run on reboot, without logging in. please help

  5. It took a little digging around, but changing this line in the plist with the new Java path seems to work. You have to put quotes around it since the path has a space.

    exec "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" -Djava.awt.headless=true -Xmx1024M -jar /Applications/UniFi.app/Contents/Resources/lib/ace.jar start
    
    1. You are a life saver! Every time the controller is updated, I've literally been copying and pasting the bundled version of Java from an older versions of the Controller into the new UniFi.app package. I knew there had to be a way to point to the manually installed version of Java.

      Still really frustrating the Ubiquiti unbundled Java (though it appears to be due to Oracle's terrible licensing), and even worse that the Controller is still written in Java…

  6. Rob- I've been looking, for weeks now, for a fix to my UniFi.app not launching on my mac. I tried everything on the Ubiquity community pages and zilch. This did the trick – along with additional feedback from Raul and Wade. Thank you all!

  7. To run UniFi controller as a faceless app with version 5.12.66 simply did the change in Info.plist file
    change "ui" to "start"
    From:
    JVMOptions

    	
    		-Xdock:name=UniFi
    		-Dcom.apple.mrj.application.apple.menu.about.name=UniFi
    		com.ubnt.ace.Launcher
    		ui
    

    To:
    JVMOptions

    	
    		-Xdock:name=UniFi
    		-Dcom.apple.mrj.application.apple.menu.about.name=UniFi
    		com.ubnt.ace.Launcher
    		start
    

    Then run:

    "/Applications/UniFi.app/Contents/MacOS/JavaAppLauncher"

    After that you can do whatever you want, e.g. use launchd
    Mine:

    /Library/LaunchDaemons/com.ubiquiti.unifi.plist

    Label
    com.ubiquiti.unifi
    Disabled

    RunAtLoad

    ProgramArguments

    /Applications/UniFi.app/Contents/MacOS/JavaAppLauncher

    UserName
    put_user_name_here
    ServiceDescription
    Unifi Manager

    1. That last bit, enabling it from launchd – a few questions:
      Do you remove the LaunchDaemon plist file that we created based on this post?
      You have the settings, but I'm using old school editor (vi) so it would help see all the xml tags, can you put your contents of com.ubiquiti.unifi.plist in this thread?

      Thank You

  8. Pingback: Making Game: How do I run Ubiquiti's UniFi Network Controller on macOS? - TECHPRPR
  9. Pingback: Linux HowTo: How do I run Ubiquiti's UniFi Network Controller on macOS? - TECHPRPR
  10. Could we get an update on above? I tried multiple things but can't get it working (macOs 10.15.7)

  11. Hello!

    I did the steps and also chowned the plist to root.
    Unfortunately i am also running openHab on this machine and if i try to acces localhost:8443 i am forwarded to my openhab isntance (normally port 8080).
    Is there anything i can do?

    Thank you!

  12. Hello!

    I have a problem accessing the UI. I also have OpenHab installed and when i acces localhost:8443 it forwards me to the openhab instance … 9000 is grafana. any thoughts?
    If i try to open the app manually it says java is not installed – but it was successfully installed via brew (following your guide).

    Thank you!

  13. Hi Rob, thanks for the article. My setup is the same and I will be ordering an EdgeRouter and the unifi 6 lite but do your instructions continue to be valid? I see that you last commented on Oct 6 2020 which is a few months after I write this note.

      1. Hi Rob,

        I have to read your article in detail and follow the steps carefully but are you running the latest controller? https://help.ui.com/hc/en-us/articles/360012282453-UniFi-Set-up-a-UniFi-Network-Controller.

        Just another analysis, folks appear to choose running the UniFi controller in a VM locally or on a cloud service, purchasing dedicated hardware from Ubiquity, or running it in docker etc, … your approach appears to be very cost effective as RAM and CPU are kept to a bare minimum as the native app runs headless in the background.

        What is the CPU/RAM toll this has on your mini?

        I want to mimic your steps because I have a Core2Duo Mac mini which runs a small SFTP server so why not have it do one more task right?

        I found your article just in time! Thank you for sharing this with those stumbling by.
        —Alex

        1. To be honest, the easiest way is to just run the UniFi controller with the GUI visible. This means that the Mac has to be logged in at all times though. The next easiest is to get a CloudKey 2 as it's built for it. I'm cheap as I already have the Mac. It doesn't use a noticeable amount of CPU/RAM.

  14. Thank you for the writeup and updates! I just got this to work in <10 min on my Mac mini M1 with Big Sur.

    Question: The controller software gets regular updates. What is a good way to check and install the updates? Stop the launchd service manually and launch the controller from the UI?

    1. Can you provide steps to stop the launchd service manually? If I open Activity Monitor which process should I quit?

  15. When I tried this, my server was up and running fine, but oddly 3 of my devices (2 APs and Gateway) were put into a adoption loop, where they couldn't adopt. As soon as I switched back to the UniFi app, the devices adopt just fine. Anyone else seen this?

  16. Anyone struggling with this after 2022:

    1- Prevent the controller app to run in interactive UI mode
    Go to Terminal and switch to the root (with password prompt) and edit in nano the key under JVMOptions, switch ui to start:
    sudo nano /Applications/UniFi.app/Contents/Info.plist
    (ctrl+x, and y to save)
    Test your changes by running:
    /Applications/UniFi.app/Contents/MacOS/JavaAppLauncher

    2- Create a launcher agent (daemon/service) (nano will save under the right group, just copy and paste)
    sudo nano /Library/LaunchDaemons/com.unifi.controller.service.plist

    Label
    com.ubiquiti.unifi
    KeepAlive

    ProgramArguments

    /Applications/UniFi.app/Contents/MacOS/JavaAppLauncher

    RunAtLoad

    UserName
    yourusername
    ServiceDescription
    Unifi Manager

    Finally, load with
    sudo launchctl load /Library/LaunchDaemons/com.unifi.controller.service.plist

  17. Good article. As an fyi for anyone… I am coming off of a Ubuntu OS device with the controller, where the $100 device died. I had controller backups on a small memory card and an old mac mini, but it too as a poster stated, have 10.15.7 (Catalina). Has anyone have this solution working on Catalina? I ask as I followed all of the steps. What I noticed is when I loaded the plist to run with launchctl and basically nothing happening, tail -f /var/log/system.log shows these lines:

    Jan 31 16:57:50 Mac-mini com.apple.xpc.launchd[1] (com.unifi.controller.service.plist[1889]): Service exited with abnormal code: 1
    Jan 31 16:57:50 Mac-mini com.apple.xpc.launchd[1] (com.unifi.controller.service.plist): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
    Jan 31 16:58:00 Mac-mini com.apple.xpc.launchd[1] (com.unifi.controller.service.plist[1890]): Service exited with abnormal code: 1
    Jan 31 16:58:00 Mac-mini com.apple.xpc.launchd[1] (com.unifi.controller.service.plist): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.

    The version of controller I have installed is 7.4.140.

    1. When you look for the status code 1 for launchctl it says is a problem with permissions.

      It may be, but I got rid of that problem by eliminating EnableGlobbing and the line with the true next to it.

      I still have problems with file permissions. My OS is Catalina.

  18. Hi. Could someone post an updated launch script to work with the latest Network Application and Java 11? The above script no longer works. As of February 2023, the lastest official release of the Unifi Network Application is version 7.3.83. Per the release page
    https://community.ui.com/releases/UniFi-Network-Application-7-3-83/88f5ff3f-4c13-45e2-b57e-ad04b4140528
    it has the following JAVA requirement "An updated/current version of Java 11 must be installed on the system hosting the UniFi Network Application." Previously only Java Runtime Environment (JRE) 8 was required.

    1. You have change the path to java. I use JDK 17 so my path is "/Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home/bin/java"

    2. I am working on it.

      So far…

      You need to eliminate
      EnableGlobbing

      As Globbing is not supported anymore since Mac OS 10.10

      You also need to install Java JDK (not only the JRE) because it is the one that includes the command line commands to run the script.

      I have been able to bring up the service (headless) and show the login screen, but I am having problems with file permissions as all the information is stored in the user's ~/Library/ApplicationSupport/Unifi folder, linked to the app container file structure, and now you need root to access those files.

      On my first attempt, I completely screwed up everything and I had to start over again.

      If anyone has any ideas, send me an email.

      I'll post the solution here and in my blog and link back.

      P.D. I am installing this for an old iMac late 2009 running Catalina. Hopefully, it will work up to Ventura.

  19. Can someone help me out here? I can run the GUI no problem, despite not knowing or installing any java on my machine. In theory, I feel they included the java binaries somewhere, I just dont know where

Comments are closed.