UniFi APs offline after restart: how the wrong config file path breaks everything
I rebooted my UniFi controller container and both access points went offline. The controller was healthy. The UI loaded, settings were intact, the APs showed up as Disconnected. But they wouldn’t reconnect no matter how long I waited.
This is the story of how a config file in the wrong directory silently breaks everything and stays broken through reboots.
The setup
I run the LinuxServer.io UniFi controller image in an LXC container. The controller sits behind Traefik for HTTPS termination, and the APs reach it over the local network at unifi.example.net.
I’d deployed this stack a few weeks earlier and it had been working fine. This particular day I needed to restart the container after a configuration change.
The problem
The container came back up in about 30 seconds. Both APs stayed Disconnected.
My first theory: Traefik. Maybe something with the proxy configuration was blocking the inform handshake. Then I remembered: only the web UI (port 8443) runs through Traefik. The inform protocol (port 8080) is exposed directly; it never touches the proxy. Traefik couldn’t be the cause.
My second theory: the “Override Inform Host” setting I’d configured in the controller UI. I’d set this to unifi.example.net during initial deployment, which tells the APs where to send their inform requests. I checked the controller settings and it was still there, unchanged.
So the inform URL was correct. The controller was running. And the APs just… wouldn’t connect.
Finding the real cause
I opened the controller UI and went to Settings -> System. The “Server IP Address” field showed 172.18.0.3, the Docker bridge IP the controller detected for itself, not my actual host IP.
That’s not right. I’d explicitly set system_ip in the container’s config to my actual host address.
I shelled into the container and looked at the file I’d edited:
cat /config/system.properties
There it was: system_ip=192.168.x.x. The setting was there. But the controller wasn’t reading it.
After some digging I found the problem: UniFi reads system_ip from /config/data/system.properties, not /config/system.properties. The root file is silently ignored. On restart, the controller falls back to auto-detecting the system IP, and on Docker networks it picks up the bridge IP instead of the real host IP.
There’s no error, no warning. The controller starts, the UI loads, everything looks fine. The wrong file just gets ignored.
The fix
First, add the setting to the correct file:
echo "system_ip=192.168.x.x" >> /config/data/system.properties
Then restart the container so the controller picks it up.
After restart, Settings -> System showed the correct host IP.
But the APs were still offline. They had the old inform URL cached, the one pointing at 172.18.0.3 which wasn’t reachable. I needed to manually push a new inform URL to each one.
Getting the APs back online
SSH’d into each AP and ran set-inform with the controller’s direct IP address. I used the IP rather than the hostname because DNS resolution can be unreliable when an AP hasn’t adopted to the controller:
ssh admin@192.168.x.x # AP address
set-inform http://192.168.x.x:8080/inform
First run: the AP acknowledged the command but didn’t reconnect. This is normal behavior. The first set-inform call gets the AP to reach out once; for it to stick, you run it twice:
set-inform http://192.168.x.x:8080/inform
After the second run, the AP showed up as Connected in the controller within about 10 seconds. Repeated for the second AP. Both online.
Verifying it’s persistent
The real test was whether this would survive another container restart.
I rebooted the container again. Waited. Both APs reconnected automatically within about 30 seconds. The system_ip setting held.
Controller Settings -> System still showed the correct IP. No more 172.18.0.3.
What I’d missed
Looking back at my initial setup notes, I’d added system_ip to /config/system.properties based on some documentation I’d found online. It worked at the time, or I thought it did, because I’d also set “Override Inform Host” in the UI. Those two settings do different things.
“Override Inform Host” controls the hostname the APs use in their inform URLs. That’s the DNS name the APs contact, and it stays set in the controller database. What it doesn’t do is stop the controller from re-detecting the system IP on restart. On a Docker bridge network, that auto-detection returns the bridge IP, not the host.
system_ip in /config/data/system.properties is what locks down the advertised IP. With the correct value in the right file, the controller skips auto-detection and always advertises the address you set. With it in the wrong file (/config/system.properties), it’s silently ignored and auto-detection wins on every restart. Setting it to an address the container can’t bind is also a problem, which is why a naive system.properties edit can fail in two ways: wrong file, or wrong value.
The two settings coexisted fine right after initial setup because the APs had never needed to fall back to the system IP. Once the container restarted and the controller advertised 172.18.0.3 instead of the real IP, the cached inform URL the APs had been using became invalid.
Lessons
One: The right file is /config/data/system.properties, not /config/system.properties. If you’re running the LinuxServer.io UniFi image, double-check this. The root file being silently ignored is a genuinely confusing failure mode.
Two: After fixing the controller-side config, the APs still have the old inform URL cached. Manual set-inform is required. Run it twice: first run triggers a reconnect attempt, second run makes the new URL persistent.
Three: Use the IP address, not the hostname, when running set-inform in a broken state. DNS resolution may not be reliable when the AP hasn’t adopted to the controller.
If you’re building out a UniFi setup, I’ve written about the initial deployment and Traefik configuration as well. The APs I run are the UniFi U6 Pro and older AC Pro.
As an Amazon Associate, I earn from qualifying purchases.
Related reading
Deploying UniFi Network Controller with Traefik: Decisions and Troubleshooting
Decision analysis for LXC+Docker vs VM deployment, hybrid networking strategy for UniFi device communication, and troubleshooting firewall and IP configuration issues.
Self-hosting Tailscale with Headscale
Replacing Tailscale's hosted coordination server with Headscale on a Proxmox LXC: Docker Compose setup, deprecated config keys that blocked startup, and connecting macOS, Linux, and iOS clients.
Self-hosting Backlogia, and fixing it before running it
Backlogia is a self-hosted app that pulls your game libraries from Steam, GOG, Epic and more into one place. Before I would run it I read the code, found four security gaps, and forked it. Then Starlette and a CORS bug had opinions too.
Ready to Transform Your Career?
Let's work together to unlock your potential and achieve your professional goals.