ruOS × TailscaleOAuthAuth keySubnet routes
A connection story · 01 / 07

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.

This guide follows a working ruOS setup verified on October 7, 2026. Console behavior may change. A saved credential is not proof of a connected desktop.

Scroll to follow the path from credential to connection to private subnet access.

Before either method · 02 / 07

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.

Run once on the ruOS desktop
sudo tailscale set --operator=ruv

This makes ruv the Tailscale operator without granting general root access. It fixed our console auth-key connection.

Not specific to auth keys. OAuth also ultimately runs a desktop join. If ruOS runs that command as ruv, the same permission requirement applies. A future ruOS image may configure this automatically.
Verify the saved setting
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.

Preferred path · 03 / 07
OAuth client

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.

  1. Open Tailscale admin → Settings → Trust credentials. Create an OAuth credential, or edit your existing one.
  2. Under Keys → Auth Keys, enable Write. Select the tag within this scope, for example tag:mfj.
  3. Keep the client ID and secret. A new secret is shown only at creation.
  4. In ruOS → Network → OAuth client, enter the ID, secret, and exactly tag:mfj, then click Connect.
Auth Keys ≠ OAuth Keys. 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.

Alternative path · 04 / 07
Auth key

One key.
A simpler first connection.

  1. Ensure the operator setting from chapter 2 is configured on the ruOS desktop.
  2. Open Tailscale admin → Settings → Keys and generate an auth key.
  3. Choose Reusable if ruOS will use it for multiple provisioning attempts or desktops. Set an appropriate expiry.
  4. 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.
  5. 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.

The console reports “Saved (write-only)” because the credential cannot be read back. Follow that with a real connection check.
Connection check · 05 / 07

“Saved” is not “connected.”

The Network page should show a tailnet IP, desktop name, and peers. Verify the daemon too:

Run on the ruOS desktop
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.

Inspect the daemon mode
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.

Beyond the tailnet IP · 06 / 07

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.

  1. On the subnet router, advertise 10.0.0.0/24 and configure IP forwarding as required by its OS.
  2. Approve the advertised route in Tailscale’s admin console, unless an auto-approver handles it. Access rules must allow the traffic.
  3. On your ruOS desktop, accept subnet routes:
Run on ruOS, not the subnet router
sudo tailscale set --accept-routes=true
The ruOS Connect workflow we tested sets --accept-routes=false. Enable it again after reconnecting through the console. Opening or refreshing the console does not itself disable routes.
Verify and test a known LAN device
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.

Keep the evidence · 07 / 07

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.

Live daemon log on our modified desktop
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.

Your connection checklist