Adopt UniFi devices to a VPS controller
Broadcast discovery stops at the first router. Here is how to point remote UniFi access points at a controller on your VPS, and keep port 8080 private.
Why UniFi adoption fails across the internet
A factory-default UniFi device looks for its controller by shouting on the local network. It sends a UDP broadcast to port 10001 and waits for a controller in the same broadcast domain to answer. A broadcast stops at the first router, so an access point in your office never reaches a controller sitting in a data centre. Adoption over the internet works only when you tell the device where the controller is.
After that first contact, the whole thing is one HTTP conversation. The device posts to an inform URL, http://<controller-address>:8080/inform, every few seconds. The controller answers with configuration. That is the entire management channel: TCP port 8080, opened outbound by the device. The controller never dials the device, which is why the office needs no port forward and no static public address.
So once you have a UniFi Network application running on your own VPS, the only job left is getting that URL onto each device. Three routes do it. They differ in how much of your local network you have to change, so work down the list only as far as your site actually needs.
What the device needs before you start
The device must not be managed by another controller. A device that still holds an earlier controller's adoption key appears as "Managed by Other", and SSH with the default credentials is refused, because that controller changed them. Reset it, either by holding the physical reset button for about ten seconds while the device is powered, or over SSH if you still have working credentials:
set-defaultThe device reboots into factory settings. Its LED runs through the startup colours and then settles into a steady state, white on current models and steady amber on older ones. Wait for that steady LED. A device that is still booting will not answer anything you type at it.
The device also needs an IP address and a default route out of the site. Adoption is outbound, so the site firewall only has to permit outbound TCP 8080 to your VPS. And the controller needs an address that does not move. A home connection with a changing public IP and no hostname attached to it will break every adopted device on the day the address changes.
Route 1: set-inform over SSH, for one or two devices
This touches nothing except the device. Find its local address in your router's DHCP lease list, then connect. On a factory-default device the user and the password are both ubnt.
ssh ubnt@192.168.1.42At the device prompt, look at the current state first, then set the inform URL, then look again.
info
set-inform http://203.0.113.10:8080/inform
infoThe second info should print the URL you just typed on its Status: line. A line like Status: Unknown[11] (http://203.0.113.10:8080/inform) means the URL is set and the device is not getting a usable answer back, so the address, the port or the path between them is wrong. If the URL on that line is still the default http://unifi:8080/inform, the command did not take, and the usual reason is that the device is not in a factory-default state.
With the URL set and reachable, the device shows up in the controller as pending adoption within about half a minute. Click Adopt. The device reboots as part of adoption, and it can come back with the default inform URL again, which looks like the adoption silently failed. Run set-inform a second time while the device is still listed in the controller. Repeating the command is safe. After adoption completes, the SSH user and password are whatever the controller sets under Settings, System, Advanced, so ubnt will stop working.
Route 2: a local DNS record named unifi
The default inform URL on a factory-default device is http://unifi:8080/inform. That is a hostname, not an address, so the device resolves the name unifi through whatever resolver DHCP handed it. Point that name at your VPS and a factory-default device adopts itself with nothing typed on the device at all. This is the route to use when you are shipping hardware to a site you will not visit.
Most home routers and small office gateways run dnsmasq underneath, where the record is one line:
address=/unifi/203.0.113.10Reload the resolver, then prove the record works from a laptop on the same network as the devices:
dig +short unifi @192.168.1.1That should print your controller's address. If it prints nothing, the device will not resolve it either, and no amount of waiting will help. If your DHCP server hands out a search domain, add the record for the fully qualified name as well, unifi.lan or whatever your domain is, so the name resolves whichever form the device tries first. The record only has to work inside the site, so there is nothing to publish publicly. If you are unsure which resolver your devices are being given, how a name turns into an address covers where that answer comes from.
One warning that follows from the section on security below: if you point unifi at a private tunnel address, the devices themselves have to be on that tunnel, not just your laptop.
Route 3: DHCP option 43, for a site with more than a handful of devices
Option 43 is the DHCP vendor-specific option. UniFi devices read suboption 1 from it as the controller's IPv4 address, so every device that takes a lease learns where to go without a DNS record and without SSH. This is the right answer for a site where you will keep plugging in new hardware.
The value is suboption number 01, then the length 04, then the four octets of the address in hex. For 203.0.113.10: 203 is cb, 0 is 00, 113 is 71, and 10 is 0a. So the value is 01:04:cb:00:71:0a. Many firewall appliances, including MikroTik and pfSense, want exactly that string, with or without the colons depending on the box.
On ISC dhcpd you declare the vendor space instead of writing hex:
option space ubnt;
option ubnt.unifi-address code 1 = ip-address;
class "ubnt" {
match if substring (option vendor-class-identifier, 0, 4) = "ubnt";
option vendor-class-identifier "ubnt";
vendor-option-space ubnt;
option ubnt.unifi-address 203.0.113.10;
}On dnsmasq it is again one line:
dhcp-option=vendor:ubnt,1,203.0.113.10Two things about option 43 catch people out. First, both forms above send the option only to clients whose vendor class identifier starts with ubnt, so you cannot test it by renewing the lease on a laptop: the laptop is not a UniFi device and will never be sent the option. Test it by rebooting an actual access point and watching the controller. Second, option 43 arrives with a DHCP lease, so it reaches a device that is asking for one. A device that already holds an inform URL from an earlier controller ignores it. Reset the device first and the option does its job on the next boot.
A device that is offered several of these at once tries them in turn and stays with whichever controller answers, so a DNS record and an option 43 entry pointing at the same controller do not conflict.
Why a device appears and then drops out of adoption
This is the most common failure that has nothing to do with the network, and most adoption guides skip it. The device shows up in the pending list, you click Adopt, and it either returns to pending or reports that adoption failed. The path is fine. The versions are not.
The controller has to recognise the device model and speak the management protocol that the device's firmware speaks. Hardware bought this quarter ships with firmware newer than a controller build you installed months ago, so the controller sees a device it cannot fully provision and stops partway through. This bites self-hosted controllers much harder than Ubiquiti's own hardware, because nothing updates a controller on your VPS unless you do. As of September 2026 the network application still moves every few weeks.
Read both numbers before you touch anything else. On the device, info prints a Version line. In the controller, the version is on the Settings, System page. If the device is newer, update the controller first, because a current controller supports older firmware but not the reverse. If the device is older than anything the controller supports, upgrade the device directly over SSH:
ssh ubnt@192.168.1.42
upgrade FIRMWARE_URLReplace FIRMWARE_URL with the .bin address for your exact model, taken from the Ubiquiti downloads page. The device fetches the file itself, so it needs outbound HTTPS from the site. It reboots when the transfer and the write finish, which takes a few minutes, and the LED returns to steady white. Copy the URL for your exact model. The wrong image can leave the device unbootable, and there is no undo over SSH.
Why port 8080 must not face the public internet
Look at the inform URL again: it starts with http://, not https://. The inform channel is plain HTTP on TCP 8080. Before a device is adopted it holds no key of its own, so that first exchange is protected only by a value that is identical on every UniFi device and is published in the open source implementations of the protocol. It is not a secret. Anything crossing the public internet before adoption completes should be treated as readable by whoever is on the path.
The management interface is the larger problem. Putting the controller UI on a public IP exposes an admin login and the whole application to the internet's background scanning, permanently, for the convenience of adopting a device once.
The clean answer is to stop the traffic being public at all. Put the site and the VPS on one private network, with the site's router advertising its LAN so the access points have a route to the controller's private address, then set the inform URL to that private address and close 8080 on the public interface. Advertising a home or office subnet from a subnet router is the version of this with the least per-site configuration, because the devices themselves need no client software.
If a tunnel is not an option, allow 8080 from the site's public address only, and nowhere else:
sudo ufw default deny incoming
sudo ufw allow from 198.51.100.7 to any port 8080 proto tcp
sudo ufw status numberedufw status numbered should list that rule with the source address on it. A rule with Anywhere as the source is the one you were trying to avoid. This breaks the day the site's public address changes, which on a residential line happens without warning, so treat it as the compromise it is. The rest of the ruleset matters just as much, and the baseline ufw rules a VPS should start with covers what else should be shut.
For the browser side, serve the UI over TLS rather than on a raw port. An nginx reverse proxy in front of the controller gives you one certificate and one place to add access control, and a Cloudflare Tunnel with no inbound ports open removes the public listener entirely. Both of those carry your browser, not your access points. The devices still need their own path to 8080, and the controller's UDP 3478 traffic is not HTTP, so an HTTP tunnel cannot carry it. Solve the admin UI and the device channel separately.
Set the inform host that the controller advertises
The controller tells each adopted device where to reach it, and it works that address out from its own network interfaces. On a VPS install behind Docker or any NAT, it picks the address it can see, which is often private. The device adopts, is handed that address, switches its inform URL to it, and immediately loses the controller. The symptom is a device that reaches "Adopting" and stays there, or a device whose info shows an inform URL you never typed:
Status: Unknown[11] (http://172.30.33.3:8080/inform)Fix this once, in Settings, System, Advanced. Set the Inform Host to the address your devices actually use, the public IP or the tunnel address, and enable the override. Every device adopted after that receives the correct URL. Devices already stuck need one more set-inform to get back in contact.
What to check when it still says Adopting
Work through these in order, and read your own output at each step rather than assuming.
- SSH to the device and run
info. Read the URL on theStatus:line. If it is not the URL you set, the device reverted during its reboot, so runset-informagain while the device is visible in the controller. - From a laptop on the device's own network, test the path:
nc -vz 203.0.113.10 8080. Success prints a line containingsucceeded. A hang means something between you and the VPS is dropping the traffic;Connection refusedmeans the path is open and the controller is not listening, which is a controller problem, not an adoption problem. - Compare the
Versionfrominfowith the version on the controller's Settings, System page. A device newer than the controller is the firmware mismatch described above. - Read the Inform Host under Settings, System, Advanced. A private address there explains a device that adopts and then vanishes.
- Look at how the controller lists the device. "Managed by Other" means it still holds an older controller's key, and
set-defaulton the device clears it. - Watch the connection arrive on the VPS:
sudo ss -tnp | grep :8080while the device is trying. A connection from the site's public address means informs are landing. An empty result means nothing is arriving, so go back to step 2. - If the device adopts but then responds slowly to changes, check that outbound UDP 3478 is not blocked at the site. The controller uses it to prompt a device to check in immediately, so blocking it does not stop adoption but does make the device look unresponsive.
Almost every remaining case is one of two things: the device is not really in a factory-default state, or the address it was given is not an address it can reach. Both are visible in the output of info, which is why that command is step one.
FAQ
Why can my VPS controller not find my access point over the internet?
UniFi discovery is a UDP broadcast to port 10001, and a broadcast does not leave the local network. The controller and the device are in different broadcast domains, so neither one ever hears the other. Nothing you change on the controller fixes this. You have to give the device the controller's address yourself, with set-inform over SSH, a local DNS record for the name unifi, or DHCP option 43.
Do I have to factory reset a UniFi device before adopting it to a remote controller?
In practice, yes. A device that was adopted before holds the previous controller's key and its own changed SSH credentials, so set-inform and DHCP option 43 are both ignored and the controller lists it as "Managed by Other". Run set-default over SSH if you still have working credentials, or hold the reset button for about ten seconds. Wait for the LED to settle into a steady state before you try again.
Is it safe to open port 8080 to the internet for adoption?
No, and it is easy to avoid. The inform channel is plain HTTP, and a device that has not been adopted yet has no key of its own, so the first exchange is not private. Put the site and the VPS on one tunnel or mesh network and use a private address in the inform URL. If that is impossible, restrict TCP 8080 to the site's public address with a source-limited firewall rule, and never expose the management interface itself on a raw port.
My device adopts and then goes back to Adopting. What is wrong?
Two causes account for most of these. The first is the inform host: the controller worked out its own address as a private one, handed that to the device during adoption, and the device can no longer reach it. Set the Inform Host explicitly under Settings, System, Advanced and enable the override. The second is a firmware version the controller does not support, which shows as a device that appears, accepts the adopt click, then returns to pending. Compare the Version line from info against the controller version and update the controller first.