Skip to content

Tailscale — mihomo

mihomo can join a Tailscale tailnet as a userspace node and route traffic through it, all from within the proxy config. The node runs entirely in userspace (gVisor-backed), so no kernel TUN device or system Tailscale daemon is required. Point control-url at a self-hosted Headscale to use it with an alternative coordination server.

Outbound

Entry under proxies: with type: tailscale. Embeds BasicOption (common outbound fields).

FieldTypeDefaultAllowed valuesDescription
namestring(required)<string>Unique proxy name.
hostnamestring(unset)<string>Node hostname to register on the tailnet.
auth-keystring(unset)<auth key>Tailscale auth key for headless (non-interactive) login.
control-urlstring(Tailscale default)<URL>Coordination-server URL; set this to point at a self-hosted Headscale instead of Tailscale's default.
state-dirstringtailscale<directory path>Directory where the node persists its state/keys.
ephemeralboolfalsetrue | falseRegister as an ephemeral node that is removed automatically when offline.
udpboolfalsetrue | falseAllow UDP traffic.
accept-routes*bool(unset)true | falseAccept subnet routes advertised by other tailnet nodes.
exit-nodestring(unset)<node name or IP>Use this tailnet node (name or IP) as an exit node.
exit-node-allow-lan-access*bool(unset)true | falsePermit direct LAN access while routing through an exit node.

Source: adapter/outbound/tailscale.go:52-65 · pinned at v1.19.27 (5184081)

Examples

Minimal outbound joining a tailnet with a headless auth key:

yaml
proxies:
  - name: ts
    type: tailscale
    auth-key: tskey-auth-xxxxxxxxxxxx

Routing all traffic through a tailnet exit node:

yaml
proxies:
  - name: ts-exit
    type: tailscale
    auth-key: tskey-auth-xxxxxxxxxxxx
    hostname: mihomo-node
    exit-node: us-exit-1
    exit-node-allow-lan-access: true
    accept-routes: true
    udp: true

Against a self-hosted Headscale coordination server:

yaml
proxies:
  - name: ts-headscale
    type: tailscale
    auth-key: <headscale pre-auth key>
    control-url: https://headscale.example.com
    state-dir: tailscale-state

Notes

  • auth-key enables headless (non-interactive) login — required for an unattended node. Without it the node cannot authenticate on its own.
  • state-dir defaults to tailscale and is resolved relative to the mihomo working directory. The node persists its keys and machine identity there, so reusing the same directory keeps the same tailnet identity across restarts.
  • ephemeral: true registers a node that the coordination server removes automatically once it goes offline — handy for short-lived or containerized instances that should not linger in the tailnet device list.
  • exit-node accepts either a node name or an IP. When it names a real peer (rather than an auto-selection expression), mihomo waits for the tailnet backend to reach the running state before applying the exit-node preference.
  • accept-routes is opt-in: subnet routes advertised by other nodes are ignored unless you enable it.

Cross-core notes

  • sing-box exposes Tailscale as an endpoint type rather than an outbound — it lives under endpoints[], alongside WireGuard, with snake_case field names.
  • Xray-core has no Tailscale support.

Source: adapter/outbound/tailscale.go:52-65 · v1.19.27 (5184081)

Core Tutorial by Argsment