Cloudflare Tunnel: Hướng dẫn Expose Server không cần Public IP
I. Giới thiệu Cloudflare Tunnel
Cloudflare Tunnel (còn gọi là Argo Tunnel) cho phép bạn expose các ứng dụng và server tới internet mà không cần phải mở port hoặc có public IP. Điều này rất hữu ích khi:
- Bạn muốn expose server nhưng ISP không cấp public IP hoặc cấm mở port
- Muốn bảo vệ server khỏi trực tiếp truy cập từ internet
- Cần access server từ bất kỳ nơi nào mà không cần VPN
- Muốn tránh DDoS attack (Cloudflare filter sẵn)
- Cần setup nhanh mà không phức tạp
Lợi ích Cloudflare Tunnel:
- Không cần mở port trên firewall/router
- Tự động HTTPS với Cloudflare SSL
- DDoS protection & WAF (Web Application Firewall)
- Không cần public IP (chỉ cần outbound connection)
- Tốc độ nhanh (sử dụng Cloudflare global network)
- Miễn phí (1 tunnel/tháng)
- Dễ cấu hình qua Docker
So sánh Cloudflare Tunnel vs Ngrok vs Localtunnel:
| Tính năng | Cloudflare Tunnel | Ngrok | Localtunnel |
|---|---|---|---|
| Giá | Miễn phí (1 tunnel) | Miễn phí (limited), Paid | Miễn phí |
| Custom domain | Có (domain của bạn) | Có (paid) | Không |
| SSL/TLS | Tự động (Cloudflare) | Tự động | Tự động |
| Setup | Dễ | Dễ | Rất dễ |
| Stability | Rất ổn định | Ổn định | Bình thường |
II. Chuẩn bị Cloudflare & Tạo Tunnel
1. Tài khoản Cloudflare
Bạn cần có:
- Tài khoản Cloudflare (miễn phí)
- Domain quản lý bởi Cloudflare
Nếu chưa có, truy cập https://www.cloudflare.com để đăng ký.
2. Tạo Tunnel trong Cloudflare Dashboard
Bước tạo tunnel:
- Đăng nhập Cloudflare Dashboard
- Chọn domain của bạn
- Vào Networks → Tunnel
- Click Create a tunnel
- Đặt tên:
my-tunnel - Chọn connector: Docker
- Copy command sẽ xuất hiện (có TOKEN)
3. Lấy Tunnel Token
Cloudflare sẽ sinh ra token dạng:
cloudflared tunnel --no-autoupdate run --token eyJhbGciOiJSUzI1NiIsImtpZCI6IjM...
Copy phần token sau --token để dùng trong Docker.
4. Cấu hình Public Hostname (Optional)
Nếu muốn tạo domain public ngay lập tức:
- Tại dashboard tunnel, chọn tab Public Hostname
- Click Add a public hostname
- Điền thông tin:
- Subdomain:
app - Domain:
yourdomain.com - Type:
HTTP - URL:
http://127.0.0.1:80(hoặc app của bạn) - Click Save
Bây giờ app.yourdomain.com sẽ redirect tới server local của bạn qua tunnel.
III. Cấu hình Cloudflare Tunnel với Docker
1. Docker Compose cơ bản
version: '3.8'
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: always
command: tunnel --no-autoupdate run --token YOUR_TOKEN_HERE
mem_limit: 1024m
cpus: 0.1
networks:
- docker-net
networks:
docker-net:
external: true
Giải thích cấu hình:
- image: cloudflare/cloudflared:latest (official image)
- command: Chạy tunnel với token
- --no-autoupdate: Tắt auto-update (Docker sẽ quản lý version)
- networks: Sử dụng docker-net (mạng external có sẵn)
- restart: always: Tự động khởi động lại nếu crash
2. Deploy qua Portainer
- Vào Portainer Dashboard
- Chọn Stacks → Add stack
- Đặt tên Stack:
cloudflare-tunnel - Copy/paste docker-compose vào Web editor
- Thay YOUR_TOKEN_HERE bằng token thực tế từ Cloudflare
- Chọn network:
docker-net - Click Deploy the stack
3. Kiểm tra hoạt động
Vào Portainer → Stacks → cloudflare-tunnel → Container → cloudflared → Logs.
Bạn sẽ thấy dòng như:
INF |RPC stream 0 established INF Starting metrics server on 127.0.0.1:60168 INF Registered tunnel connection connIndex=0 INF Tunnel now available at: tunnel-name.cfargotunnel.com
Kiểm tra trong Cloudflare Dashboard → Tunnel → Status phải là HEALTHY.
IV. Cấu hình Routing & Public Hostname
1. Routing HTTP/HTTPS
Cloudflare Tunnel hỗ trợ routing dựa vào:
- Domain/Subdomain
- Path (ví dụ: /api/*, /admin/*)
- Protocol (HTTP, HTTPS, SSH, RDP)
Cấu hình trong Cloudflare Dashboard:
- Vào Tunnel → Public Hostname
- Thêm multiple hostnames cho các backend khác nhau
2. Ví dụ cấu hình nhiều backends
Hostname: app1.yourdomain.com → http://app1:3000 Hostname: app2.yourdomain.com → http://app2:3000 Hostname: db-admin.yourdomain.com → http://adminer:8080 Hostname: *.yourdomain.com → http://nginx-proxy:80
3. Access Control (Bảo vệ với Teams)
Để bảo vệ tunnel bằng Cloudflare Access:
- Vào Tunnel → Access
- Cấu hình authentication policy
- Chỉ người dùng authenticated mới có thể access
V. Tích hợp với Nginx Proxy Manager & Uptime Kuma
1. Sử dụng Cloudflare Tunnel với Nginx Proxy Manager
Khi combine Cloudflare Tunnel + Nginx Proxy Manager:
Internet → Cloudflare Tunnel → Nginx Proxy Manager → Backend Apps
Cấu hình:
- Cloudflare Tunnel point tới Nginx Proxy Manager (port 80)
- Nginx Proxy Manager forward tới các apps khác nhau
- SSL từ Cloudflare (ngoài) + Nginx (bên trong)
2. Giám sát Tunnel với Uptime Kuma
Để monitor Cloudflare Tunnel:
- Vào Uptime Kuma → Add New Monitor
- Chọn HTTP(s)
- URL:
https://app.yourdomain.com - Heartbeat Interval: 60
- Click Save
Uptime Kuma sẽ giám sát túnel qua domain public.
VI. Cấu hình Advanced
1. Environment File (Bảo mật Token)
Thay vì hardcode token:
version: '3.8'
services:
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
restart: always
command: tunnel --no-autoupdate run --token ${CLOUDFLARE_TOKEN}
env_file:
- /root/cloudflare/.env
mem_limit: 1024m
cpus: 0.1
networks:
- docker-net
networks:
docker-net:
external: true
File /root/cloudflare/.env:
CLOUDFLARE_TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IjM...
2. Health Check & Metrics
Cloudflared có metrics port (mặc định 60168):
command: tunnel --no-autoupdate run --token YOUR_TOKEN --metrics 127.0.0.1:60168
Có thể scrape metrics với Prometheus:
scrape_configs:
- job_name: 'cloudflared'
static_configs:
- targets: ['cloudflared:60168']
3. Multiple Connectors (High Availability)
Để redundancy, deploy 2 connectors:
version: '3.8'
services:
cloudflared-1:
image: cloudflare/cloudflared:latest
restart: always
command: tunnel --no-autoupdate run --token TOKEN_1
networks:
- docker-net
cloudflared-2:
image: cloudflare/cloudflared:latest
restart: always
command: tunnel --no-autoupdate run --token TOKEN_2
networks:
- docker-net
networks:
docker-net:
external: true
Tạo token từ cùng 1 tunnel, Cloudflare sẽ auto-balance.
4. SSH Tunnel
Expose SSH qua tunnel:
- Tạo public hostname dengan type SSH
- Point tới:
ssh://localhost:22 - SSH qua:
ssh -v [email protected]
VII. Troubleshooting
Tunnel không kết nối
- Kiểm tra token có đúng không
- Kiểm tra network outbound tới Cloudflare API
- Xem logs:
docker logs cloudflared - Thử recreate tunnel và lấy token mới
Public Hostname không hoạt động
- Kiểm tra tunnel status là HEALTHY
- Kiểm tra backend URL có accessible không
- Kiểm tra DNS pointing đúng chưa
- Xem logs Cloudflare (Analytics tab)
Connection timeout/slow
- Kiểm tra internet connection
- Kiểm tra backend response time
- Thử từ browser khác / device khác
- Kiểm tra Cloudflare rate limiting
VIII. Lưu ý quan trọng
- Token bảo mật: Giữ kín tunnel token, đừng share lên GitHub
- Network: Container cần outbound HTTPS tới Cloudflare API
- Backend URL: Phải là IP/hostname local (không public IP)
- SSL: Cloudflare tự động cung cấp SSL, backend không cần
- Bandwidth: Miễn phí nhưng Cloudflare có rate limit
- Uptime: Tùy thuộc vào Cloudflare infrastructure
- CORS: Nếu dùng API, cấu hình CORS đúng trong app
- Recreate tunnel: Nếu thay đổi routing, có thể phải restart container
IX. Best Practice
- Sử dụng environment variables cho token (không hardcode)
- Backup token ở nơi an toàn
- Enable Cloudflare Access để bảo vệ sensitive services
- Monitor tunnel health qua Uptime Kuma
- Kết hợp với Nginx Proxy Manager cho flexible routing
- Enable WAF trong Cloudflare Dashboard để bảo vệ application
- Kiểm tra analytics để theo dõi traffic
Vậy là bạn đã hoàn thành cấu hình Cloudflare Tunnel để expose server mà không cần public IP!