Tailscale - Complete API Reference
Share local services via Tailscale Serve (private) and Funnel (public internet access).
Chat Commands
Share Local Services (Private)
/tailscale serve 3000 Share port on tailnet /tailscale serve 3000 --path /api Share at specific path /tailscale serve stop 3000 Stop sharing port /tailscale serve status View active shares
Public Access (Funnel)
/tailscale funnel 3000 Expose to internet /tailscale funnel 3000 --https Force HTTPS /tailscale funnel stop 3000 Stop public access /tailscale funnel status View funnels
Network Status
/tailscale status Network status /tailscale ip Show Tailscale IP /tailscale peers List connected peers /tailscale ping <peer> Ping a peer
File Transfer
/tailscale send <file> <peer> Send file to peer /tailscale receive Receive incoming files
TypeScript API Reference
Create Tailscale Client
import { createTailscaleClient } from 'clodds/tailscale';
const tailscale = createTailscaleClient({ // Auth (optional if already logged in) authKey: process.env.TAILSCALE_AUTHKEY,
// Socket path socketPath: '/var/run/tailscale/tailscaled.sock', });
Serve (Private Sharing)
// Share local port on tailnet await tailscale.serve({ port: 3000, protocol: 'https', // 'http' | 'https' });
console.log(Shared at: https://${tailscale.hostname}:3000);
// Share at specific path await tailscale.serve({ port: 8080, path: '/api', protocol: 'https', });
// Share with custom hostname await tailscale.serve({ port: 3000, hostname: 'clodds', // clodds.tailnet-name.ts.net });
// Stop sharing await tailscale.serveStop(3000);
// Get serve status
const serves = await tailscale.serveStatus();
for (const serve of serves) {
console.log(Port ${serve.port} → ${serve.url});
}
Funnel (Public Internet)
// Expose to public internet await tailscale.funnel({ port: 3000, protocol: 'https', });
console.log(Public URL: https://${tailscale.hostname}.ts.net);
// With custom domain (if configured) await tailscale.funnel({ port: 3000, hostname: 'api.example.com', });
// Stop funnel await tailscale.funnelStop(3000);
// Get funnel status
const funnels = await tailscale.funnelStatus();
for (const funnel of funnels) {
console.log(Port ${funnel.port} → ${funnel.publicUrl});
}
Network Status
// Get status const status = await tailscale.status();
console.log(Hostname: ${status.hostname});
console.log(IP: ${status.ip});
console.log(Tailnet: ${status.tailnet});
console.log(Online: ${status.online});
// List peers
const peers = await tailscale.peers();
for (const peer of peers) {
console.log(${peer.hostname} (${peer.ip}));
console.log( OS: ${peer.os});
console.log( Online: ${peer.online});
console.log( Last seen: ${peer.lastSeen});
}
// Ping peer
const ping = await tailscale.ping('other-machine');
console.log(Latency: ${ping.latencyMs}ms);
File Transfer
// Send file to peer await tailscale.sendFile({ file: '/path/to/file.zip', peer: 'other-machine', });
// Receive files (returns when file received) const received = await tailscale.receiveFile({ savePath: '/downloads', timeout: 60000, });
console.log(Received: ${received.filename});
console.log(From: ${received.sender});
console.log(Size: ${received.size} bytes);
Get Tailscale IP
const ip = await tailscale.getIP();
console.log(Tailscale IP: ${ip}); // 100.x.x.x
Serve vs Funnel
Feature Serve Funnel
Access Tailnet only Public internet
Auth Tailscale identity None (public)
URL machine.tailnet.ts.net machine.ts.net
Use case Internal tools Public APIs
URL Formats
Type Format
Serve https://machine.tailnet-name.ts.net:port
Funnel https://machine.ts.net
Custom domain https://your-domain.com
Use Cases
Share Dev Server
// Share local dev server with team await tailscale.serve({ port: 3000 }); // Team can access at https://your-machine.tailnet.ts.net:3000
Expose Webhook Endpoint
// Make webhook publicly accessible await tailscale.funnel({ port: 3000, path: '/webhooks' }); // External services can POST to https://your-machine.ts.net/webhooks
Share Bot with Phone
// Access bot from phone while away from desk await tailscale.serve({ port: 18789 }); // Open https://your-machine.tailnet.ts.net:18789/webchat on phone
Requirements
-
Tailscale installed and running
-
Logged into a Tailnet
-
For Funnel: Funnel enabled in Tailscale admin
Best Practices
-
Use Serve for internal — Keep private services private
-
Use Funnel sparingly — Only for truly public endpoints
-
Add authentication — Funnel bypasses Tailscale auth
-
Monitor access — Check who's connecting
-
Stop when done — Don't leave services exposed