Tailscale Serve ou Funnel : lequel choisir ?
Serve garde votre service sur le tailnet avec HTTPS ; Funnel l’expose sur Internet. Découvrez la policy qui peut bloquer Funnel et le bon choix selon l’accès voulu.
tailscale serve ou funnel : qui peut accéder à l’URL
La différence entre tailscale serve et tailscale funnel concerne le public, et rien d’autre. serve ajoute une interface HTTPS (hypertext transfer protocol secure) à un port local et le publie uniquement sur votre tailnet. funnel publie ce même port local sur l’ensemble de l’Internet public, via les serveurs relais gérés par Tailscale. Les deux commandes utilisent les mêmes flags et les mêmes cibles. Un seul mot sépare un tableau de bord privé d’un tableau de bord accessible depuis Internet.
Dans les deux cas, vous obtenez un certificat déjà approuvé par les navigateurs, sur un nom se terminant par ts.net, sans devoir ouvrir de port entrant dans le firewall de votre VPS. Votre daemon tailscaled maintient déjà une connexion sortante vers le tailnet ; le trafic arrive donc par cette connexion. Ajouter un serveur au tailnet est une tâche distincte. Exécuter un VPS comme nœud de sortie Tailscale ou Annoncer un routeur de sous-réseau pour un réseau privé couvre ce sujet. La publication d’un service déjà présent sur le tailnet est le sujet de cette section.
Conditions préalables pour que les deux commandes fonctionnent
- Tailscale 1.38.3 ou version ultérieure sur le VPS, connecté à votre tailnet. Vérifiez-le avec
tailscale versionettailscale status. - MagicDNS activé. MagicDNS est le DNS intégré de Tailscale (système de noms de domaine). C’est ce qui attribue à la machine un nom tel que
blog-vps.your-tailnet.ts.net, au lieu de lui fournir uniquement une adresse100.x. - Certificats HTTPS activés pour le tailnet, dans la page DNS de la console d’administration. Sans cela, vous ne pouvez pas placer de certificat devant votre port.
- Pour
funneluniquement, l’attribut de nœudfunneldans le fichier de stratégie du tailnet. C’est à cette étape que la plupart des premières tentatives échouent. Elle est expliquée plus bas.
Toutes les commandes présentées ici commencent par sudo, car l’interface de ligne de commande communique avec tailscaled via un socket dans lequel seul root peut écrire. Accordez à un utilisateur le droit de s’en passer :
sudo tailscale set --operator=$USERPublier sur votre tailnet avec tailscale serve
Pointez serve vers un port local et le reste se fait automatiquement.
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.La commande 3000 seule est un raccourci pour http://127.0.0.1:3000. Tailscale écoute sur le port 443 de l’adresse tailnet de la machine, termine TLS (transport layer security) avec le certificat ts.net, puis transmet les requêtes HTTP en clair vers votre port local. Votre application n’a jamais besoin de savoir qu’un certificat existe. C’est la principale raison d’utiliser cette solution devant un panneau d’administration que vous laisseriez sinon en HTTP simple. Une interface web liée uniquement à 127.0.0.1 est un candidat évident. L’interface web dsh sur le port 3080 en est un bon exemple : au lieu d’ouvrir un tunnel SSH chaque fois que vous en avez besoin, pointez serve vers 3080 une seule fois et accédez-y depuis n’importe quel appareil du tailnet.
Lisez maintenant la dernière ligne : Press Ctrl+C to exit. La commande s’exécute au premier plan et le mappage reste dans ce processus. Fermez le terminal et l’URL cesse de fonctionner, car rien n’a été écrit sur le disque. Ajoutez --bg pour enregistrer le mappage dans la configuration serve du nœud. Celle-ci reste disponible après la fermeture du terminal et après un redémarrage.
sudo tailscale serve --bg 3000Serve accepte autre chose qu’un simple numéro de port. --set-path monte un service sous un sous-chemin, afin que plusieurs applications puissent partager le même nom d’hôte :
sudo tailscale serve --bg --set-path=/grafana 3000
sudo tailscale serve --bg --set-path=/metrics 9090La cible peut également être un répertoire de fichiers statiques ou un backend qui utilise déjà TLS avec un certificat que vous ne voulez pas vérifier :
sudo tailscale serve --bg /srv/reports
sudo tailscale serve --bg https+insecure://localhost:8443La commande ne se limite pas non plus à HTTP. --tcp=<port> transmet un flux TCP (transmission control protocol) brut, tandis que --tls-terminated-tcp=<port> termine TLS sur votre nœud et transmet le contenu en clair. Vous pouvez ainsi placer un certificat approuvé devant un service qui ne parle pas du tout HTTP :
sudo tailscale serve --bg --tls-terminated-tcp=443 tcp://127.0.0.1:9899Pourquoi Funnel indique-t-il que l’attribut du nœud n’est pas défini ?
Funnel est désactivé par défaut pour tout un tailnet. La première exécution affiche ce message, puis s’arrête :
Funnel not available; "funnel" node attribute not set. See https://tailscale.com/kb/1223/tailscale-funnel/.La commande était correcte. La policy du tailnet n’a pas autorisé ce nœud à publier. Le client refuse donc l’opération avant même de contacter un relay. Modifiez le fichier de policy du tailnet dans la console d’administration, sous Access Controls, puis ajoutez l’attribut :
"nodeAttrs": [
{
"target": ["autogroup:member"],
"attr": ["funnel"],
},
],autogroup:member l’accorde à tous les membres du tailnet. Si une seule machine doit pouvoir publier, attribuez-lui un tag et ciblez plutôt ce tag, par exemple tag:public. Enregistrez la policy, puis exécutez de nouveau la commande Funnel.
Si votre compte est administrateur du tailnet, les clients récents proposent un raccourci : la CLI affiche une URL de consentement sur login.tailscale.com. En ouvrant cette URL, vous activez les certificats HTTPS et ajoutez l’attribut automatiquement. Si vous n’êtes pas administrateur, cette URL ne vous sera d’aucune utilité. Une personne ayant accès à la policy doit effectuer la modification.
Publier sur Internet avec Tailscale Funnel
Une fois l’attribut défini, la commande est celle que vous connaissez déjà, avec un verbe différent.
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.Lisez toujours cette première ligne. Available within your tailnet et Available on the internet sont les seules différences visibles entre un service privé et un service public, et les commandes qui les produisent ne diffèrent que d’un mot.
En août 2026, Funnel écoute sur le port 443, 8443 ou 10000, et sur aucun autre. La valeur par défaut est 443, tandis que --https=8443 ou --https=10000 sont les alternatives. Tout autre port est refusé, car les relais Funnel n’acceptent les connexions que sur ces ports. C’est pourquoi une URL Funnel contient toujours le nom d’hôte seul, ou le nom d’hôte suivi de :8443.
Comment voir ce qui est actuellement publié ?
Les suppositions sont la raison pour laquelle un tableau de bord reste public pendant un mois. Interrogez directement le nœud.
tailscale serve status
tailscale funnel status
tailscale serve status --jsonLes deux commandes d’état lisent la même configuration. L’une ou l’autre vous donne donc une vue complète. Utilisez la forme --json dans un script ou un contrôle planifié, car la sortie standard est destinée aux utilisateurs. Lorsqu’aucune configuration n’existe, une seule ligne s’affiche :
No serve configSi vous voyez cela après une configuration qui fonctionnait, le mapping a été créé au premier plan et le processus a disparu. Recréez-le avec --bg.
Pour supprimer un mapping, répétez la commande qui l’a créé et ajoutez off à la fin. Pour supprimer tous les mappings serve et funnel du nœud, utilisez reset.
sudo tailscale funnel --https=443 3000 off
sudo tailscale serve resetExécutez de nouveau tailscale serve status après l’une ou l’autre opération et vérifiez ce qui reste, au lieu de supposer que la commande a fait ce que vous vouliez.
Ce que vous gagnez et ce que vous abandonnez
Les avantages sont réels, et c’est pour cela que certains choisissent cette solution plutôt qu’un reverse proxy.
- Un certificat reconnu par les navigateurs, renouvelé automatiquement. Aucun client ACME (automatic certificate management environment) à installer, et aucune tâche de renouvellement à ne pas oublier.
- Aucun port entrant à ouvrir dans le pare-feu du VPS.
tailscaledétablit une connexion sortante. Un pare-feu ufw en refus par défaut sur votre VPS peut donc rester aussi restrictif qu’avant. - Aucun enregistrement DNS à acheter, à configurer ou dont il faut attendre la propagation.
- Aucun port forwarding. C’est essentiel pour une machine derrière un NAT (network address translation), contrairement à un VPS doté d’une adresse IP publique.
Les coûts sont tout aussi réels, et Funnel les impose tous.
- Le nom ne vous appartient pas. Les visiteurs externes voient
host.your-tailnet.ts.net. Funnel ne prend pas en charge les domaines personnalisés. Vous ne pouvez donc pas placerapp.example.comdevant cette adresse. - Le chemin ne vous appartient pas. Le trafic atteint d’abord un relais Tailscale, qui transmet le flux à votre nœud via le tailnet. Tailscale indique que le trafic Funnel est soumis à des limites de bande passante qui ne sont ni publiées ni configurables. Mesurez donc votre propre débit avant de dépendre d’une valeur précise.
- Les contrôles sont absents. Un reverse proxy que vous administrez vous fournit des access logs, des limites de débit, des plafonds de taille des requêtes et un emplacement pour gérer l’authentification. Funnel vous fournit une URL. Tout le reste doit être géré par votre application.
- La liste des ports est fixe, comme indiqué plus haut.
Ces deux fonctionnalités reposent également sur une infrastructure exploitée par Tailscale : l’émission du certificat pour le nom ts.net et les relais funnel eux-mêmes. L’importance de cette dépendance dépend de ce que ces serveurs peuvent ou ne peuvent pas faire avec votre trafic. C’est précisément ce que décrit le modèle de confiance de Tailscale. Leur utilisation est gratuite, car le forfait gratuit couvre jusqu’à six utilisateurs avec un nombre illimité d’appareils chacun, et c’est le nombre de comptes, plutôt que la liste des fonctionnalités, qui fait finalement passer un tailnet sur un forfait payant. Au-delà de ce seuil, la facturation dépend des utilisateurs et non des machines. Il est donc utile de vérifier le coût réel d’un tailnet avec un forfait payant avant que serve ou funnel ne devienne indispensable. Si vous envisagez un serveur de contrôle Headscale auto-hébergé, ne partez pas du principe que ces deux fonctionnalités vous suivront. Consultez les notes de version de la version de Headscale que vous prévoyez d’exécuter.
Quelle option utiliser ?
La règle est simple.
Utilisez serve pour tout ce qui est interne : interfaces d’administration, tableaux de bord, interface de métriques que vous ne voulez pas faire indexer, copie de préproduction d’un site. L’appartenance au tailnet constitue le contrôle d’accès, et c’est un contrôle efficace. Un appareil qui n’est pas connecté au tailnet ne peut même pas résoudre le nom.
Utilisez funnel pour un lien de démonstration, un récepteur de webhook auquel un tiers doit envoyer une requête POST ou un callback OAuth pendant le développement. C’est le moyen le plus rapide d’obtenir une URL HTTPS publique, et une commande off suffit à y mettre fin. Public signifie public : le nom d’hôte n’est pas un secret, et un funnel placé devant une application sans authentification constitue un service ouvert. Tout ce qui se trouve derrière doit authentifier ses propres requêtes, avec la même rigueur que pour un endpoint d’API Ollama exposé.
Utilisez un reverse proxy classique pour tout ce que vous considéreriez comme de la production. Votre domaine, votre certificat, vos journaux, vos limites de débit, et aucun autre intermédiaire dans le chemin des requêtes. Comparer nginx, Caddy et Traefik comme reverse proxy explique comment en choisir un.
Modes d’échec et messages affichés
Funnel refuse de démarrer. Funnel not available; "funnel" node attribute not set. indique un problème de stratégie, pas un problème de commande. Ajoutez l’attribut funnel au fichier de stratégie tailnet, enregistrez-le, puis réessayez.
La commande fonctionnait, mais tailscale serve status indique maintenant No serve config. Le mapping a été créé au premier plan, puis le processus s’est terminé. Relancez la même commande avec --bg.
Le nom est résolu, mais aucune réponse n’arrive. Serve transmet les requêtes au service cible indiqué. Si aucun processus n’écoute à cette adresse, Serve ne peut rien joindre. Vérifiez avec ss -ltnp | grep 3000 sur la même machine que celle qui exécute tailscaled. La cause fréquente est un conteneur qui publie son port sur une adresse de bridge Docker au lieu de 127.0.0.1. Dans ce cas, l’hôte ne voit aucun processus à l’écoute à l’endroit prévu. Fonctionnement du réseau Docker Compose indique où un port publié est réellement exposé.
Erreurs de certificat sur le nom ts.net. Les certificats HTTPS ne sont probablement pas activés pour le tailnet. Activez-les dans la console d’administration, puis exécutez séparément l’étape de génération du certificat afin que ses erreurs ne soient pas mélangées à la sortie de Serve :
sudo tailscale cert your-host.your-tailnet.ts.netFunnel fonctionne avec les données mobiles, mais se comporte différemment depuis votre ordinateur portable. Votre ordinateur portable est connecté au tailnet. MagicDNS résout donc le nom vers l’adresse 100.x et vous accédez directement au service, sans passer par un relais. Ce comportement est normal. Cela signifie aussi que votre ordinateur portable ne peut pas tester l’accessibilité publique. Utilisez curl depuis une machine qui n’est pas connectée au tailnet.
FAQ
Quelle est la différence entre tailscale serve et tailscale funnel ?
Qui peut atteindre le résultat. tailscale serve publie un port local à une URL HTTPS accessible uniquement par les appareils de votre tailnet. tailscale funnel publie le même port à une URL accessible par n’importe qui sur Internet, via les serveurs relais gérés par Tailscale. Les options et les cibles sont communes aux deux commandes. La première ligne de la sortie indique laquelle vous avez obtenue : Available within your tailnet ou Available on the internet.
Pourquoi tailscale funnel indique-t-il que l’attribut du nœud n’est pas défini ?
Parce que funnel est désactivé pour un tailnet tant qu’un administrateur ne l’a pas activé. Le message est Funnel not available; "funnel" node attribute not set. et provient de votre propre client, avant tout contact avec un relais. Ajoutez une entrée nodeAttrs accordant l’attribut funnel à autogroup:member, ou à un tag si une seule machine doit publier, dans le fichier de stratégie du tailnet, sous Access Controls. Un administrateur du tailnet peut aussi suivre l’URL de consentement affichée par la CLI.
Quels ports Tailscale Funnel peut-il utiliser ?
Uniquement 443, 8443 et 10000. Le port par défaut est 443, et vous pouvez en choisir un autre avec --https=8443 ou --https=10000. Il s’agit d’une limite des relais Funnel, et non de votre serveur. Aucun changement de pare-feu ou de configuration sur le VPS ne permet donc de la lever. tailscale serve n’a pas cette restriction, car le trafic ne quitte jamais votre tailnet.
Une URL serve ou funnel survit-elle à un redémarrage ?
Uniquement si vous avez utilisé --bg. Sans cette option, la commande s’exécute au premier plan, affiche Press Ctrl+C to exit., puis le mapping disparaît avec le processus. Avec --bg, le mapping est écrit dans la configuration serve du nœud et revient avec tailscaled après un redémarrage. Vérifiez avec tailscale serve status : la commande affiche No serve config lorsqu’aucun mapping n’est défini.
Est-il sûr de laisser un funnel actif ?
C’est sûr du point de vue du transport : la connexion est HTTPS et aucun port n’est ouvert sur votre pare-feu. Ce n’est pas sûr au sens habituel, car l’URL est publique et l’application située derrière l’URL l’est donc aussi. Laissez un funnel actif uniquement devant une application qui authentifie elle-même ses requêtes. Désactivez-le lorsque la démonstration ou le test du webhook est terminé, en réutilisant la commande qui l’a créé et en ajoutant off à la fin.
Sources concernant le comportement des commandes ci-dessus : la documentation et la référence CLI de Tailscale Serve et Funnel sur tailscale.com/docs.