Nouvelle génération de tunneling & mesh

Exposez vos services locaux
en une commande SSH

Tunnels HTTPS sécurisés, sous-domaines automatiques et ports TCP — sans installer le moindre client. Auto-hébergé, open source, prêt pour la production.

Statut live
Tunnels
Auto
HTTPS
0
Install client
bash — ssh
$ ssh -4 -p 443 -R 80:localhost:3000 localvhost.com
Tunnel créé avec succès
https://app-7f3.localvhost.com
Fonctionnalités

Tout pour exposer vos services

Simple comme une commande SSH, robuste comme une infrastructure de production.

HTTPS automatique

Certificats Let's Encrypt générés et renouvelés sans intervention. TLS 1.3, partout.

Ultra rapide

Infrastructure 100% Go, latence minimale, connexions persistantes et pool optimisé.

Sous-domaines

Sous-domaine aléatoire ou personnalisé : app.localvhost.com.

Tunnels TCP & TLS partagés

Bases de données, SSH, RDP, Redis… sur le port de votre choix (1024-65535, honoré tel quel). Plusieurs services TLS peuvent même partager un port, routés par sous-domaine (SNI), chiffrés de bout en bout.

Sécurité intégrée

Fournisseur d'identité OIDC complet (SSO), HTTPS/HSTS, en-têtes durcis. Login admin protégé contre le brute-force ; rate-limiting & pare-feu IP intégrés (désactivés en mode haute performance).

Sans client

Aucune installation : un simple OpenSSH suffit. Compatible Linux, macOS, Windows.

Architecture

Comment ça marche

Votre machine ouvre un tunnel SSH sortant. LocalVhost le route vers Internet via Caddy, avec HTTPS automatique.

Votre machine localhost:3000 LOCALVHOST SSH server :2222 Caddy :443 HTTPS Visiteurs https://app.localvhost.com tunnel SSH -R HTTPS public
Interactif

Générateur de commande

Composez votre tunnel en quelques clics — la commande se construit en direct, prête à copier.

commande générée
Résultat
Documentation

Guide de démarrage

De zéro à un service public en moins d'une minute. Copiez-collez, c'est prêt.

1Démarrage rapide

Une seule commande. Aucun compte, aucun client à installer — juste votre OpenSSH.

ssh -4 -p 443 -R 80:localhost:3000 localvhost.com
# → https://<aléatoire>.localvhost.com pointe vers votre localhost:3000
💡-p 443 fait passer le SSH par le même port que le HTTPS (rien d'exotique à ouvrir côté réseau) ; -4 force l'IPv4, recommandé pour le multiplexage du port 443.

2Tunnel HTTP

Exposez n'importe quel serveur web local. Le port 80 demande un sous-domaine HTTPS.

# app locale sur le port 3000
ssh -4 -p 443 -R 80:localhost:3000 localvhost.com

# port local différent (ex: 5000)
ssh -4 -p 443 -R 80:localhost:5000 localvhost.com

3Sous-domaine personnalisé

Préfixez par le nom souhaité pour obtenir une URL stable et mémorisable.

ssh -4 -p 443 -R monapp:80:localhost:3000 localvhost.com
→ https://monapp.localvhost.com

4Tunnels TCP directs

Pour les services non-HTTP (bases de données, SSH, VNC…), exposez-les sur le port de votre choixn'importe quel port de 1024 à 65535. Le port demandé est honoré tel quel : demandez 5432, vous obtenez localvhost.com:5432.

# MySQL / MariaDB — exposé sur le MÊME port
ssh -4 -p 443 -R 3306:localhost:3306 localvhost.com       # → localvhost.com:3306

# PostgreSQL
ssh -4 -p 443 -R 5432:localhost:5432 localvhost.com       # → localvhost.com:5432

# Redis
ssh -4 -p 443 -R 6379:localhost:6379 localvhost.com

# SSH distant (port au choix)
ssh -4 -p 443 -R 2022:localhost:22 localvhost.com         # puis: ssh -p 2022 user@localvhost.com
💡Le port demandé vous est attribué à l'identique et reste stable à la reconnexion. Seuls les ports dont le serveur a besoin (ses propres services et ceux détectés en écoute) sont refusés — priorité absolue aux services du serveur. Les ports privilégiés (<1024) sont réservés par sécurité ; demandez plutôt un port ≥ 1024. Si un port est déjà pris, l'erreur est explicite : choisissez-en un autre. La commande ssh -4 -p 443 -R 0:localhost:3000 localvhost.com, elle, crée un tunnel HTTP à sous-domaine auto.

🖥️ RDP sans port — rdp.localvhost.com dans mstsc

Pour le Bureau à distance, connectez-vous avec mstsc en tapant simplement un nomsans indiquer de port (mstsc vise 3389 par défaut). Avec un poste sur le port 3389, le serveur relaie les octets à l'identique (verbatim), TLS + NLA de bout en bout : mode prouvé avec un vrai mstsc. Pour plusieurs postes, donnez à chacun un port dédié (relais verbatim lui aussi) — voir ci-dessous.

port rdp.localvhost.com mstsc — sans port (3389) rdp2.localvhost.com:33892 mstsc — port dédié LocalVhost relais verbatim Poste A 192.168.1.5:3389 Poste B 192.168.1.7:3389 TLS + NLA chiffrés de bout en bout — le serveur n'aiguille que, sans jamais déchiffrer
  1. Pour le poste principal, ouvrez un tunnel nommé sur le port 3389 depuis une machine ayant accès au poste Windows. Dans mstsc, vous taperez juste rdp.localvhost.comsans port.
  2. Pour chaque poste supplémentaire, choisissez un port dédié (33892, 33893…) : dans mstsc, vous taperez rdp2.localvhost.com:33892 (avec le port). Un poste = un port — c'est le PORT qui aiguille, le nom est mémotechnique.
  3. Dans mstsc (Connexion Bureau à distance), saisissez l'adresse (sans port pour le poste sur 3389, avec le port dédié pour les autres) — ou téléchargez le raccourci .rdp déjà configuré, ci-dessous.
  4. À la 1ʳᵉ connexion, Windows affiche un avertissement de certificat : c'est normal (voir plus bas), cliquez sur « Se connecter quand même ».
# Poste principal → nom « rdp » sur 3389 (RDP interne 192.168.1.5:3389)
ssh -4 -p 443 -R rdp:3389:192.168.1.5:3389 localvhost.com        # → mstsc : rdp.localvhost.com (SANS port)

# Poste supplémentaire → PORT DÉDIÉ 33892 (RDP interne 192.168.1.7:3389)
ssh -4 -p 443 -R rdp2:33892:192.168.1.7:3389 localvhost.com     # → mstsc : rdp2.localvhost.com:33892
.localvhost.com
⬇ Télécharger le .rdp
🔒Le serveur ne déchiffre rien : il ne fait qu'aiguiller par le nom, le TLS et le NLA (CredSSP) restent de bout en bout entre votre client mstsc et votre poste — aucun risque de MITM, le mot de passe n'est jamais visible côté serveur. Repli si votre réseau bloque le 3389 sortant : un port haut classique -R 44046:localhost:3389localvhost.com:44046 (à indiquer explicitement dans mstsc).
Un poste sur 3389 = relais 100 % transparent (prouvé). Le serveur relaie les octets à l'identique, sans jamais les interpréter — le plus robuste, compatible SSL / NLA / CredSSP. Pour plusieurs postes, un port dédié par poste reste en relais verbatim (recommandé). ⚠️ Partager le même 3389 entre ≥2 postes par nom d'hôte (SNI) obligerait le serveur à interposer un préambule, ce qui peut casser le NLA de mstsc : non garanti, préférez un port dédié.
🛡️Avertissement de certificat = normal. Comme le chiffrement est de bout en bout, mstsc voit le certificat de votre propre poste Windows (dont le nom diffère de rdp.localvhost.com) : Windows signale « l'identité de l'ordinateur distant ne peut pas être vérifiée ». C'est attendu — le raccourci .rdp garde le NLA activé et se contente d'afficher cet avertissement (jamais de contournement). Confirmez pour vous connecter.
🩹Erreur « Could not connect via TLS » (Remmina / FreeRDP, ou hôte Windows 7 / Server 2008) ? Ces postes présentent un certificat RDP signé en SHA-1, refusé par le TLS moderne des clients Linux (OpenSSL) — alors que mstsc l'accepte. Correctif en un clic, à lancer en administrateur sur le poste distant : ⬇ rdp-cert-fix-win7.bat — il régénère le certificat en SHA-256 (méthode compatible Windows 7, clé privée générée localement, jamais transmise) et le relie à l'écouteur RDP. Dépannage immédiat, sans rien changer sur le poste : Remmina → « TLS Security Level = 0 », ou xfreerdp /tls:seclevel:0.

5Services TLS partagés — un port, plusieurs backends (SNI)

Plusieurs services TLS (HTTPS internes, API mTLS, TLS natif) partagent un seul port public : le serveur les aiguille par le nom d'hôte (SNI) de leur poignée de main, exactement comme le RDP. La lecture est passive → le TLS/mTLS reste de bout en bout, chaque service garde son propre certificat, le serveur ne déchiffre jamais rien.

SNI app1.localvhost.com:9443 client TLS · curl app2.localvhost.com:9443 navigateur LocalVhost :9443 · démux SNI Service A 192.168.1.10:443 · cert propre Service B 192.168.1.11:443 · cert propre TLS / mTLS de bout en bout — le serveur aiguille par SNI, sans jamais déchiffrer
# Service A (HTTPS interne) → nom « app1 », sur le port TLS partagé 9443
ssh -4 -p 443 -N -R app1:9443:192.168.1.10:443 localvhost.com   # → app1.localvhost.com:9443

# Service B (autre HTTPS interne) → nom « app2 », MÊME port
ssh -4 -p 443 -N -R app2:9443:192.168.1.11:443 localvhost.com   # → app2.localvhost.com:9443
# chaque nom atteint SON backend, avec SON certificat
curl https://app1.localvhost.com:9443/   # → 192.168.1.10:443 (cert du service A)
curl https://app2.localvhost.com:9443/   # → 192.168.1.11:443 (cert du service B)
🔒Idéal quand le backend doit garder son propre certificat : mTLS, certificate pinning, PKI interne. Contrairement au tunnel HTTP (où Caddy termine le TLS avec un certificat géré), ici le TLS n'est jamais terminé — le serveur ne voit que des octets chiffrés.
🧭Couvre les protocoles « TLS-d'abord » (le client envoie un ClientHello en premier) : HTTPS, TLS natif. Ne couvre pas MySQL/SSH (le serveur parle en premier, aucun nom sur le fil → utilisez un tunnel TCP nommé), ni le RDP (démux dédié sur 3389).
⚠️Le port 9443 est le port TLS partagé configuré côté serveur. SNI requis : un client TLS qui n'envoie pas de SNI n'est pas routable (rare) — pour ce cas, un tunnel TCP nommé (routage par port). L'option -N garde le tunnel ouvert sans ouvrir de shell.

6Quel mécanisme pour quel service ?

Un seul critère décide : qui parle en premier, et où se trouve le nom d'hôte. Le serveur ne peut router une connexion que s'il trouve un identifiant dans ses premiers octets — soit le port, soit un nom (Host HTTP ou SNI TLS). Voici l'arbre de décision, le comparatif et le catalogue complet.

Quel est le protocole du service ? Web HTTP(S) navigateur, API REST, webhook Tunnel HTTP sous-domaine.localvhost.com · :443 · TLS auto Plusieurs services TLS à mutualiser HTTPS internes, API mTLS, TLS natif Démux SNI appN.localvhost.com:9443 · cert propre Autre TCP, ou un seul service MySQL, PostgreSQL, SSH, Redis… TCP nommé localvhost.com:port · un port dédié Bureau à distance client mstsc / RDP Démux RDP rdp.localvhost.com · :3389 (ou port dédié) TLS · TCP · RDP : chiffrement de bout en bout — HTTP : TLS géré par le serveur (cert auto)
MécanismeRouté parPorts publicsTLS bout-en-boutPour quoi
Tunnel HTTPsous-domaine (Host)443 (partagé)Non — Caddy termine (cert auto)sites, API web, webhooks
Démux SNIsous-domaine (SNI)9443 (partagé)Oui — cert du backendplusieurs HTTPS/TLS internes, mTLS
TCP nomméport (nom cosmétique)un par service (1024-65535)Oui — flux opaquetout TCP : bases, SSH, cache…
Démux RDPnom (SNI) / port3389 (ou dédié)Oui — TLS + NLABureau à distance (mstsc)

📇 Catalogue de cas réels

La commande se lance depuis une machine ayant accès au service (le même réseau local). localhost = remplacez par l'hôte/IP interne si le service tourne ailleurs.

ServiceCommandeAdresse publique
🌐 Web & applications — tunnel HTTP (cert Let's Encrypt auto + SSO)
Site web / SPA (Vite, Next…)ssh -4 -p 443 -R 80:localhost:3000 localvhost.comhttps://<aléatoire>.localvhost.com
… avec URL stablessh -4 -p 443 -R monapp:80:localhost:3000 localvhost.comhttps://monapp.localvhost.com
API REST / webhookssh -4 -p 443 -R api:80:localhost:8080 localvhost.comhttps://api.localvhost.com
Site WEBDEV (Serveur d'appli PC SOFT)ssh -4 -p 443 -R webdev:80:192.168.1.20:80 localvhost.comhttps://webdev.localvhost.com
WordPress / PHP (Apache, Nginx)ssh -4 -p 443 -R blog:80:localhost:80 localvhost.comhttps://blog.localvhost.com
Tomcat / Spring Boot (Java)ssh -4 -p 443 -R app:80:localhost:8080 localvhost.comhttps://app.localvhost.com
.NET / IIS (ASP.NET, Kestrel)ssh -4 -p 443 -R dotnet:80:localhost:5000 localvhost.comhttps://dotnet.localvhost.com
Jenkins / GitLab CIssh -4 -p 443 -R ci:80:localhost:8080 localvhost.comhttps://ci.localvhost.com
Grafanassh -4 -p 443 -R grafana:80:localhost:3000 localvhost.comhttps://grafana.localvhost.com
Jupyter Notebookssh -4 -p 443 -R nb:80:localhost:8888 localvhost.comhttps://nb.localvhost.com
Prometheus (UI)ssh -4 -p 443 -R prom:80:localhost:9090 localvhost.comhttps://prom.localvhost.com
🗄️ Bases de données — tunnel TCP nommé (binaire, bout-en-bout)
HFSQL Client/Serveur (WinDev — PC SOFT)ssh -4 -p 443 -R hfsql:4900:192.168.1.20:4900 localvhost.comhfsql.localvhost.com:4900
MySQL / MariaDBssh -4 -p 443 -R 3306:localhost:3306 localvhost.comlocalvhost.com:3306
PostgreSQLssh -4 -p 443 -R 5432:localhost:5432 localvhost.comlocalvhost.com:5432
Microsoft SQL Serverssh -4 -p 443 -R mssql:1433:192.168.1.30:1433 localvhost.commssql.localvhost.com:1433
Oracle Databasessh -4 -p 443 -R oracle:1521:192.168.1.31:1521 localvhost.comoracle.localvhost.com:1521
Redisssh -4 -p 443 -R 6379:localhost:6379 localvhost.comlocalvhost.com:6379
MongoDBssh -4 -p 443 -R 27017:localhost:27017 localvhost.comlocalvhost.com:27017
Elasticsearch / OpenSearchssh -4 -p 443 -R es:9200:localhost:9200 localvhost.comes.localvhost.com:9200
Firebirdssh -4 -p 443 -R fb:3050:localhost:3050 localvhost.comfb.localvhost.com:3050
Cassandrassh -4 -p 443 -R cass:9042:localhost:9042 localvhost.comcass.localvhost.com:9042
CouchDBssh -4 -p 443 -R couch:5984:localhost:5984 localvhost.comcouch.localvhost.com:5984
InfluxDBssh -4 -p 443 -R influx:8086:localhost:8086 localvhost.cominflux.localvhost.com:8086
Memcachedssh -4 -p 443 -R mc:11211:localhost:11211 localvhost.commc.localvhost.com:11211
📨 Files, brokers & IoT — tunnel TCP nommé
RabbitMQ (AMQP)ssh -4 -p 443 -R amqp:5672:localhost:5672 localvhost.comamqp.localvhost.com:5672
Apache Kafkassh -4 -p 443 -R kafka:9092:localhost:9092 localvhost.comkafka.localvhost.com:9092
MQTT (Mosquitto, IoT)ssh -4 -p 443 -R mqtt:1883:localhost:1883 localvhost.commqtt.localvhost.com:1883
NATSssh -4 -p 443 -R nats:4222:localhost:4222 localvhost.comnats.localvhost.com:4222
🖥️ Accès distant & bureau
SSH / SFTP distantssh -4 -p 443 -R 2022:localhost:22 localvhost.comssh -p 2022 user@localvhost.com
RDP — un poste (« sans port » dans mstsc)ssh -4 -p 443 -R rdp:3389:192.168.1.5:3389 localvhost.commstsc : rdp.localvhost.com
RDP — poste supplémentaire (port dédié)ssh -4 -p 443 -R rdp2:33892:192.168.1.7:3389 localvhost.commstsc : rdp2.localvhost.com:33892
VNCssh -4 -p 443 -R 5900:localhost:5900 localvhost.comlocalvhost.com:5900
✉️ Messagerie & annuaire — tunnel TCP nommé
SMTPssh -4 -p 443 -R 2525:localhost:25 localvhost.comlocalvhost.com:2525
IMAPssh -4 -p 443 -R imap:1143:localhost:143 localvhost.comimap.localvhost.com:1143
POP3ssh -4 -p 443 -R pop3:1110:localhost:110 localvhost.compop3.localvhost.com:1110
LDAP / Active Directoryssh -4 -p 443 -R ldap:1389:192.168.1.10:389 localvhost.comldap.localvhost.com:1389
🧰 DevOps & fichiers — tunnel TCP nommé
Docker Registryssh -4 -p 443 -R registry:5000:localhost:5000 localvhost.comregistry.localvhost.com:5000
Git (protocole git://)ssh -4 -p 443 -R git:9418:localhost:9418 localvhost.comgit.localvhost.com:9418
MinIO / S3 (API)ssh -4 -p 443 -R s3:9000:localhost:9000 localvhost.coms3.localvhost.com:9000
FTP (mode passif à configurer)ssh -4 -p 443 -R ftp:2121:localhost:21 localvhost.comftp.localvhost.com:2121
🔐 Services TLS internes — démux SNI (cert du backend préservé, mTLS OK)
HTTPS interne (cert propre / mTLS)ssh -4 -p 443 -N -R app1:9443:192.168.1.10:443 localvhost.comhttps://app1.localvhost.com:9443
… un 2ᵉ, même portssh -4 -p 443 -N -R app2:9443:192.168.1.11:443 localvhost.comhttps://app2.localvhost.com:9443
⚖️Avantages & limites en un coup d'œil. HTTP — le plus simple, cert auto + SSO, mais le serveur termine le TLS (pas de bout-en-bout). SNI — partage un port et garde le cert du backend, mais protocoles TLS-d'abord seulement. TCP nommé — tout protocole, bout-en-bout, mais un port par service. RDP — « sans port » dans mstsc, TLS + NLA préservés.
🪟Pile WinDev / WEBDEV (PC SOFT). La base HFSQL Client/Serveur écoute en TCP 4900 par défaut → un tunnel TCP nommé (-R hfsql:4900:…:4900) l'expose telle quelle sur hfsql.localvhost.com:4900 : protocole binaire relayé octet pour octet, de bout en bout (aucune interposition), votre application WinDev/WEBDEV/WinDev Mobile s'y connecte comme en local. Un site WEBDEV dynamique (servi par le Serveur d'application WEBDEV derrière IIS/Apache) passe lui par un tunnel HTTP (-R webdev:80:…:80) → https://webdev.localvhost.com avec certificat auto + SSO. Le Centre de Contrôle HFSQL (administration) utilise aussi le 4900.
🛡️Sur les ports TCP / SNI / RDP, le démux aiguille sans authentifier (modèle anonyme, à la Serveo) : la sécurité repose sur le backend. Pour un service sensible, activez le mTLS côté backend (le démux SNI le préserve intégralement) ou passez par le VPN mesh / le SSO OIDC.

7Tunnels persistants

Gardez un service exposé en continu, avec reconnexion automatique — idéal pour la production.

# autossh : relance le tunnel en cas de coupure réseau
autossh -M 0 -4 -p 443 -o ServerAliveInterval=30 -o ServerAliveCountMax=3 -N -R monapp:80:localhost:3000 localvhost.com
# service systemd — /etc/systemd/system/tunnel.service
[Service]
ExecStart=/usr/bin/ssh -4 -p 443 -o ServerAliveInterval=30 -o ExitOnForwardFailure=yes -N -R monapp:80:localhost:3000 localvhost.com
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

8Options SSH avancées

Arrière-plan, keep-alive, clé dédiée — identique sous Linux, macOS et Windows.

# arrière-plan (sans shell) + keep-alive
ssh -4 -fN -p 443 -o ServerAliveInterval=30 -R 80:localhost:3000 localvhost.com

# clé SSH spécifique
ssh -4 -p 443 -i ~/.ssh/ma_cle -R 80:localhost:3000 localvhost.com

# Windows (OpenSSH intégré, PowerShell) — même commande
ssh -4 -p 443 -R 80:localhost:3000 localvhost.com

9Exemples par framework

Démarrez votre app en arrière-plan (&), puis ouvrez le tunnel vers son port.

# React / Vue / Angular (dev server :3000)
npm run dev &
ssh -4 -p 443 -R 80:localhost:3000 localvhost.com

# API Node / Express (:8080) avec sous-domaine 'monapi' ('api' seul est réservé)
node server.js &
ssh -4 -p 443 -R monapi:80:localhost:8080 localvhost.com

# Python / Flask (:5000)
flask run --port 5000 &
ssh -4 -p 443 -R 80:localhost:5000 localvhost.com
💡Utilisez & (arrière-plan) et non && : un serveur de dev ne « rend pas la main », && empêcherait le tunnel de démarrer.

10Dashboard & analytics temps réel

Chaque tunnel dispose d'un tableau de bord live : trafic en direct (WebSocket), carte des visiteurs géolocalisés, journaux de requêtes, statistiques par pays, par chemin et par navigateur.

https://localvhost.com/dashboard LIVE 12 480Visites 24 h 37Pays 42 msTemps réponse 3Tunnels actifs Trafic temps réel (WebSocket) Journal des requêtes 200GET /api/users🇫🇷 200POST /login🇩🇪 302GET /dashboard🇺🇸 200GET /assets/app.js🇯🇵 404GET /favicon.ico🇧🇷 200GET /api/stats🇬🇧 200GET /🇨🇦
Flux live WebSocket Carte des visiteurs (GeoIP) Stats pays / chemin / navigateur Journal des requêtes Isolation par utilisateur
# votre dashboard personnel
https://localvhost.com/dashboard
📊Un compte est créé automatiquement pour chaque sous-domaine personnalisé ; les identifiants s'affichent une fois, à la première connexion du tunnel. Chaque utilisateur ne voit QUE ses propres tunnels et visites (isolation vérifiée côté serveur).

11Sécurité & SSO — Fournisseur d'identité OIDC

LocalVhost embarque un fournisseur OpenID Connect complet (signature RS256, sans dépendance externe). Un seul déploiement authentifie tous vos services auto-hébergés — NetBird (VPN mesh), Grafana, headscale, Proxmox, Portainer… — via Authorization Code + PKCE ou Device Flow, avec sessions longues (refresh token roté), déconnexion SSO et révocation inclus.

LocalVhost OIDC · RS256 NetBird · Device + PKCE Grafana · Code + PKCE headscale · Code + PKCE
Authorization Code + PKCE S256 Device Flow (RFC 8628) Refresh token · offline_access Auth silencieuse (prompt=none · max_age) Déconnexion SSO (RP-Initiated Logout) Révocation immédiate (RFC 7009 · jti) Introspection (RFC 7662) RS256 · JWKS publié Discovery automatique Claim groups (RBAC) CORS SSO multi-domaines

Configuration par découverte automatique : pointez chaque service sur l'URL de discovery, il résout seul les endpoints et les clés.

# Découverte OIDC (issuer, endpoints, clés)
https://localvhost.com/.well-known/openid-configuration
EndpointRôle
/.well-known/openid-configurationDécouverte des métadonnées (issuer, endpoints, algos, scopes)
/oidc/jwks.jsonClés publiques de signature — RS256, kid localvhost-1
/oidc/authorizeAutorisation (flux code) — PKCE S256 obligatoire ; auth silencieuse prompt=none / max_age / id_token_hint
/oidc/tokenÉchange code / device_code / refresh_token → id_token + access_token (+ refresh_token si offline_access)
/oidc/userinfoClaims à jour du porteur — révocation effective
/oidc/device_authorizationDémarrage du Device Flow (machines sans navigateur) — renvoie user_code + verification_uri_complete (QR-friendly)
/oidc/deviceApprobation utilisateur — protégée CSRF + same-origin
/oidc/logoutDéconnexion RP-initiée (RP-Initiated Logout 1.0) — post_logout_redirect_uri validée
/oidc/revokeRévocation immédiate d'un refresh_token ou access_token (RFC 7009) — effet instantané à /userinfo
/oidc/introspectIntrospection de token (RFC 7662) — état/claims d'un access_token ou refresh_token ; auth client requise, binding par client

Scopes openid profile email offline_access  ·  Claims sub auth_time at_hash preferred_username name email email_verified groups

🔗 NetBird

management.json
AuthIssuer: https://localvhost.com
AuthAudience: netbird
AuthKeysLocation:
  …/oidc/jwks.json
OIDCConfigEndpoint:
  …/.well-known/openid-configuration

📊 Grafana

[auth.generic_oauth]
auth_url  = …/oidc/authorize
token_url = …/oidc/token
api_url   = …/oidc/userinfo
scopes = openid profile email offline_access
use_pkce = true
use_refresh_token = true
role_attribute_path =
 contains(groups[*],'admins')
   && 'Admin' || 'Viewer'

🕸️ headscale

config.yaml · oidc
issuer: https://localvhost.com
client_id: headscale
client_secret: <secret>
scope:
  [openid, profile, email]
allowed_groups: [users]

Déclarez vos propres services (client_id, secret, redirections) sans recompiler, et pilotez les groupes RBAC par utilisateur :

# Ajouter des clients OIDC (Grafana, headscale, …)
OIDC_EXTRA_CLIENTS='[{"id":"grafana","secret":"CHANGEME",
  "name":"Grafana","redirect_uris":["https://grafana.exemple.com/login/generic_oauth"],
  "post_logout_redirect_uris":["https://grafana.exemple.com/login"]}]'
# Groupes du claim "groups" par utilisateur (RBAC)
OIDC_GROUPS_JSON='{"admins":["alice"],"ops":["bob","carol"]}'
🛡️Jetons RS256 signés (clés publiées via JWKS) ; access/id token 1 h, sessions longues via offline_accessrefresh_token persistés (survivent au redémarrage), rotés (usage unique) avec détection de rejeu par famille (RFC 6819) et plafond de vie absolu ; stockés hachés (SHA-256). PKCE S256 obligatoire pour tous les clients. HTTPS + HSTS et en-têtes durcis actifs ; login admin protégé en permanence contre le brute-force. Révocation : compte désactivé → 401 immédiat à /userinfo ; /oidc/revoke (RFC 7009) invalide instantanément un refresh_token ou un access_token (denylist par jti, bornée à l'expiration) — un client ne peut révoquer que ses propres jetons. Déconnexion SSO via /oidc/logoutpost_logout_redirect_uri validée (anti open-redirect).

Prêt à exposer votre premier service ?

Une commande suffit. Pas d'inscription, pas de client, pas d'attente.

ssh -4 -p 443 -R 80:localhost:3000 localvhost.com
Accéder au dashboard