Tutoriel

Pangolin sur VPS : exposer un service derrière NAT sans port

Déploiement11 min de lecture11 étapes

Vous avez un service qui tourne sur un NAS, un Raspberry Pi ou une VM locale, et vous voulez le rendre accessible depuis Internet — sans ouvrir de port sur votre box, sans IPv4 fixe, et sans confier vos flux à un SaaS tiers. Pangolin, associé à Gerbil, répond exactement à ce problème : un relais WireGuard que vous opérez vous-même sur un VPS, avec HTTPS automatique et une interface web pour tout piloter.

Sommaire· Le problème : exposer un service derrière NAT1/11
  1. 01Le problème : exposer un service derrière NAT
  2. 02Ce que Pangolin apporte face aux alternatives
  3. 03Architecture : VPS relay, Gerbil et Newt
  4. 04Prérequis
  5. 05Déploiement de Pangolin et Gerbil sur le VPS
  6. 06Ajout d'un tunnel avec Newt sur la machine d'origine
  7. 07Exposition d'un service : exemple Nextcloud derrière NAT
  8. 08Sécurité : tokens, rotation et contrôle d'accès
  9. 09Dépannage
  10. 10Pangolin vs Cloudflare Tunnel vs Tailscale/Headscale
  11. 11Aller plus loin

Le problème : exposer un service derrière NAT

La plupart des connexions résidentielles ou d'entreprise placent vos machines derrière un NAT : aucun port entrant n'est joignable depuis l'extérieur sans configuration explicite sur le routeur. Et même quand cette configuration est possible, elle expose directement votre réseau local.

Les scénarios réels sont nombreux : un NAS Synology dont vous voulez partager Nextcloud avec des clients, un homelab sous Proxmox hébergeant une dizaine de services, un Raspberry Pi tournant en domotique, ou une VM locale de développement que vous souhaitez tester depuis l'extérieur. Dans tous ces cas, la solution habituelle — le port-forwarding — pose deux problèmes : elle dépend du routeur, et elle ouvre un chemin direct vers votre réseau privé.

Les alternatives courantes ont chacune leurs limites : Cloudflare Tunnel passe l'intégralité de vos flux par les serveurs Cloudflare, ce qui pose des questions de confidentialité et impose leur infrastructure. Tailscale/Headscale crée un réseau mesh entre vos machines, ce qui est excellent pour les accès point-à-point — mais n'est pas conçu pour exposer publiquement un service HTTP(S) avec un sous-domaine dédié. Pangolin occupe un espace différent : un relais WireGuard self-hosted, avec gestion des certificats et des sous-domaines, que vous contrôlez entièrement depuis votre VPS.

Ce que Pangolin apporte face aux alternatives

  • Self-hosted complet — vos flux transitent par votre VPS uniquement, aucun tiers ne voit votre trafic applicatif.
  • Pas d'ouverture de port entrant — la connexion est initiée depuis la machine d'origine vers le VPS (sens sortant), le NAT n'est jamais un obstacle.
  • HTTPS automatique via Let's Encrypt — Pangolin gère les certificats pour chaque sous-domaine exposé, sans intervention manuelle.
  • Interface web intégrée — ajout de tunnels, gestion des ressources et des utilisateurs depuis un panneau web, sans éditer de fichiers de configuration.
  • Chiffrement de bout en bout WireGuard — le tunnel entre la machine d'origine et le VPS est chiffré au niveau transport, indépendamment du HTTPS applicatif.
  • Multisite — un seul Pangolin sur le VPS peut relayer des dizaines de services depuis des machines différentes, sous des sous-domaines distincts.

Architecture : VPS relay, Gerbil et Newt

Pangolin repose sur trois composants qui se répartissent les rôles :

[Machine d'origine]                [VPS ServOrbit]              [Internet]
  service:8080                      Pangolin (orchestration)
  newt (client)  ←─WireGuard UDP─→  Gerbil  (tunnel WG)   ←─HTTPS──→  visiteur
                                    Traefik (reverse proxy)

Pangolin est le plan de contrôle : il gère les tunnels, les sous-domaines, les certificats et les utilisateurs via une API REST et une interface web. Il tourne sur le VPS.

Gerbil est le pair WireGuard côté serveur. Il ouvre un port UDP, établit les tunnels avec les clients, et route le trafic entrant vers les services exposés. Il tourne également sur le VPS, aux côtés de Pangolin.

Newt est le client léger qui tourne sur la machine d'origine (NAS, Pi, VM locale). Il contacte Gerbil sur le port UDP WireGuard, maintient le tunnel actif, et redirige le trafic reçu vers le service local sur le port configuré.

Le flux concret : un visiteur arrive sur nextcloud.mondomaine.com → Traefik (géré par Pangolin) reçoit la requête HTTPS → la transmet via Gerbil au tunnel WireGuard actif → Newt la reçoit et la relaie vers localhost:8080 sur la machine d'origine. Le service répond par le même chemin en sens inverse.

Prérequis

Côté VPS :
- VPS avec accès root et IPv4 dédiée — le plan {{vps.start.name}} suffit pour démarrer (1 vCPU, 1 Go de RAM pour des charges légères, 2 Go recommandés pour plusieurs tunnels actifs).
- Ubuntu 22.04 ou 24.04 (Debian 12 fonctionne également).
- Un port UDP libre pour WireGuard (par défaut 51820, configurable).
- Un nom de domaine avec accès à la gestion DNS — vous devrez créer un enregistrement wildcard *.mondomaine.com pointant vers l'IP du VPS.
- Docker et Docker Compose installés (apt install docker.io docker-compose-plugin).

Côté machine d'origine :
- Une machine Linux (Raspberry Pi, NAS sous DSM 7+, VM Proxmox, serveur physique) avec accès sortant UDP vers le port WireGuard du VPS — la plupart des FAI le laissent passer.
- Un service qui écoute sur un port local (Nextcloud, Gitea, Home Assistant, etc.).

Version actuelle : Pangolin 1.23.0 (sortie le 16 septembre 2026).

Déploiement de Pangolin et Gerbil sur le VPS

  1. Préparer le VPS et ouvrir le port WireGuard

    Connectez-vous en root sur le VPS et installez Docker s'il n'est pas déjà présent :

    apt update && apt install -y docker.io docker-compose-plugin ufw

    Ouvrez le port UDP pour WireGuard (51820 par défaut) et assurez-vous que les ports HTTP/HTTPS sont accessibles :

    ufw allow 80/tcp
    ufw allow 443/tcp
    ufw allow 51820/udp
    ufw enable

    Si vous souhaitez restreindre l'accès au panneau d'administration (port 3000 par défaut), limitez-le à votre IP :

    ufw allow from VOTRE_IP to any port 3000
  2. Créer le fichier docker-compose.yml

    Créez un dossier de travail et le fichier de configuration :

    mkdir -p /opt/pangolin && cd /opt/pangolin

    Créez docker-compose.yml avec le contenu suivant :

    cat > docker-compose.yml <<'EOF'
    services:
      pangolin:
        image: fosrl/pangolin:1.23.0
        container_name: pangolin
        restart: unless-stopped
        volumes:
          - ./config:/app/config
          - ./data:/app/data
        ports:
          - "3000:3000"
        networks:
          - pangolin_net
    
      gerbil:
        image: fosrl/gerbil:latest
        container_name: gerbil
        restart: unless-stopped
        cap_add:
          - NET_ADMIN
        volumes:
          - ./data:/var/lib/gerbil
        ports:
          - "51820:51820/udp"
        networks:
          - pangolin_net
        depends_on:
          - pangolin
    
    networks:
      pangolin_net:
        driver: bridge
    EOF

    Adaptez le numéro de version de l'image pangolin à la dernière release disponible sur GitHub.

  3. Configurer Pangolin et démarrer la stack

    Créez le dossier de configuration et un fichier config.yml minimal :

    mkdir -p /opt/pangolin/config
    cat > /opt/pangolin/config/config.yml <<'EOF'
    app:
      base_domain: mondomaine.com
      admin_email: [email protected]
      port: 3000
    
    wireguard:
      port: 51820
      subnet: 10.0.0.0/24
    
    acme:
      enabled: true
      staging: false
    EOF

    Remplacez mondomaine.com par votre domaine réel. Démarrez la stack :

    cd /opt/pangolin && docker compose up -d
    docker compose logs -f pangolin

    Pangolin génère un mot de passe administrateur au premier démarrage — notez-le depuis les logs. L'interface web est accessible sur http://IP_VPS:3000.

  4. Configurer le DNS wildcard

    Dans votre zone DNS, créez un enregistrement A wildcard pointant vers l'IP du VPS :

    *.mondomaine.com  →  A  →  IP_VPS

    Sur Cloudflare, créez ce même enregistrement avec le proxy désactivé (DNS-only, nuage gris) pour que les certificats Let's Encrypt puissent être émis correctement via le défi HTTP-01 utilisé par Pangolin.

  5. Créer une unité systemd pour le redémarrage automatique

    Docker avec restart: unless-stopped suffit généralement, mais si vous préférez une unité systemd dédiée :

    cat > /etc/systemd/system/pangolin.service <<'EOF'
    [Unit]
    Description=Pangolin reverse tunnel stack
    After=docker.service
    Requires=docker.service
    
    [Service]
    Type=oneshot
    RemainAfterExit=yes
    WorkingDirectory=/opt/pangolin
    ExecStart=/usr/bin/docker compose up -d
    ExecStop=/usr/bin/docker compose down
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl daemon-reload
    systemctl enable pangolin

Ajout d'un tunnel avec Newt sur la machine d'origine

  1. Créer un tunnel dans l'interface Pangolin

    Connectez-vous à l'interface web Pangolin sur http://IP_VPS:3000 avec les identifiants admin. Allez dans Sites → Ajouter un site, donnez-lui un nom (ex. homelab) et notez le token de site généré. Puis dans Ressources → Ajouter une ressource, choisissez le site, saisissez le sous-domaine souhaité (nextcloud.mondomaine.com) et le port local de la machine d'origine (ex. 8080).

  2. Installer Newt sur la machine d'origine

    Sur la machine qui héberge votre service, téléchargez le binaire Newt correspondant à votre architecture :

    # Sur Linux x86_64
    curl -Lo /usr/local/bin/newt \
      https://github.com/fosrl/newt/releases/latest/download/newt-linux-amd64
    chmod +x /usr/local/bin/newt

    Pour un Raspberry Pi (ARM64) :

    curl -Lo /usr/local/bin/newt \
      https://github.com/fosrl/newt/releases/latest/download/newt-linux-arm64
    chmod +x /usr/local/bin/newt
  3. Configurer et démarrer Newt

    Lancez Newt avec le token de site récupéré à l'étape précédente :

    newt \
      --server https://mondomaine.com:3000 \
      --token VOTRE_TOKEN_DE_SITE \
      --target localhost:8080

    Pour un démarrage automatique, créez une unité systemd :

    cat > /etc/systemd/system/newt.service <<'EOF'
    [Unit]
    Description=Newt WireGuard tunnel client
    After=network.target
    
    [Service]
    ExecStart=/usr/local/bin/newt \
      --server https://mondomaine.com:3000 \
      --token VOTRE_TOKEN_DE_SITE \
      --target localhost:8080
    Restart=always
    RestartSec=5
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
    systemctl daemon-reload
    systemctl enable --now newt
  4. Vérifier la connectivité end-to-end

    Sur le VPS, vérifiez que le tunnel WireGuard est établi :

    docker exec gerbil wg show

    Vous devriez voir un peer avec un latest handshake récent. Depuis n'importe quel navigateur ou en ligne de commande :

    curl -I https://nextcloud.mondomaine.com

    Réponse attendue : HTTP/2 200 (ou la page de connexion de votre service). Le certificat Let's Encrypt est émis automatiquement au premier accès.

Exposition d'un service : exemple Nextcloud derrière NAT

  1. Configurer Nextcloud pour accepter le domaine proxy

    Nextcloud bloque les requêtes venant de domaines non déclarés. Ajoutez le domaine public à config.php :

    # Depuis la machine d'origine, dans le dossier Nextcloud
    nano config/config.php

    Ajoutez dans le tableau trusted_domains :

    'trusted_domains' =>
      array (
        0 => 'localhost',
        1 => 'nextcloud.mondomaine.com',
      ),
    'overwritehost' => 'nextcloud.mondomaine.com',
    'overwriteprotocol' => 'https',
  2. Vérifier l'accès public et le certificat

    Attendez 30 à 60 secondes après le premier accès pour que Let's Encrypt émette le certificat, puis :

    curl -v https://nextcloud.mondomaine.com 2>&1 | grep -E 'subject|issuer|HTTP'

    Le certificat est signé par Let's Encrypt et l'URL publique est désormais accessible depuis n'importe quel réseau, sans aucun port ouvert côté réseau local.

Sécurité : tokens, rotation et contrôle d'accès

Rotation des tokens de site — générez un nouveau token depuis l'interface Pangolin et mettez à jour l'unité systemd de Newt sur la machine d'origine. L'ancien token est immédiatement invalidé. Planifiez cette rotation tous les 90 jours ou à chaque changement de personnel ayant accès à la machine d'origine.

Restrictions IP dans Pangolin — pour chaque ressource exposée, vous pouvez définir une liste blanche d'IP dans Ressources → Politique d'accès. Utile pour restreindre l'accès à votre backoffice ou à vos outils internes à votre plage d'IP de bureau.

Accès authentifié — Pangolin prend en charge les providers OIDC (Authentik, Keycloak, Zitadel) pour ajouter une couche d'authentification devant n'importe quelle ressource exposée, sans modifier l'application derrière le tunnel.

Restriction du port d'administration — le port 3000 de Pangolin ne doit pas être accessible publiquement. Restreignez-le à votre IP avec ufw allow from VOTRE_IP to any port 3000 && ufw deny 3000.

Dépannage

Le tunnel ne s'établit pas — UDP bloqué par le FAI. Certains opérateurs filtrent l'UDP sortant sur des ports non standard. Testez depuis la machine d'origine : nc -u -v IP_VPS 51820. Si la connexion est refusée, changez le port WireGuard dans config.yml pour 443 (UDP) ou 53 (UDP) — ces ports passent presque toujours. Mettez à jour ufw sur le VPS en conséquence.

MTU mismatch — latence ou coupures aléatoires. WireGuard ajoute un overhead d'encapsulation (environ 60 octets). Si votre service transfère de gros fichiers et que vous observez des coupures, réduisez le MTU de l'interface WireGuard dans la configuration Gerbil : mtu = 1380 est une valeur sûre sur la plupart des liaisons.

Service non joignable après tunnel actif. Vérifiez d'abord que le service local écoute bien sur 0.0.0.0 et non uniquement sur 127.0.0.1 : ss -tlnp | grep 8080. Ensuite, confirmez que le port configuré dans Pangolin correspond au port réel du service. Enfin, vérifiez les logs de Newt : journalctl -u newt -f.

Certificat Let's Encrypt non émis. Pangolin utilise le défi HTTP-01, qui exige que le port 80 du VPS soit joignable depuis Internet. Vérifiez que ufw allow 80/tcp est actif et qu'aucun autre service ne tient le port 80 (ss -tlnp | grep :80). Sur Cloudflare, assurez-vous que l'enregistrement wildcard est en DNS-only (nuage gris).

Interface Pangolin inaccessible après redémarrage. Si Docker redémarre avant que le réseau soit disponible, Pangolin peut démarrer sans interface réseau. Ajoutez network-online.target dans la dépendance systemd, ou relancez simplement docker compose up -d depuis /opt/pangolin.

Pangolin vs Cloudflare Tunnel vs Tailscale/Headscale

Faites défiler le tableau

CritèrePangolin + GerbilCloudflare TunnelTailscale / Headscale
HébergementSelf-hosted sur votre VPSSaaS CloudflareSaaS (Tailscale) ou self-hosted (Headscale)
CoûtCoût du VPS uniquementGratuit jusqu'à certains seuils, puis abonnementGratuit (usage perso), abonnement équipe
Chiffrement E2EWireGuard entre la machine et le VPS, HTTPS jusqu'au visiteurTLS jusqu'aux serveurs Cloudflare (déchiffré en transit)WireGuard entre tous les nœuds (mesh complet)
Exposition HTTP publiqueOui, avec HTTPS automatique et sous-domaines personnalisésOui, avec certificats gérés par CloudflareNon prévu nativement (nécessite un reverse proxy en plus)
Complexité d'administrationMoyenne — une stack Docker à maintenir, une interface webFaible — connector en un binaire, tout géré côté CloudflareFaible (Tailscale) à Moyenne (Headscale auto-hébergé)
Confidentialité du traficTrafic visible uniquement sur votre VPSTrafic déchiffré par Cloudflare sur leurs serveursTrafic chiffré en mesh, jamais centralisé

Aller plus loin

Pangolin 1.23.0 introduit le support de la haute disponibilité en édition Enterprise et la gestion de plusieurs administrateurs serveur — des fonctionnalités utiles dès que votre infrastructure dépasse un usage personnel.

Pour exposer des services non-HTTP (SSH privé, base de données, protocoles UDP applicatifs), Pangolin prend désormais en charge les ressources TCP/UDP privées accessibles via le client Newt — sans les exposer publiquement sur une URL, mais en les rendant accessibles depuis votre réseau WireGuard.

Si votre besoin est différent — coordonner l'accès entre plusieurs machines sans exposition publique — Headscale sur VPS est l'outil adapté. Pour une exposition sans VPS intermédiaire en utilisant l'infrastructure Cloudflare, Cloudflare Tunnel reste l'option la plus simple. Et pour poser les bases du chiffrement réseau sur VPS, le guide WireGuard sur VPS couvre l'installation et la configuration de l'interface WireGuard native.

Un VPS avec accès root et IPv4 dédiée

Pangolin et Gerbil ont besoin d'un port UDP ouvert et d'une IPv4 dédiée pour écouter les connexions WireGuard entrantes. Les VPS ServOrbit fournissent les deux, avec le choix de l'OS et un accès root complet.

Besoin d'aide ?

Parcourez notre centre d'aide et notre FAQ, ou contactez notre équipe — rappel, WhatsApp ou e-mail. Support en français, anglais et arabe.

Écrire sur WhatsApps'ouvre dans un nouvel onglet