Bypass DS-Lite: Reverse Proxy with Docker & Pangolin
Learn how to bypass DS-Lite with a tunnel and securely access your local services using a reverse proxy with Docker and Pangolin.

Table of Contents
In the age of DS-Lite (Dual Stack Lite), it’s becoming increasingly difficult to access your own services—like websites, APIs, or other applications—from the internet. Why? Because many internet providers no longer assign public IPv4 addresses. But don’t worry—this article will show you how to solve this problem! With the open-source reverse proxy Pangolin, you can create a secure tunnel between your local server and an external VPS. This way, you can access your services from anywhere in the world.
Why DS-Lite Is a Problem
Before we dive into the solution, let’s quickly review why DS-Lite is such a hurdle:
- No Public IPv4 Address: With DS-Lite, you don’t get your own public IPv4 address. This means your router isn’t directly accessible from the internet.
- Restricted Remote Access: Without a public IP address, you can’t open ports to reach services like a web server or other applications from outside your network.
- IPv6 as an Alternative? Theoretically, you could use IPv6, but many networks and devices still don’t fully support it. Plus, configuring IPv6 can be tricky and unreliable.
The solution is simple: Use an external VPS (virtual private server) as a bridge between your local network and the internet. Sounds like a lot of work? It’s not—if you know how to do it.
What Is a Reverse Proxy?
A reverse proxy is a server that accepts requests from the outside and forwards them to the correct service in your local network. Think of it like a post office: You send a letter to the post office, and they make sure it reaches the right recipient.
With Pangolin, this process becomes even easier. Pangolin is an open-source tool specifically designed to create secure tunnels between your local server and an external VPS. It uses modern encryption and is incredibly easy to configure.
What You Need for This Setup
Before we begin, here’s a quick list of what you’ll need:
- A Local Server: This could be a Raspberry Pi, an old PC, or any other machine running your services.
- An External VPS: A virtual server with a public IP address. I recommendNetcup, as they offer affordable plans starting at just 1 € per month.
- Domain: A domain where you can adjust DNS settings. Again, Netcup offers domains for as little as 0.42 € per month.
- Basic Linux Knowledge: You should know how to connect to a server via SSH and execute basic commands.
Would you prefer a German video tutorial with all the steps? Check out this YouTube video.
Step-by-Step: Setting Up Your Reverse Proxy with Pangolin
Prepare Your Local Server
First, set up your local server. Install Docker and Docker Compose if you haven’t already.
Rent and Set Up a VPS
Next, rent a VPS with Ubuntu as the operating system. After connecting to the server via SSH, update the system and install Docker.
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/raspbian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/raspbian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Install Pangolin
Create the necessary folders for Pangolin and its configuration files.
mkdir -p pangolin/config
touch pangolin/config/traefik_config.yaml
touch pangolin/config/dynamic_config.yml
touch pangolin/docker-compose.yml
Customize these files to suit your needs, especially the domain.
docker-compose.yml:
services:
pangolin:
image: fosrl/pangolin:1.0.0-beta.14
container_name: pangolin
restart: unless-stopped
volumes:
- ./config:/app/config
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
interval: "3s"
timeout: "3s"
retries: 5
gerbil:
image: fosrl/gerbil:1.0.0-beta.3
container_name: gerbil
restart: unless-stopped
depends_on:
pangolin:
condition: service_healthy
command:
- --reachableAt=http://gerbil:3003
- --generateAndSaveKeyTo=/var/config/key
- --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config
- --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth
volumes:
- ./config/:/var/config
cap_add:
- NET_ADMIN
- SYS_MODULE
ports:
- 51820:51820/udp
- 443:443 # Port for traefik because of the network_mode
- 80:80 # Port for traefik because of the network_mode
traefik:
image: traefik:v3.3.3
container_name: traefik
restart: unless-stopped
network_mode: service:gerbil # Ports appear on the gerbil service
depends_on:
pangolin:
condition: service_healthy
command:
- --configFile=/etc/traefik/traefik_config.yml
volumes:
- ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
- ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
networks:
default:
driver: bridge
name: pangolin
traefik_config.yaml:
api:
insecure: true
dashboard: true
providers:
http:
endpoint: "http://pangolin:3001/api/v1/traefik-config"
pollInterval: "5s"
file:
filename: "/etc/traefik/dynamic_config.yml"
experimental:
plugins:
badger:
moduleName: "github.com/fosrl/badger"
version: "v1.0.0-beta.3"
log:
level: "INFO"
format: "common"
certificatesResolvers:
letsencrypt:
acme:
httpChallenge:
entryPoint: web
email: admin@example.com # REPLACE THIS WITH YOUR EMAIL
storage: "/letsencrypt/acme.json"
caServer: "https://acme-v02.api.letsencrypt.org/directory"
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: "30m"
http:
tls:
certResolver: "letsencrypt"
serversTransport:
insecureSkipVerify: true
dynamic_config.yml (hier die E-Mail-Adresse anpassen):
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
routers:
# HTTP to HTTPS redirect router
main-app-router-redirect:
rule: "Host(`proxy.example.com`)" # REPLACE THIS WITH YOUR DOMAIN
service: next-service
entryPoints:
- web
middlewares:
- redirect-to-https
# Next.js router (handles everything except API and WebSocket paths)
next-router:
rule: "Host(`proxy.example.com`) && !PathPrefix(`/api/v1`)" # REPLACE THIS WITH YOUR DOMAIN
service: next-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
# API router (handles /api/v1 paths)
api-router:
rule: "Host(`proxy.example.com`) && PathPrefix(`/api/v1`)" # REPLACE THIS WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
# WebSocket router
ws-router:
rule: "Host(`proxy.example.com`)" # REPLACE THIS WITH YOUR DOMAIN
service: api-service
entryPoints:
- websecure
tls:
certResolver: letsencrypt
services:
next-service:
loadBalancer:
servers:
- url: "http://pangolin:3002" # Next.js server
api-service:
loadBalancer:
servers:
- url: "http://pangolin:3000" # API/WebSocket server
Start the Containers
Start the containers to generate the remaining files.
sudo docker compose -f pangolin/docker-compose.yml up -d
Once the config/config.yaml
file is created, stop the containers and customize it.
sudo docker compose -f pangolin/docker-compose.yml down
sudo nano pangolin/config/config.yaml
app:
dashboard_url: "https://example.com" # Auf deine Domain anpassen
base_domain: "example.com" # Auf deine Domain anpassen
log_level: "info" # debug, info, warn, error
save_logs: false # true, false
# log_failed_attempts: true # true, false
server:
external_port: 3000
internal_port: 3001
next_port: 3002
internal_hostname: "pangolin"
session_cookie_name: "p_session_token"
resource_access_token_param: "p_token"
resource_session_request_param: "p_session_request"
traefik:
cert_resolver: "letsencrypt"
http_entrypoint: "web"
https_entrypoint: "websecure"
prefer_wildcard_cert: true
gerbil:
start_port: 51820
base_endpoint: "example.com" # Auf deine Domain anpassen
use_subdomain: false
block_size: 24
site_block_size: 30
subnet_group: 100.89.137.0/20
rate_limits:
global:
window_minutes: 1
max_requests: 100
email:
smtp_host: "host.hoster.net" # Auf deine E-Mail-Einstellungen anpassen
smtp_port: 587 # Auf deine E-Mail-Einstellungen anpassen
smtp_user: "no-reply@example.com" # Auf deine E-Mail-Einstellungen anpassen
smtp_pass: "aaaaaaaaaaaaaaaaaa" # Auf deine E-Mail-Einstellungen anpassen
no_reply: "no-reply@example.com" # Auf deine E-Mail-Einstellungen anpassen
users:
server_admin:
email: "admin@example.com" # Login Daten anpassen
password: "Password123!" # Login Daten anpassen
flags:
require_email_verification: true
disable_signup_without_invite: true
disable_user_create_org: true
allow_raw_resources: true
allow_base_domain_resources: true
Log In
Open your browser and navigate to the URL you specified in the config.yaml
. Log in using the credentials you defined in the same file. Save the Newt configuration to establish a tunnel between your local server and the VPS.
Install Newt
With Newt, you create a secure tunnel between your local server and the VPS. This tunnel allows you to access your local services via the external server.
Install Newt on your local server:
mkdir newt
touch newt/docker-compose.yml
nano newt/docker-compose.yml
services:
newt:
image: fosrl/newt
container_name: newt
restart: unless-stopped
environment:
- PANGOLIN_ENDPOINT=https://example.com
- NEWT_ID=2ix2t8xk22ubpfy
- NEWT_SECRET=nnisrfsdfc7prqsp9ewo1dvtvci50j5uiqotez00dgap0ii2
Adjust the values for PANGOLIN_ENDPOINT
, NEWT_ID
, and NEWT_SECRET
.
Start the container:
sudo docker compose -f newt/docker-compose.yml up -d
You should now see a successful connection in the Pangolin interface.
Create a Resource
Create a resource in the Pangolin interface to enable access to your local server.
Conclusion
With a reverse proxy and Pangolin, you can elegantly bypass the DS-Lite issue and securely access your local services from anywhere. While the setup might seem complex at first, the effort pays off: You gain full control over your data and independence from expensive cloud services.
Give it a try and share your experiences in the comments!