Skip to content

Instantly share code, notes, and snippets.

@AmazingTurtle
Last active February 18, 2025 15:44
Show Gist options
  • Save AmazingTurtle/e8a68a0cbe501bae15343aacbf42a1d8 to your computer and use it in GitHub Desktop.
Save AmazingTurtle/e8a68a0cbe501bae15343aacbf42a1d8 to your computer and use it in GitHub Desktop.
restore access to unifi controller

Restore access to a unifi controller

When you are unable to login to the unifi controller or forgot admin password, you can restore access using SSH and manipulating mongodb directly.

Warning

Do not uninstall unifi controller - most of the data is not stored in mongodb. In case you thought a mongodb backup would be sufficient, you may have fucked up already, just like me. However I managed to write this "tutorial" for anyone to not run into the same trap.

Apparently this guide no longer works with recent unifi controller versions (starting nov/dec 2022). Since I no longer use unifi hardware in my home system, I can not update the guide myself. In case you've gotten here to recover your data, you're likely doomed. But giving it a try won't hurt anyway, therefore: good luck.

Steps

1. Generate password

Use quickhhash.com to generate a new password. Use sha512 / crypt(3) / $6$ with the any salt you like (I used 9Ter1EZ9$lSt6 in the example below, but it really doesn't matter).

I have generated a dummy password for you if you want to leave this step out. It is Ch4ngeM3VeryQu!ck:

$6$9Ter1EZ9$4RCTnLfeDJsdAQ16M5d1d5Ztg2CE1J2IDlbAPSUcqYOoxjEEcpMQag41dtCQv2cJ.n9kvlx46hNT78dngJBVt0

2. SSH to controller

SSH to the server running the unifi controller. In my case it's running on a raspberry pi.

3. Connect to mongodb

By default unifi comes with mongodb running on port 27117. To connect to it, use the mongo cli tool. Make sure it is installed.

Connect using the following command:

mongo --port 27117

When connected to mongo, execute the following commands to switch the database and verify the installation

use ace;
show collections;

It should show a list of collections, e.g. account, admin, alarm, broadcastgroup, ....

4. Fix

It is very likely that you got here because of power/data loss. You want to check if admins are still in the database. To do so, execute the following command in the mongo cli:

db.admin.find()

If the result is blank or you don't remember your password, there's two ways. Make sure to replace variables before executing commands.

4.1. Change password of existing user

db.admin.update({ name: "<YOUR-NAME-GOES-HERE>" }, { $set: { "x_shadow": "<PASSWORD-HASH-FROM-STEP-1-GOES-HERE>" } });

4.2. Create a new user

db.admin.insert({ "email" : "<YOUR-EMAIL-GOES-HERE>", "last_site_name" : "default", "name" : "<YOUR-NAME-GOES-HERE>", "time_created" : NumberLong(100019800), "x_shadow" : "<PASSWORD-HASH-FROM-STEP-1-GOES-HERE>" })

5. Get admin id

db.admin.find()

Will output something like this:

> db.admin.find()
{ "_id" : ObjectId("5d0a2e7e8f01c49af4cbe3cd"), "email" : "...", ... }

Take the contents of _id, in this case it is 5d0a2e7e8f01c49af4cbe3cd. You should remember it for the next steps.

6. Fix permissions

You will need to attach the admin role using db.privilege to the newly created user. The privilege belongs to an admin and a site_id.

Make sure to get your site_ids using the following command:

db.site.find()

It will show something like this:

> db.site.find()
{ "_id" : ObjectId("5d07b088280f9002d7676c87"), "name" : "super", "key" : "super", "attr_hidden_id" : "super", "attr_hidden" : true, "attr_no_delete" : true, "attr_no_edit" : true }
{ "_id" : ObjectId("5d07b088280f9002d7676c88"), "name" : "default", "desc" : "Default", "attr_hidden_id" : "default", "attr_no_delete" : true }

Once you know the ids of your sites, you can continue with creating privilege entries. You will need the admin id from step 5.

Use the following command for each site you got from db.site.find()

db.privilege.insert({ "admin_id" : "<ADMIN-ID-GOES-HERE>", "permissions" : [ ], "role" : "admin", "site_id" : "<SITE-ID-GOES-HERE>" });

Optionally verify that all privileges have been created using the following command:

> db.privilege.find()
{ "_id" : ObjectId("5d0bb7573d70717df47d5af6"), "admin_id" : "5d0a2e7e8f01c49af4cbe3cd", "permissions" : [ ], "role" : "admin", "site_id" : "5d07b088280f9002d7676c87" }
{ "_id" : ObjectId("5d0bb7573d70717df47d5af7"), "admin_id" : "5d0a2e7e8f01c49af4cbe3cd", "permissions" : [ ], "role" : "admin", "site_id" : "5d07b088280f9002d7676c88" }

7. Test

Now you're all set. You eventually want to restart the unifi controller using service unifi restart. You can login now. Good Luck.

@lpacor
Copy link

lpacor commented May 30, 2024

The @AmazingTurtle saved my day as well! I lost access to my self-hosted (still cloudkey 1.1.19) unified controller (7.2.97, apparently the last one available for the legacy cloudkey) after updating my SSO password on unify.ui.com (I think it depended on that).
Following @alexbergsland additional hint made everything available again already at the first attempt.
My next step will be to try and reactivate the unified SSO for the other account, the step after that to get rid of the old cloudkey and find another solution.

Copy link

ghost commented Jul 3, 2024

Thanks for the helpful information.

@drdaeman
Copy link

Thank you! This worked with 8.1.127, when I had to nuke the database.
I needed the ui_settings.dashboardConfig as explained above. I haven't noticed it before db.admin.insert so I had to do this:

db.dashboard.find();
db.admin.update({ name: "<USERNAME>" }, { $set: { "ui_settings" : { "dashboardConfig" : { "lastActiveDashboardId" : "<DASHBOARD_ID>", "dashboards" : { "<DASHBOARD_ID>" : { "order" : 1 } } } } } });

@calinorg
Copy link

Thanks man, you're a lifesaver.
After restoring access to unifi management page, i did a "Restore Device" once again which finally worked like a charm, and got my sites and all back.

Thanks again!

@FormadorLar
Copy link

FormadorLar commented Nov 7, 2024

thank you so much!! lifesaver!!

Also, you should update quickhash.com to https://www.dcode.fr/crypt-hashing-function

@Zippo2000
Copy link

Zippo2000 commented Feb 10, 2025

Did anything change for current unifi versions (Network 9.0.114, Unifi OS UDM Pro SE 4.1.13)?

History:

  • I am not able to login to web ui with the initial set up admin account.
  • The second configured account (super user; my mailadress and full name) is also not working for web ui.
  • BUT I can log in with a nickname (I don't know where this nickname is stored, did also not find it in mongodb) and the password from super user account -> it seems that then I am logged in with super user account
  • SSH is working

I tried the steps from above (incl. the hint with ui_settings...) with no luck:
I was able to set a password for admin account (x_shadow was empty before), I corrected the privileges, I added the ui_settings - but no login is possible.

To be honest, it seems that changing anything in this db does not have any effect.

I am grateful for any help.

@tr3nt1337
Copy link

@Zippo2000 In my case, it looks like the moved these settings into a Postgres database.

I was able to recover my user by connecting to my UDM via SSH. From there I started a psql session with the user postgres.
You'll find a database called ulp-go and a table user. It seems they changes the algorithm used to hash the password. You can use this online tool to generate a new Argon2 password hash: https://argon2.online

image

@Zippo2000
Copy link

@Zippo2000 In my case, it looks like the moved these settings into a Postgres database.

@tr3nt1337 thank you very much for that hint! But - I need further assistance. I'm totally new to psql (to be honest, no further experience with databases at all).

I managed to start via psql -U postgres
Connect to database \c ulp-go
Display the table \d user
With SELECT login FROM public.user; and SELECT password FROM public.user; I got three entries each. How do I find out what the correct user is?

What is the correct command to set the new password?

Thank you very much for your help!

@tr3nt1337
Copy link

@Zippo2000 Not quite sure how to figure out the user names. I know the MongoDB contains some cleartext names. I manages to figure out the user by comparing the unqiue_ids with the entries in the MongoDB collection admin.

So in user SSH session execute mongo --port 27117 ace --eval "db.admin.find().forEach(printjson);" | less. This way you are able to easily search for the fields you are looking for. Now, in your less session, execute a search for fields called uid by entering /uid. Less will jump to the first finding of the string uid. By typing n you can jump to the next finding. By typing N (UPPER CASE) you can jump to the previous one. Somewhere around the uid field you will see a field called name. If you got your account, copy the value of uid.

Back in psql:

To update the row you can use a simple UPDATE query.
UPDATE public.users SET password = 'YOUR-HASH-GOES-HERE' WHERE unique_id = 'YOUR-USERS-ID-GOES-HERE';

@Zippo2000
Copy link

@tr3nt1337 Wow, success! Thank you for your detailed description!

May I buy one beer for you? :-)

@tr3nt1337
Copy link

@Zippo2000 No need for that, glad I was able to help you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment