cloudkey is a replacement for /usr/bin/ck-ui on your Ubiquiti Cloud Key
Generation 2 device: a small Go daemon that drives the front-panel OLED
display and status LEDs directly, without the stock UI.
The display cycles through these screens, fading in and holding each one lit before fading to a genuinely black, held-blank state (real rest time for the OLED panel) between screens.
WireGuard and Tailscale check actual tunnel liveness rather than the
systemd unit state of the underlying service: wg-quick@<iface> is
typically a one-shot unit that stays "active" forever once wg-quick up
succeeds, and tailscaled's unit reports "active" whenever the daemon
process is running, neither of which reflects the peer/tailnet actually
being reachable. So WireGuard status comes from a recent handshake
(wg show <iface> latest-handshakes), and Tailscale status comes from
tailscale status --json's BackendState.
autossh is the exception: -R (remote) forwards bind no local port to
probe, so without a -M monitor port there's no local traffic signal to
check at all. autossh status therefore falls back to systemctl is-active <unit> — which only proves the autossh/ssh process is still running, not
that the tunnel is passing traffic. Pair each tunnel's ssh config with
ServerAliveInterval/ServerAliveCountMax so a genuinely dead connection
makes the process exit (and the unit go inactive) instead of hanging open
indefinitely; without that, a stale tunnel can still show as "up".
After boot, the status LED is blue while the daemon is idle. With -speedtest
enabled, it blinks blue while a speed test is running. When
-reset-button-cmd is configured, a physical reset-button press blinks it
white (a 300ms fade up, 300ms fade down) as acknowledgment, then returns to
blue.
- Turn on SSH from the Unifi Console
ssh root@UniFi-CloudKeyG2- Download the latest
cloudkeybinary from the Releases page and copy it to/usr/local/bin/cloudkey. - Continue with Using the
systemdService below. It disables the stock service without removing its binary, so you can restore it if needed.
Disable the old service first.
systemctl disable ck-uisystemctl stop ck-ui
Install this one.
- Copy
cloudkey.serviceto/lib/systemd/system/and ensure the downloaded or built binary is at/usr/local/bin/cloudkey. touch /etc/cloudkey.envand set any flags you need as environment variables (see Configuration below).systemctl daemon-reloadsystemctl enable cloudkeysystemctl start cloudkey
- Have a working Go environment (see
go.modfor the minimum version). make build— cross-compiles for the Cloud Key'slinux/armtarget and writes the binary to.local/bin/cloudkey.- SCP the file over to your Cloud Key, or use
make deployif you've setDEPLOY_HOST/DEPLOY_KEYin theMakefilefor your device.
At this point, you can choose to back up and overwrite the /usr/bin/ck-ui
file or install the systemd service above, depending on your Linux
experience.
Every flag can also be set via an environment variable — useful for
/etc/cloudkey.env under systemd. Env vars are the flag name uppercased,
with dashes replaced by underscores, prefixed with CLOUDKEY_.
| Flag | Env var | Default | Description |
|---|---|---|---|
-delay |
CLOUDKEY_DELAY |
5000 |
Milliseconds each screen stays lit |
-blank-delay |
CLOUDKEY_BLANK_DELAY |
3000 |
Milliseconds screens stay blanked between screens |
-demo |
CLOUDKEY_DEMO |
false |
Use fake screen data instead of network, storage, CPU/memory, and speed-test collection; the framebuffer and LEDs still require target hardware |
-speedtest |
CLOUDKEY_SPEEDTEST |
false |
Enable and display the speedtest screen |
-reset-button-cmd |
CLOUDKEY_RESET_BUTTON_CMD |
"" |
Shell command to run on a single physical reset-button press (empty disables the watcher) |
-pidfile |
CLOUDKEY_PIDFILE |
/var/run/cloudkey.pid |
Pidfile path |
-reset |
CLOUDKEY_RESET |
false |
Clear the screen and exit, instead of running normally |
-version |
CLOUDKEY_VERSION |
false |
Print version and exit |
-autossh-tunnel1-name |
CLOUDKEY_AUTOSSH_TUNNEL1_NAME |
"" |
Label for the first autossh tunnel; empty disables the autossh screen entirely |
-autossh-tunnel1-service |
CLOUDKEY_AUTOSSH_TUNNEL1_SERVICE |
"" |
systemd unit name to check for the first tunnel's liveness (e.g. autossh-tunnel1); empty always shows down |
-autossh-tunnel2-name |
CLOUDKEY_AUTOSSH_TUNNEL2_NAME |
"" |
Label for the second autossh tunnel; empty hides the second row |
-autossh-tunnel2-service |
CLOUDKEY_AUTOSSH_TUNNEL2_SERVICE |
"" |
systemd unit name to check for the second tunnel's liveness |
-wireguard-name |
CLOUDKEY_WIREGUARD_NAME |
WireGuard |
Display name for the WireGuard screen |
-wireguard-iface |
CLOUDKEY_WIREGUARD_IFACE |
"" |
WireGuard interface to check, e.g. wg0; empty disables the wireguard screen |
-wg-cmd |
CLOUDKEY_WG_CMD |
wg |
wg binary to run for WireGuard status checks; override if it's not on PATH |
-tailscale |
CLOUDKEY_TAILSCALE |
false |
Enable and display the Tailscale screen |
-tailscale-name |
CLOUDKEY_TAILSCALE_NAME |
TailScale |
Display name for the Tailscale screen |
-tailscale-cmd |
CLOUDKEY_TAILSCALE_CMD |
tailscale |
tailscale binary to run for Tailscale status checks; override if it's not on PATH |
If the wireguard or tailscale screen is enabled but its binary can't be found, cloudkey exits at startup with an error rather than silently showing "disconnected" forever — a missing dependency is a configuration error to fix, not a display state.
CLOUDKEY_WIREGUARD_NAME is just the label shown as the screen's title —
pick anything (it defaults to WireGuard). CLOUDKEY_WIREGUARD_IFACE
is not free text: it has to match the real interface name on the device
running cloudkey. To find it, run one of these on that device:
wg show interfaces # lists every active WireGuard interface
ip link show type wireguardIf the tunnel is managed by wg-quick (as wg-quick@<iface> under
systemd), the interface name is also the config file's name minus
.conf — /etc/wireguard/wg0.conf means wg0 — or you can read it
straight off the unit:
systemctl list-units 'wg-quick@*'See cloudkey.env.example for a starter /etc/cloudkey.env. Example:
CLOUDKEY_SPEEDTEST=true
CLOUDKEY_RESET_BUTTON_CMD=systemctl restart unifi
I am an edge case. I do not use my Cloud Key device for Unifi. I think it is a great sexy little hardware device, but to manage a network off of what is essentially a POE SDCard, you are insane.
Issues with stability are very well documented. Using mongodb on an sdcard (limited write cycles) without automatically reparing has lead me to have to recover 4 times in 2 years even with the secondary USB power from the UPS. That is NOT remotely production stable. Run Unifi on a server, not a "raspberry pi".
With that said, I am sure you are asking yourself "Why do you have it all?" The Ubiquity Cloud Key Gen2 is a POE, ARMv7, Single-Board-Computer with on-board battery backup and a 160x64 framebuffer display built-in. It is sexy, for under $200. It looks like an iDevice.
Sure, you can buy a $35 Raspberry Pi, add a case, with a touchscreen, with a power-supply, and blah blah, but I'll pay for quality and craftmanship so it does not look like another Frankenstein project around my house.
I can ship it to my parents, tell them to plug one cable into the new-fangled doo-hickey and tell them to call their ISP when it has a sad face on it (feature not developed yet).







