Docker Homelab Series - Phần 9: Cloudflare Tunnel: Hướng dẫn Expose Server không cần Public IP

Hướng dẫn Cloudflare Tunnel

Cloudflare Tunnel: Hướng dẫn Expose Server không cần Public IP

Cloudflare Tunnel

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:

  1. Đăng nhập Cloudflare Dashboard
  2. Chọn domain của bạn
  3. Vào NetworksTunnel
  4. Click Create a tunnel
  5. Đặt tên: my-tunnel
  6. Chọn connector: Docker
  7. 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:

  1. Tại dashboard tunnel, chọn tab Public Hostname
  2. Click Add a public hostname
  3. Đ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)
  4. 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

  1. Vào Portainer Dashboard
  2. Chọn StacksAdd stack
  3. Đặt tên Stack: cloudflare-tunnel
  4. Copy/paste docker-compose vào Web editor
  5. Thay YOUR_TOKEN_HERE bằng token thực tế từ Cloudflare
  6. Chọn network: docker-net
  7. 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:

  1. Vào Tunnel → Public Hostname
  2. 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:

  1. Vào Tunnel → Access
  2. Cấu hình authentication policy
  3. 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:

  1. Vào Uptime Kuma → Add New Monitor
  2. Chọn HTTP(s)
  3. URL: https://app.yourdomain.com
  4. Heartbeat Interval: 60
  5. 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:

  1. Tạo public hostname dengan type SSH
  2. Point tới: ssh://localhost:22
  3. 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!

Post a Comment

Previous Post Next Post
QR Code
Quét mã QR để gọi miễn phí