π A powerful Docker solution combining Traefik reverse proxy with Cloudflare Tunnel Expose your local services to the internet securely with automatic SSL and DNS management
- β¨ Features
- ποΈ Architecture
- π Quick Start
- βοΈ Service Configuration
- π Cloudflare Setup
- π§ Advanced Configuration
- π³ Docker Usage
- π€ Contributing
- π License
- π Acknowledgments
- π Support
|
|
graph TB
A[π Internet] --> B[βοΈ Cloudflare CDN]
B --> C[π Cloudflare Tunnel]
C --> D[π Traefik Proxy]
D --> E[π± Your Services]
F[π€ DNS API] --> G[π Auto DNS Records]
H[π Let's Encrypt] --> I[π SSL Certificates]
Flow Overview:
- π Internet Traffic β Cloudflare CDN for caching and protection
- π Secure Tunnel β Encrypted connection through Cloudflare Tunnel
- π Traefik Proxy β Intelligent routing to your services
- π€ Automatic SSL β Let's Encrypt certificates via DNS challenge
- π DNS Management β Auto-create subdomains for services
- π³ Docker & Docker Compose
- βοΈ Cloudflare account with domain
- π Cloudflare API tokens
git clone https://github.com/zenkiet/traefik-tunnel-expose.git
cd traefik-tunnel-expose# Copy example environment file
cp env.example .env
# Edit configuration
nano .env # or your preferred editor# User/Group Identifiers
# These help avoid permission issues between host and container
PUID=1000
PGID=1000
UMASK=022
# Container name prefix
CONTAINER_PREFIX=
# Paths for persistent data
CONFIG_PATH=/opt/appdata/config
DATA_PATH=/opt/appdata/data
# Container settings
TZ=Asia/Ho_Chi_Minh
RESTART_POLICY=unless-stopped
NETWORK_MODE=bridge
# ===== REQUIRED =====
HOST=127.0.0.1
BASE_DOMAIN=zenkiet.dev
TAG=latest
# =============================================================================
# AUTO UPDADTE
# =============================================================================
AUTO_UPDATE=TRUE
GOTIFY_URL=
GOFITY_TOKEN=
# =============================================================================
# CLOUDFLARE TUNNEL
# =============================================================================
CF_ENABLED=true
CLOUDFLARE_DNS_API_TOKEN=your_cloudflare_zone_api_token_here
CF_ZONE_ID=your_cloudflare_zone_id
CF_TUNNEL_ID=your_cloudflare_tunnel_id
CF_ACCOUNT_ID=your_cloudflare_account_id
CF_TUNNEL_SECRET=your_cloudflare_account_secret_id
CF_API_EMAIL=kietgolx65234@gmail.com
ACME_CA_SERVER=https://acme-staging-v02.api.letsencrypt.org/directory
#! For production, use:
# ACME_CA_SERVER=https://acme-v02.api.letsencrypt.org/directory# π Start services
make up
# π Check status
make status- ποΈ Traefik Dashboard: http://127.0.0.1:8080
- π Your Services: https://service.yourdomain.com
Create configuration files in conf.d/ directory:
# π HTTP Router and Service Configuration
http:
routers:
myapp:
rule: 'Host(`myapp.yourdomain.com`)'
service: 'myapp-service'
entrypoints:
- websecure
tls:
certResolver: cloudflare
middlewares:
- default-headers
- rate-limit
services:
myapp-service:
loadBalancer:
servers:
- url: 'http://myapp-container:3000'
healthCheck:
path: '/health'
interval: '30s'
middlewares:
default-headers:
headers:
frameDeny: true
sslRedirect: true
browserXssFilter: true
contentTypeNosniff: true
forceSTSHeader: true
stsIncludeSubdomains: true
stsPreload: true
stsSeconds: 31536000
rate-limit:
rateLimit:
burst: 100
average: 50π± Web Application with Authentication
http:
routers:
webapp-secure:
rule: 'Host(`webapp.yourdomain.com`)'
service: 'webapp'
entrypoints:
- websecure
tls:
certResolver: cloudflare
middlewares:
- auth
- secure-headers
services:
webapp:
loadBalancer:
servers:
- url: 'http://webapp:8080'
middlewares:
auth:
basicAuth:
users:
- 'admin:$2y$12$...' # Generated with htpasswd -nb admin <password>
secure-headers:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlAllowOriginList:
- https://yourdomain.com
accessControlMaxAge: 100
hostsProxyHeaders:
- 'X-Forwarded-Host'ποΈ Database Service (Internal Only)
http:
routers:
db-admin:
rule: 'Host(`db.yourdomain.com`)'
service: 'database-admin'
entrypoints:
- websecure
tls:
certResolver: cloudflare
middlewares:
- ip-whitelist
- auth
services:
database-admin:
loadBalancer:
servers:
- url: 'http://adminer:8080'
middlewares:
ip-whitelist:
ipWhiteList:
sourceRange:
- '192.168.1.0/24'
- '10.0.0.0/8'- π Navigate to Cloudflare API Tokens
- π§ Create Custom Token with permissions:
| Scope | Resource | Permission |
|---|---|---|
| Zone | Zone:Read | Specific zones |
| Zone | DNS:Edit | Specific zones |
| Account | Cloudflare Tunnel:Edit | Specific accounts |
- π Copy the generated token
π₯οΈ Using cloudflared CLI (Recommended here)
# π₯ Install cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb -o cloudflared.deb
sudo dpkg -i cloudflared.deb
# π Authenticate with Cloudflare
cloudflared tunnel login
# π Create tunnel
cloudflared tunnel create my-tunnel
# π« Generate tunnel token
cloudflared tunnel token my-tunnel
# π Print tunnel info
cloudflared tunnel info my-tunnel{
"Tunnel": "your-tunnel-id", # CF_TUNNEL_ID
"AccountTag": "your-account-tag", # CF_ACCOUNT_ID
"TunnelToken": "your-tunnel-token" # CF_TUNNEL_TOKEN
}- Go to Zero Trust β Networks β Tunnels
- Create new tunnel
- Install connector and copy the token
cloudflared tunnel token --cred-file ./credentials.json <TUNNEL_ID>{
"Tunnel": "your-tunnel-id", # CF_TUNNEL_ID
"AccountTag": "your-account-tag", # CF_ACCOUNT_ID
"TunnelToken": "your-tunnel-token" # CF_TUNNEL_TOKEN
}The service automatically creates DNS records, but you can manually verify:
# π Check DNS records
dig myapp.yourdomain.com
nslookup myapp.yourdomain.comβ‘ Custom Traefik Configuration
Create config/traefik-dynamic.yml for advanced settings:
# π TLS Configuration
tls:
options:
default:
sslProtocols:
- 'TLSv1.2'
- 'TLSv1.3'
cipherSuites:
- 'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384'
- 'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305'
- 'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256'
# π Global Middlewares
http:
middlewares:
secure-headers:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlMaxAge: 100
hostsProxyHeaders:
- 'X-Forwarded-Host'
referrerPolicy: 'same-origin'β‘ Performance Tuning
services:
traefik-tunnel:
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 256M
healthcheck:
test: ['CMD', 'traefik', 'healthcheck']
interval: 30s
timeout: 10s
retries: 3
start_period: 40s# π― Latest version
docker pull zenkiet/traefik-tunnel-expose:latest
# π·οΈ Specific version
docker pull zenkiet/traefik-tunnel-expose:v1.0.0
# π Check image info
docker inspect zenkiet/traefik-tunnel-expose:latestdocker run -d \
--name traefik-tunnel \
--restart unless-stopped \
-p 80:80 \
-p 443:443 \
-p 8080:8080 \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./data:/data \
-v ./config:/etc/traefik \
-e CF_API_TOKEN=your_token \
-e CF_ZONE_ID=your_zone_id \
zenkiet/traefik-tunnel-expose:latestWe welcome contributions! Here's how you can help:
- π Search existing issues
- π Create detailed bug report
- π·οΈ Use appropriate labels
- π‘ Discuss in GitHub Discussions
- π Create feature request issue
- π Submit pull request
# π΄ Fork and clone
git clone https://github.com/your-username/traefik-tunnel-expose.git
cd traefik-tunnel-expose
# πΏ Create feature branch
git checkout -b feature/amazing-feature
# π§ Make changes and test
docker-compose up -d
# β
Commit changes
git commit -m "β¨ Add amazing feature"
# π Push and create PR
git push origin feature/amazing-featureWe use Conventional Commits:
β¨ feat:New featuresπ fix:Bug fixesπ docs:Documentationπ¨ style:Code formattingβ»οΈ refactor:Code restructuringβ‘ perf:Performance improvementsβ test:Testingπ§ chore:Maintenance
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License
Copyright (c) 2025 ZenKiet
This project wouldn't be possible without these amazing technologies:
|
Traefik Reverse Proxy |
Cloudflare Tunnel & Security |
Alpine Linux Lightweight OS |
Docker Containerization |
β If this project helped you, please consider giving it a star! β
Made with β€οΈ by ZenKiet