GitHub Sync Guide
Last updated: 2026-09-22. Applies to Ubicon 0.3.0 and later.
GitHub sync is an optional feature of Ubicon. It keeps your icon assignments and custom icons in a private GitHub repository that you own, and every browser you connect stays in step through it. This page is the full reference: how it works, what the different tokens mean, what happens in every situation we could think of, and what to do when something goes wrong. If you only want to set it up, the wizard in Ubicon's options page walks you through it in about three minutes and you do not need to read any of this first.
What it is, and is not
- Optional and off by default. Until you set it up, Ubicon never contacts GitHub and works exactly as it always has: assignments in your browser's own sync storage, custom icons on the machine where you uploaded them.
- Your repository, your account. The data lives in a private repository in your own GitHub account. Ubicon has no server. The author of Ubicon never sees your data and cannot reach your repository.
- No item limit. Browser sync storage stops at about 500 assignments. A browser connected to GitHub sync does not have that limit.
- Custom icons sync too. Without GitHub sync they stay on the machine where you uploaded them.
- Any mix of browsers. Chrome, Edge and Firefox all connect to the same repository, signed in to the browser or not.
- A plain, readable file. The repository holds an ordinary JSON file and PNG images. You can open them on github.com, and GitHub keeps a history of every change.
- Not encrypted. The file lists MAC addresses and the icons you chose for them. Keep the repository private.
- Not a backup you have to manage. Every connected browser keeps a full local copy. Losing a token or a browser never loses the data; the repository is always there to reconnect to.
Setting it up
Open Ubicon's options page (click the toolbar icon, then Set up GitHub sync, or right-click the icon and choose Options). The wizard has three steps. Each opens the right GitHub page with everything filled in that GitHub allows a link to fill in.
- Create your private repository. Click Open GitHub. The page is already filled in: the name
ubicon-sync, a description, and Private selected. Click Create repository. The repository is copied from a small starter that contains only a README explaining what the repository is for. - Create your access token. Click Open GitHub. The token's name, description, "No expiration" and the Contents permission (Read and write) arrive filled in. One thing GitHub cannot fill in from a link: under Repository access, change All repositories to Only select repositories and pick
ubicon-sync. Then click Generate token and copy it. GitHub shows a token only once. - Paste the token into Ubicon and click Connect. Your browser asks once for permission to talk to api.github.com; allow it. Ubicon then checks the token, finds your repository, confirms the token reaches nothing else, and uploads whatever this browser already has. The success screen shows a setup code for your other browsers.
If a check fails, the wizard turns that line into a fix card that says exactly what to change on GitHub. Your token stays in the field, so you fix it on GitHub and click Connect again. You never start over.
You need a GitHub account. A free one is enough. If you do not have one, the wizard's intro links to the sign-up page.
Tokens
The token is what lets Ubicon read and write your repository. Everything about who can do what to your synced icons comes down to which tokens exist and what each one is allowed.
Fine-grained, not classic
GitHub has two kinds of personal access token. Ubicon only accepts fine-grained tokens (they start with github_pat_), because only those can be limited to a single repository. A classic token (starting with ghp_) can only be granted to all of your repositories at once, so Ubicon refuses it and points you back to the token step.
Read and write, or read-only
The token's Contents permission decides what a browser can do:
- Read and write is the normal token. A browser using it can assign, change and remove icons, and everything it does reaches every other connected browser.
- Read-only makes a view-only browser. It shows the icons and receives updates, and cannot change anything.
Expiry
The wizard's link asks GitHub for a token with no expiration, so there is no yearly renewal to remember. If you would rather it expire, change the expiration on the GitHub page before generating it. Ubicon reads the expiry date from GitHub and shows a warning in the popup and the options page starting 14 days before. When a token expires, that browser keeps its icons and stops syncing until you paste a new token under Manage, Replace token.
Only select repositories
Ubicon refuses any token that can reach a repository other than ubicon-sync, with no way to override it. A token left on "All repositories" would let anyone holding it, or your setup code, read every private repository you own and write to all of them. The check works like this:
- Ubicon asks GitHub which repositories the token can see. A token limited to selected repositories is shown only the private repositories it was selected on, so any other private repository in the list means the token was left too broad.
- GitHub shows your public repositories to every token, whether or not the token was granted on them, so those cannot be judged from the list alone. Ubicon probes one of them with a request that only succeeds for a token that was granted on that repository. If it succeeds, the token reaches all of your public repositories too, and it is refused.
- The check runs when you connect, when you replace a token, and once a day after that. If a token's reach grows later, syncing pauses, your icons stay, and the options page shows what to fix. Syncing resumes on its own once the token is corrected.
The one case Ubicon cannot tell apart at setup time is an account whose only repository is ubicon-sync with a token left on "All repositories": there is nothing else for the token to reach yet. The daily check catches it as soon as another repository exists.
Fixing a token without starting over
Editing a fine-grained token on GitHub keeps its value. If Ubicon refuses a token because it reaches other repositories, open your tokens on GitHub, open the token, click Edit, set Repository access to Only select repositories, pick ubicon-sync, click Update, and then click Connect in Ubicon again with the same token.
Several tokens at once
Tokens are independent. Creating a new token does not affect an old one, and disconnecting a browser changes nothing on GitHub. So if one browser uses an older token and you create a new one for another browser, both keep working. A browser only needs a new token when the token it holds is deleted on GitHub: it then reports "GitHub rejected the token", keeps its icons, and waits for Replace token.
If a token leaks
A token limited to ubicon-sync lets its holder read and change the icons in that repository and nothing else in your GitHub account. If you think one has leaked, delete it on GitHub. Every browser using it stops syncing at its next attempt and keeps its icons; give each a new token with Replace token. GitHub's history lets you see and undo any change that was made in the meantime (see What is in the repository).
View-only tokens
A token created with Contents set to Read-only gives a view-only browser. Read this section before using one, because it works differently from a normal connection in one important way.
- The browser shows the icons from the repository and picks up every change made elsewhere.
- It cannot assign, change or remove icons. The assign button on the UniFi page and the remove buttons in the popup show a notice instead.
- Its own local icons do not survive. Any icons assigned in that browser before connecting are replaced by the repository's on the first sync. There is no way for a view-only browser to keep icons of its own alongside the shared ones, because nothing it holds can ever reach the repository, and a browser that shows something different from everyone else is exactly what sync exists to prevent. Export a backup first if you want to keep them.
- A view-only browser cannot start an empty repository. The first browser you connect has to use a Read and write token.
- A setup code made from a view-only browser starts the next browser view-only as well.
- To turn a view-only browser into a normal one, replace its token with a Read and write token under Manage.
View-only is for someone who should see your icons and never change them: a colleague who watches the console, or a second machine you want kept identical without any risk of an accidental edit. It is not for keeping a separate personal set of icons; use a normal connection or stay disconnected for that.
The setup code
The setup code is a single line starting with ubicon1. that bundles the repository name and the token, so another browser can join with one paste instead of the three wizard steps. It also carries the view-only flag when it comes from a view-only browser.
- It contains your token. Anyone with the code can connect a browser to your repository with the same rights as the token. Treat it like a password.
- Where to find it. On the success screen after connecting, and any time later under Manage, Show setup code. It is hidden until you click Show.
- Copy or Download. Copy puts it on the clipboard. Download saves
ubicon-setup-code.txt, a small text file with the code and a note on what it is for and how to guard it, the way sites hand out backup codes when you turn on two-factor sign-in. Keep the file somewhere private, such as a password manager. - Using it. On the other browser, open Ubicon's options, click I have a setup code, paste, Connect. The same checks run as in the wizard.
- You can also just paste the token. The wizard's third step accepts the raw token on any browser and finds your repository by name. The setup code is a convenience, not the only way in.
- If it leaks, delete the token it contains on GitHub. The code is then useless.
Multiple browsers
- Each browser is connected on its own. Connecting one does nothing to the others. A browser you have not connected keeps working exactly as before, using your browser's own sync storage, with no change and no prompts.
- Any mix. Chrome, Edge, Firefox and Brave can all be connected to the same repository. Whether the browser is signed in to a Google or Mozilla account makes no difference; GitHub sync does not use browser sync.
- Joining later merges, it does not replace. When a browser with existing assignments connects with a normal token, its assignments and the repository's are merged. For a device assigned differently in both places, the newest change wins. Nothing is thrown away except where the same device was changed on both sides.
- Browser sync users get a heads-up. If you are signed in to your browser's sync, connecting one browser leaves a small note in browser sync storage (the repository name, the time, and a label like "Chrome on Windows", never the token). Your other browsers of the same kind on that account then show a notice offering to connect, with an Enter setup code button and a Dismiss button. It is only a suggestion; nothing is blocked. The note travels only as far as your browser's sync does, so a Firefox install never hears about a Chrome setup.
- Drift. Once one browser is connected, changes made there no longer reach unconnected browsers through browser sync, and changes made in unconnected browsers do not reach the repository. They will merge when that browser connects. Connect all the browsers you use, or none.
How syncing works
- When it runs. When the browser starts, every five minutes, about ten seconds after you change an icon, and whenever you click Sync now. A browser that is not connected makes no requests at all.
- Newest change wins. Every assignment carries the time it was last changed. When two browsers changed the same device, the later change wins everywhere. If two changes carry the same time, which happens mostly for data carried over from versions before 0.3.0, whatever is already in the repository wins, so every browser ends up identical.
- Removals travel too. Removing an icon leaves a small marker so the removal beats an older assignment still held elsewhere. Markers are kept for 30 days. A browser that has been offline for longer than that and still holds the old assignment can bring it back; remove it again if that happens.
- Two browsers writing at once. GitHub refuses a write based on an out-of-date version of the file. Ubicon then reads again, merges, and writes once more. Nothing is lost.
- Custom icons. Each custom icon is one PNG file in the repository, uploaded once when it is first assigned and downloaded once by each browser that needs it. The manifest only refers to it by name, so it stays small.
- Clock skew. Because the newest change wins, a machine whose clock is badly wrong could always win or always lose. Ubicon compares each machine's clock against GitHub's and corrects the timestamps it writes when the difference is more than a minute.
- Offline. Changes made while offline are kept and pushed at the next successful sync. The popup shows the last successful sync time.
- Import. Importing a backup file counts as a deliberate change, so every imported assignment is stamped with the current time and wins the next merge.
What is in the repository
README.md, from the starter, explaining what the repository is.ubicon.json, the manifest. It lists each assigned device by MAC address with the icon it got (a community database id, or the id and label of a custom icon) and the time of the last change, plus the removal markers. Keys are sorted and the file is indented, so GitHub's diffs stay readable.icons/, one PNG file per custom icon, named by its id.
Every sync is one commit, named for the browser that made it, so the repository's history shows what changed and when. Two things to know:
- Do not edit ubicon.json by hand. Ubicon merges by timestamp and will undo an edit that is older than what a browser holds. If the file is edited into something Ubicon cannot read, syncing stops with "the sync file could not be read" and nothing is overwritten until it is fixed.
- Restoring an older version. You can restore
ubicon.jsonto any earlier commit on github.com (open the file's history, open the old version, and commit it back). Connected browsers pick it up at their next sync. Because the restored entries carry their old timestamps, a browser holding a newer change for the same device will still win for that device; that is the merge doing its job.
Disconnecting and cleaning up
- Disconnect is under Manage on the options page. It affects that browser only: it pushes any pending change if the token still works, forgets the token, stops all contact with GitHub, and keeps every icon. The browser goes back to using its own sync storage. If it holds more assignments than browser sync storage can take (about 500), they stay in local storage on that machine instead, and Ubicon says so.
- The repository is never touched by Disconnect. Delete it yourself on GitHub if you no longer want the data there: repository Settings, Danger Zone, Delete this repository. Delete the token at github.com/settings/personal-access-tokens.
- Other browsers are not affected. They keep syncing with the repository until you disconnect each one.
- "Also stop suggesting GitHub sync on my other browsers" is a checkbox on the Disconnect panel. It removes the heads-up note from browser sync storage. Leave it unticked if other browsers are still connected; tick it when you are turning sync off everywhere.
- Old copies in browser sync storage. When a browser connects, the assignments it had in browser sync storage are copied, not moved, and are left in place unchanged. That copy is what your unconnected browsers keep using, so Ubicon never deletes it.
Sharing with other people
- One token per person. Create a separate token for each person (same settings as the wizard, or Read-only for view-only) and give each a setup code made from their own token. To remove someone, delete their token on GitHub; nobody else is affected. If several people share one token, deleting it cuts them all off at once.
- There are two roles, and GitHub enforces them. A Read and write token can do everything Ubicon can do: assign, change and remove icons. A Read-only token can only view. There is no in-between; GitHub has no permission for "may add but may not remove". Anyone who can change icons can also remove them, and the repository's history is how you see who did what and undo it.
- The owner is the GitHub account. Whoever owns the repository creates and deletes tokens and can restore any earlier version. That is the only administrator there is. Ubicon adds no accounts, roles or passwords of its own.
- What a teammate cannot do. A token limited to
ubicon-syncgives no access to anything else in the owner's GitHub account, and nothing in Ubicon lets one browser disconnect another or touch another person's browser. - When someone leaves, they have normally lost access to the UniFi console as well, and their copy of the icons is of no use without it. Delete their token so they stop receiving updates.
Privacy and security
- What leaves the machine. The MAC address of each assigned device, which icon it got, the label of each custom icon, the custom icon images, and the time of each change. That is all.
- What never leaves. Device names read from UniFi, IP addresses, console addresses, anything from UniFi itself, and anything about devices you have not assigned an icon to.
- Where the token lives. In the extension's local storage on that one machine, unencrypted, like every browser extension that holds a token. It is sent only to api.github.com and never placed in browser sync storage, never logged, and never shown in an error message.
- The repository is not encrypted. Anyone who can open it can read the MAC addresses and icon choices. Keep it private. GitHub's own privacy policy covers what is stored with them, and GitHub staff can in principle access private repositories under their terms.
- Firefox asks for a data permission. Firefox requires extensions to declare what data they send off the machine. When you connect on Firefox, its prompt covers access to api.github.com and one data category, for the MAC addresses and labels in the synced file. Nothing is sent unless you connect.
- Nothing goes to the author. Ubicon has no server, no analytics and no telemetry. The full policy is on the privacy page.
Troubleshooting
While connecting
- "This token can reach N other repositories." Repository access was left on All repositories, or extra repositories were selected. On GitHub, open the token, click Edit, set Repository access to Only select repositories, pick
ubicon-sync, click Update. Then click Connect again; the same token works. - "GitHub rejected the token." It was mistyped, has expired, or was deleted. Generate a new one from the wizard's token step, or if the GitHub page showing the token is still open, copy it again.
- "The token works but cannot see ubicon-sync." Either the repository was not created (go back to step 1), it was not selected on the token (edit the token), or it has a different name. Type the name as
owner/namein the field the wizard reveals. A repository just created from the starter can take a few seconds to appear; Ubicon retries once by itself. - "This is the older kind of token." You pasted a classic token. Go back to step 2 and create a fine-grained one.
- "This is a view-only token and the folder is still empty." The first browser has to use a Read and write token.
- "Ubicon needs permission to talk to api.github.com." The browser's permission prompt was declined. Click Connect and choose Allow.
- "Could not reach GitHub." Check the connection and try again.
- "GitHub asked us to slow down." The rate limit was reached. Wait a few minutes.
While connected
- "Paused: the token reaches other repositories." The daily check found that the token's access grew. Your icons are untouched. Fix the token on GitHub as above; syncing resumes on its own.
- "GitHub rejected the token." It was deleted or expired. Manage, Replace token.
- "The sync file could not be read."
ubicon.jsonwas edited into something invalid. Restore an earlier version from the repository's history on github.com. Ubicon never overwrites a file it cannot read. - "Your token expires on ..." Create a new token and use Replace token before that date. Nothing is lost if you miss it; syncing just pauses until you do.
- Icons missing in one browser. Click Sync now there. If a custom icon shows as "icon missing here", the image has not been downloaded yet; the next sync fetches it.
- The repository was renamed or moved. Ubicon reports it cannot see the repository. Rename it back, or disconnect and connect again with the new
owner/name. - The repository was made public by accident. Make it private again in its Settings. The MAC addresses and icon choices were readable in the meantime; the file holds no credentials.
- An icon came back after being removed. A browser offline for more than 30 days still held it. Remove it again.
Limits
- Rate limits. GitHub allows 5,000 requests an hour per token. A connected browser uses one request per five-minute check when nothing changed, which GitHub does not count, and a handful when something did. You will not get near the limit in normal use.
- Size. The manifest is read whole; up to about 8,000 assignments fit comfortably. Custom icons are capped at 256 KB each; Ubicon resizes uploads well under that.
- No encryption. See Privacy and security.
- No partial sync. A connected browser syncs all of its assignments; you cannot choose a subset.
- No undo inside Ubicon. Undo is done through the repository's history on github.com.
- One repository per browser. A browser connects to one repository at a time.
Questions
Anything this page does not answer can be raised as an issue at github.com/tvirelli/Ubicon/issues.