Tailscale serve vs funnel: which one you fit use?
Tailscale serve gives HTTPS for tailnet-only URL, while Funnel opens the port publicly. See the exact policy gate wey fit block Funnel.
tailscale serve vs funnel: who fit reach the URL
Difference between tailscale serve and tailscale funnel na who fit access am, and nothing else. serve dey put HTTPS (hypertext transfer protocol secure) front end for local port and publish am only to your tailnet. funnel dey publish that same local port to the whole public internet, through relay servers wey Tailscale dey run. Both commands dey take the same flags and the same targets. Na one word dey separate private dashboard from one wey the whole world fit reach.
Both go give you certificate wey browsers already trust, for name wey end with ts.net, and neither one need inbound port open for your VPS firewall. Your tailscaled daemon already get connection wey dey go out to the tailnet, so traffic dey arrive through that connection instead. To put server for the tailnet na one job, and run VPS as Tailscale exit node or advertise subnet router for private network cover that part. To publish service wey already dey on the tailnet na this other job.
Wetin you need before either command fit work
- Tailscale 1.38.3 or newer for the VPS, and e don log in to your tailnet. Check am with
tailscale versionandtailscale status. - MagicDNS don enable. MagicDNS na Tailscale built-in DNS (domain name system), and na am dey give the machine name like
blog-vps.your-tailnet.ts.netinstead make e get only100.xaddress. - HTTPS certificates don enable for the tailnet, for the DNS page of the admin console. Without this one, certificate no dey to put before your port.
- For
funnelonly, thefunnelnode attribute dey inside the tailnet policy file. Na here most first attempts dey stop, and we cover am below.
Every command here dey start with sudo, because the CLI dey talk to tailscaled through socket wey na root fit write to. Give one user permission to skip that:
sudo tailscale set --operator=$USERPublish to your tailnet with tailscale serve
Point serve to one local port, and e go handle the rest.
sudo tailscale serve 3000Available within your tailnet:
https://amelie-workstation.pango-lin.ts.net
|-- / proxy http://127.0.0.1:3000
Press Ctrl+C to exit.The bare 3000 na shorthand for http://127.0.0.1:3000. Tailscale dey listen on port 443 of the machine tailnet address, terminate TLS (transport layer security) with the ts.net certificate, then forward plain HTTP to your local port. Your application no need know say certificate dey exist. Na the main reason to use this in front of admin panel wey you for otherwise leave on plain HTTP.
Now read the last line: Press Ctrl+C to exit.. The command dey run for foreground, and the mapping dey inside that process. If you close the terminal, the URL go stop working because nothing write to disk. Add --bg, and the mapping go enter the node serve config. E go survive both the terminal and reboot.
sudo tailscale serve --bg 3000Serve fit take more than port number. --set-path mount service under subpath, so several apps fit share one hostname:
sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090The target fit also be directory of static files, or backend wey already dey speak TLS with certificate wey you no want check:
sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443E no stop for HTTP alone. --tcp=<port> forward raw TCP (transmission control protocol) stream, while --tls-terminated-tcp=<port> terminate TLS for your node and pass the plaintext onward. This puts trusted certificate in front of service wey no speak HTTP at all:
sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899Why Funnel dey talk say node attribute no set?
Funnel dey off for the whole tailnet by default. The first time you run am, e go print this message then stop:
Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.The command correct. Tailnet policy never give this node permission to publish, so client refuse before e even contact any relay. Edit tailnet policy file for admin console, under Access Controls, then add this attribute:
"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],autogroup:member go give every member of the tailnet this permission. If na only one machine suppose ever publish, tag that machine and target the tag instead, for example tag:public. Save the policy, then run the Funnel command again.
If your account na tailnet admin, recent clients get shortcut: CLI go print consent URL for login.tailscale.com. If you follow am, e go enable HTTPS certificates and add the attribute for you. If you no be admin, that URL no go help you. Person wey get policy access must make the edit.
Publish to the internet with tailscale funnel
Once you set the attribute, na the command wey you already know, but with another verb.
sudo tailscale funnel --bg 3000Available on the internet:
https://amelie-workstation.pango-lin.ts.net
|-- / proxy http://127.0.0.1:3000
Press Ctrl+C to exit.Read that first line every time. Available within your tailnet and Available on the internet na the only visible difference between private service and public one, and the commands wey produce dem differ by one word.
As of August 2026, funnel dey listen on port 443, 8443 or 10000, and no other port. The default na 443, while --https=8443 or --https=10000 na the alternatives. E go refuse any other port because funnel relays only accept connections on those ports. Na why funnel URL always be the bare hostname, or the hostname with :8443 join for the end.
How I fit see wetin dey published right now?
Guessing na how dashboard fit remain public for one month. Ask the node instead.
tailscale serve status
tailscale funnel status
tailscale serve status --jsonBoth status commands dey read the same config, so any one of dem go show you the complete picture. Use the --json form inside script or scheduled check, because plain output na for people to read. When nothing dey configured, you go get one line:
No serve configIf you see this after setup wey you know say work, e mean say the mapping happen for foreground and the process don disappear. Create am again with --bg.
To remove one mapping, repeat the command wey create am and put off for the end. To clear every serve and funnel mapping for the node, use reset.
sudo tailscale funnel --https=443 3000 off
sudo tailscale serve resetRun tailscale serve status again after any of dem and read wetin remain, instead make you assume say e do wetin you mean.
Wetin you gain, and wetin you give up
The benefits dey real, and na why people dey choose this instead of reverse proxy.
- Browser go trust the certificate, and e go renew am for you. You no need install ACME (automatic certificate management environment) client, and you no go forget renewal job.
- No inbound port for VPS firewall.
tailscaleddey dial out, so default-deny ufw firewall for your VPS fit remain as tight as before. - You no need buy, point, or wait for DNS record.
- You no need port forwarding. Na the main issue for machine wey dey behind NAT (network address translation), instead of VPS wey get public IP.
The costs dey real too, and funnel carry all of dem.
- The name no be your own. Public visitors go see
host.your-tailnet.ts.net. Funnel no support custom domain, so you no fit putapp.example.comin front of am. - The path no be your own. Traffic go first reach Tailscale relay, then the relay go proxy the stream to your node through the tailnet. Tailscale talk say funnel traffic get bandwidth limits wey dem never publish and wey you no fit configure, so measure your own throughput before you depend on any number.
- The controls no dey. Reverse proxy wey you run go give you access logs, rate limits, request size caps, and place to add authentication. Funnel go give you URL. Everything else must dey inside your application.
- The port list fixed, as e don talk before.
Both features still depend on infrastructure wey Tailscale dey operate: certificate issuance for the ts.net name, and the funnel relays themselves. If you dey consider self-hosted Headscale control server, no assume say either one go follow you. Check the release notes for the Headscale version wey you plan to run.
Which one I suppose use?
The rule short.
Use serve for anything wey stay internal: admin interfaces, dashboards, metrics UI wey you no want make search engines index, or staging copy of a site. Na membership of the tailnet be the access control, and e strong well. Device wey no dey for the tailnet no fit even resolve the name.
Use funnel for demo link, webhook receiver wey third party must POST to, or OAuth callback during development. Na the fastest way to get public HTTPS URL, and one off command go end am. Public mean public, though: hostname no be secret, and funnel wey dey in front of app without login na open service. Anything wey dey behind am must authenticate its own requests, with the same care wey exposed Ollama API endpoint need.
Use real reverse proxy for anything wey you go call production. Your domain, your certificate, your logs, your rate limits, and nobody else for the request path. Comparison of nginx, Caddy and Traefik as reverse proxy cover how to choose one.
Failure modes, wit di strings wey you go see
Funnel no gree start. Funnel not available; "funnel" node attribute not set. na policy problem, no be command problem. Add funnel attribute to the tailnet policy file, save am, then try again.
E work before, but now tailscale serve status dey talk say No serve config. Dem create the mapping for foreground, and that process don end. Run the same command again with --bg.
The name dey resolve, but nothing dey answer. Serve dey proxy to the target wey you name. So if nothing dey listen there, nothing dey proxy to. Confirm am with ss -ltnp | grep 3000 for the same machine wey dey run tailscaled. The common cause na say container publish its port for Docker bridge address instead of 127.0.0.1. This mean say host no see listener for the place wey you expect. How Docker Compose networking dey work show where published port actually land.
Certificate errors for ts.net name. E most likely mean say HTTPS certificates no enable for the tailnet. Turn am on for admin console, then run the certificate step by itself, so its errors no mix with serve output:
sudo tailscale cert your-host.your-tailnet.ts.netFunnel dey load for mobile data, but e dey behave differently from your laptop. Your laptop dey on the tailnet, so MagicDNS resolve the name to 100.x address, and you reach the service directly without touching relay. This na correct behaviour, and e mean say your laptop no fit test public reachability at all. Use curl from machine wey no dey on the tailnet.
FAQ
Wetin be the difference between tailscale serve and tailscale funnel?
Who fit reach the result. tailscale serve publishes local port for HTTPS URL wey only devices for your tailnet fit reach. tailscale funnel publishes the same port for URL wey anybody for internet fit reach, through relay servers wey Tailscale dey run. The flags and targets dey the same for both. The first output line go tell you which one you get: Available within your tailnet or Available on the internet.
Why tailscale funnel dey talk say the node attribute no dey set?
Because funnel dey disabled for a tailnet until somebody enables am. The message na Funnel not available; "funnel" node attribute not set. and e dey come from your own client before e contact any relay. Add a nodeAttrs entry wey grant funnel attribute to autogroup:member, or to a tag if na only one machine suppose publish, for the tailnet policy file under Access Controls. A tailnet admin fit instead follow the consent URL wey CLI print.
Which ports Tailscale Funnel fit use?
Na only 443, 8443 and 10000. The default na 443, and you fit choose another one with --https=8443 or --https=10000. Na limit of the funnel relays be this, no be limit of your server, so no firewall change or configuration change for the VPS fit remove am. tailscale serve no get this restriction because e never leave your tailnet.
Serve or funnel URL go still work after reboot?
Only if you use --bg. Without am, the command dey run for foreground, e print Press Ctrl+C to exit., and the mapping go disappear together with the process. With --bg, the mapping dey write into the node's serve config and e go return with tailscaled after reboot. Check with tailscale serve status, wey go print No serve config when nothing dey set.
E safe to leave funnel running?
E safe for transport matter: the connection na HTTPS and no port dey open for your firewall. But e no safe for the meaning wey people usually intend, because the URL public, so the application behind am public too. Leave funnel up only in front of something wey dey authenticate its own requests, and bring am down when the demo or webhook test finish, using the command wey create am with off for the end.
Sources for the command behaviour above: Tailscale Serve and Funnel documentation and CLI reference for tailscale.com/docs.