Your desktop.
Your tailnet.
Connect “My ruOS Desktop” to your own Tailscale network, then make that connection useful.
Two credentials lead to the same destination. OAuth is preferred for ongoing provisioning; an auth key is a simpler way to begin.
Scroll to follow the path from credential to connection to private subnet access.
Give the join command permission.
The console can save a credential successfully while its desktop-side command fails. In our test, the desktop user ruv lacked permission to control Tailscale.
sudo tailscale set --operator=ruv
This makes ruv the Tailscale operator without granting general root access. It fixed our console auth-key connection.
ruv, the same permission requirement applies. A future ruOS image may configure this automatically.tailscale debug prefs | grep '"OperatorUser"'
Expected: "OperatorUser": "ruv". Settings persist while the desktop’s Tailscale state is retained; a new desktop needs its own setup.
The right scope.
The exact tag.
ruOS uses your OAuth client to mint a short-lived device auth key. Its client secret stays in ruOS’s server-side credential store rather than being placed on the desktop.
- Open Tailscale admin → Settings → Trust credentials. Create an OAuth credential, or edit your existing one.
- Under Keys → Auth Keys, enable Write. Select the tag within this scope, for example
tag:mfj. - Keep the client ID and secret. A new secret is shown only at creation.
- In ruOS → Network → OAuth client, enter the ID, secret, and exactly
tag:mfj, then click Connect.
auth_keys permits creating device login keys. oauth_keys manages OAuth credentials and does not grant that permission. Our HTTP 404 minting failure disappeared after adding Auth Keys Write and the tag.If the tag isn’t available, define its owner in Tailscale’s access policy first. A tag existing elsewhere on the tailnet is not enough: the OAuth client must be authorized to use it.
One key.
A simpler first connection.
- Ensure the operator setting from chapter 2 is configured on the ruOS desktop.
- Open Tailscale admin → Settings → Keys and generate an auth key.
- Choose Reusable if ruOS will use it for multiple provisioning attempts or desktops. Set an appropriate expiry.
- Choose Ephemeral for disposable desktops. Leave it off when you want a persistent device identity. If your tailnet requires device approval, choose preauthorization when appropriate.
- In ruOS → Network → Auth key, paste the
tskey-auth-…value and click Connect.
The key is a credential, so enter it only in the console—not in this guide. It may expire or be revoked; OAuth avoids repeatedly creating replacement auth keys.
“Saved” is not “connected.”
The Network page should show a tailnet IP, desktop name, and peers. Verify the daemon too:
tailscale status tailscale ping <peer-name-or-100.x.x.x>
tailscale ping tests communication between Tailscale daemons. A relay response is a working connection; a direct path is not required.
Connected, but Chrome or ordinary ping fails?
Check the networking mode. Our vanilla startup used --tun=userspace-networking with no proxy configured. That can join a tailnet, but ordinary applications need a SOCKS5/HTTP proxy—or normal TUN networking.
ps -eo args | grep '[t]ailscaled'
For this desktop, we verified TUN support and changed the daemon to --tun=tailscale0. That was a separate application-access fix, not a requirement for OAuth authentication. Image updates may overwrite a local startup-script modification.
Need the network
behind a machine?
A peer’s 100.x.x.x address is already on Tailscale. An address such as 10.0.0.3 is on a private LAN and needs an advertised subnet route.
- On the subnet router, advertise
10.0.0.0/24and configure IP forwarding as required by its OS. - Approve the advertised route in Tailscale’s admin console, unless an auto-approver handles it. Access rules must allow the traffic.
- On your ruOS desktop, accept subnet routes:
sudo tailscale set --accept-routes=true
--accept-routes=false. Enable it again after reconnecting through the console. Opening or refreshing the console does not itself disable routes.tailscale debug prefs | grep '"RouteAll"' ping -c 4 10.0.0.3 nc -vz 10.0.0.3 443
"RouteAll": true means route acceptance is enabled. Replace the example IP and port with a real service. You don’t need this setting just to reach a peer’s Tailscale IP. The Network page we inspected had no route toggle; use the desktop terminal or console Terminal.
Find the stage
that failed.
“Could not mint a key” / HTTP 404
This is before the desktop join. Check Auth Keys Write, the client’s permitted tag, the client ID/secret, and ruOS’s API request. In our case, correcting the scope and tag fixed it. The detailed minting log belongs to the ruOS server; it isn’t in the desktop daemon log.
“Joining…” forever / access denied
Check tailscale status and OperatorUser. We reproduced “checkprefs access denied” as ruv; granting operator permission allowed the console to start the daemon.
“Mention all non-default flags”
tailscale up can reject a command that omits existing custom settings. ruOS must preserve or explicitly supply those settings. Inspect the error before changing them; don’t blindly reset your configuration.
Tailscale ping works; application access fails
Check userspace versus TUN mode, application proxy settings, destination service, and access rules. Daemon connectivity alone does not prove the service is reachable.
LAN addresses fail after reconnecting
Check RouteAll, route approval, router forwarding, and access policy. Re-enable --accept-routes=true on ruOS if Connect disabled it.
sudo tail -f /tmp/tailscaled-kernel.log
The original userspace daemon used /tmp/tailscaled.log. These paths are specific to this ruOS setup. For OAuth token creation, also check Tailscale → Logs → Configuration audit logs.