tva
← Insights

Traefik 反向代理:HTTPS 和 SSL 自动化的完整自托管指南

当您能够在不同域名下运行多个应用并自动获得 HTTPS 时,自托管的能力将呈指数级增长。Traefik 是一款现代反向代理,它使这一切成为可能,消除了手动 SSL 证书管理的复杂性,同时提供生产级的路由能力。如果您曾在 Nginx 配置或 Let’s Encrypt 续期上苦苦挣扎,Traefik 将彻底革新您的自托管工作流。

您将构建的内容

完成本综合指南后,您将拥有:

  • Traefik 反向代理处理所有 HTTP/HTTPS 流量
  • 自动 SSL 证书通过 Let’s Encrypt 实现零维护
  • 多个服务在不同域名/子域名下运行
  • 生产就绪配置可从个人项目扩展到企业级
  • 高级路由规则支持复杂应用架构
  • 容器自动发现消除手动配置
  • 安全加固配备适当的头信息和重定向

为什么选择 Traefik 而非传统反向代理

传统方案的痛点

Nginx/Apache 的挑战:

  • 手动 SSL 证书管理和续期
  • 复杂且容易出错的配置文件
  • 无自动服务发现
  • 每个新服务都需要单独配置
  • 手动更新负载均衡器

Traefik 的优势:

  • 自动服务发现:容器自行注册
  • 零停机 SSL:Let’s Encrypt 集成并自动续期
  • 动态配置:添加服务时无需重启
  • Docker 原生:专为容器化环境构建
  • 现代协议:开箱即用的 HTTP/2、WebSocket、gRPC 支持

成本和效率优势

使用 Traefik 自托管与托管解决方案的对比:

  • Cloudflare Pro:每个域名 $20/月
  • AWS Application Load Balancer:$16-25/月 + 数据传输费
  • 自托管 Traefik:€5-8/月(无限域名)
  • 年度节省:$150-250+,取决于规模

前提条件

  • 云服务器(任何提供商:DigitalOcean、Vultr、Linode、AWS 等)
  • 可控制 DNS 的域名
  • 基本的 Docker 知识
  • 服务器的 SSH 访问权限

步骤 1:服务器准备

创建云服务器

推荐的云服务器规格:

  • 镜像:Ubuntu 24.04 LTS
  • 类型:小型实例(1 vCPU,4 GB RAM)– 约 €5-8/月
  • 地点:选择离您用户最近的位置
  • SSH 密钥:添加您的公钥以实现安全访问

初始服务器设置

连接到您的服务器:

ssh root@YOUR_SERVER_IP

更新系统并安装 Docker:

# System updates
apt update && apt upgrade -y

# Install Docker dependencies
apt install apt-transport-https ca-certificates curl software-properties-common gnupg -y

# Add Docker GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add Docker repository
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker
apt update
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

# Create Docker network for Traefik
docker network create proxy

验证安装:

docker --version
docker compose version

步骤 2:核心 Traefik 配置

目录结构设置

为 Traefik 安装创建有组织的目录:

mkdir -p /opt/traefik/data
cd /opt/traefik

主 Traefik 配置

创建主配置文件:

nano /opt/traefik/data/traefik.yml

添加以下生产就绪配置:

# Global configuration
global:
  checkNewVersion: false
  sendAnonymousUsage: false

# API configuration (disabled for security)
api:
  dashboard: false
  insecure: false

# Entry points define which ports Traefik listens on
entryPoints:
  http:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: https
          scheme: https
          permanent: true
  https:
    address: ":443"

# Provider configuration - tells Traefik where to find services
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
    network: proxy
    watch: true

# Certificate management with Let's Encrypt
certificatesResolvers:
  letsencrypt:
    acme:
      email: your-email@example.com  # CHANGE THIS!
      storage: acme.json
      httpChallenge:
        entryPoint: http
      # Uncomment for staging (testing) certificates
      # caServer: https://acme-staging-v02.api.letsencrypt.org/directory

# Logging configuration
log:
  level: INFO
  filePath: "/var/log/traefik.log"

accessLog:
  filePath: "/var/log/access.log"

# Metrics (optional but recommended)
metrics:
  prometheus:
    addEntryPointsLabels: true
    addServicesLabels: true

SSL 证书存储

创建证书存储文件:

touch /opt/traefik/data/acme.json
chmod 600 /opt/traefik/data/acme.json

Docker Compose 配置

创建 Traefik Docker Compose 文件:

nano /opt/traefik/docker-compose.yml

添加以下配置:

version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "80:80"
      - "443:443"
    networks:
      - proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./data/acme.json:/acme.json
      - ./logs:/var/log
    environment:
      - TZ=Europe/Berlin  # Change to your timezone
    labels:
      - "traefik.enable=true"
      # Optional: Traefik dashboard (enable only if needed)
      # - "traefik.http.routers.dashboard.rule=Host(`traefik.yourdomain.com`)"
      # - "traefik.http.routers.dashboard.entrypoints=https"
      # - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      # - "traefik.http.routers.dashboard.service=api@internal"

networks:
  proxy:
    external: true

创建日志目录

mkdir -p /opt/traefik/logs

步骤 3:使用简单应用测试

在部署复杂应用之前,让我们用一个简单的 Web 服务测试 Traefik。

创建测试服务

mkdir -p /opt/whoami
cd /opt/whoami

创建测试服务的 Docker Compose 文件:

nano /opt/whoami/docker-compose.yml
version: '3.8'

services:
  whoami:
    image: traefik/whoami:latest
    container_name: whoami
    restart: unless-stopped
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`test.yourdomain.com`)"  # CHANGE THIS!
      - "traefik.http.routers.whoami.entrypoints=https"
      - "traefik.http.routers.whoami.tls.certresolver=letsencrypt"
      - "traefik.http.services.whoami.loadbalancer.server.port=80"

networks:
  proxy:
    external: true

启动服务

首先启动 Traefik:

cd /opt/traefik
docker compose up -d

检查 Traefik 日志:

docker logs traefik

启动测试服务:

cd /opt/whoami
docker compose up -d

DNS 配置

将测试子域名指向您的服务器:

  • 前往您的 DNS 提供商
  • 创建一条 A 记录:
    • 名称:test
    • 类型:A
    • :YOUR_SERVER_IP
    • TTL:300

等待 DNS 传播(通常 5-15 分钟)。

测试您的设置

访问 https://test.yourdomain.com – 您应该看到:

  • 绿色锁图标(HTTPS 正常工作)
  • 关于处理请求的容器信息
  • 没有证书警告

步骤 4:实际应用示例

示例 1:带数据库的 WordPress

mkdir -p /opt/wordpress
cd /opt/wordpress
nano docker-compose.yml
version: '3.8'

services:
  wordpress:
    image: wordpress:latest
    container_name: wordpress
    restart: unless-stopped
    networks:
      - proxy
      - wordpress-internal
    environment:
      - WORDPRESS_DB_HOST=wordpress-db
      - WORDPRESS_DB_NAME=wordpress
      - WORDPRESS_DB_USER=wordpress
      - WORDPRESS_DB_PASSWORD=secure_password_here
    volumes:
      - wordpress_data:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wordpress.rule=Host(`blog.yourdomain.com`)"
      - "traefik.http.routers.wordpress.entrypoints=https"
      - "traefik.http.routers.wordpress.tls.certresolver=letsencrypt"
      - "traefik.http.services.wordpress.loadbalancer.server.port=80"

  wordpress-db:
    image: mariadb:latest
    container_name: wordpress-db
    restart: unless-stopped
    networks:
      - wordpress-internal
    environment:
      - MYSQL_ROOT_PASSWORD=root_password_here
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wordpress
      - MYSQL_PASSWORD=secure_password_here
    volumes:
      - wordpress_db:/var/lib/mysql

volumes:
  wordpress_data:
  wordpress_db:

networks:
  proxy:
    external: true
  wordpress-internal:
    internal: true

示例 2:多子域名

mkdir -p /opt/multisite
cd /opt/multisite
nano docker-compose.yml
version: '3.8'

services:
  # Main application
  app:
    image: nginx:alpine
    container_name: main-app
    restart: unless-stopped
    networks:
      - proxy
    volumes:
      - ./html:/usr/share/nginx/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.app.rule=Host(`app.yourdomain.com`)"
      - "traefik.http.routers.app.entrypoints=https"
      - "traefik.http.routers.app.tls.certresolver=letsencrypt"

  # API service
  api:
    image: nginx:alpine
    container_name: api-service
    restart: unless-stopped
    networks:
      - proxy
    volumes:
      - ./api:/usr/share/nginx/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.yourdomain.com`)"
      - "traefik.http.routers.api.entrypoints=https"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"

  # Admin panel
  admin:
    image: nginx:alpine
    container_name: admin-panel
    restart: unless-stopped
    networks:
      - proxy
    volumes:
      - ./admin:/usr/share/nginx/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.admin.rule=Host(`admin.yourdomain.com`)"
      - "traefik.http.routers.admin.entrypoints=https"
      - "traefik.http.routers.admin.tls.certresolver=letsencrypt"

networks:
  proxy:
    external: true

步骤 5:高级路由和中间件

基于路径的路由

将不同路径路由到不同服务:

labels:
  - "traefik.enable=true"
  # Main app gets everything
  - "traefik.http.routers.app-main.rule=Host(`yourdomain.com`) && PathPrefix(`/`)"
  - "traefik.http.routers.app-main.priority=1"
  
  # API gets /api paths
  - "traefik.http.routers.app-api.rule=Host(`yourdomain.com`) && PathPrefix(`/api`)"
  - "traefik.http.routers.app-api.priority=10"
  - "traefik.http.routers.app-api.middlewares=api-stripprefix"
  
  # Strip /api prefix before forwarding
  - "traefik.http.middlewares.api-stripprefix.stripprefix.prefixes=/api"

安全中间件

添加安全头和身份验证:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.secure-app.rule=Host(`secure.yourdomain.com`)"
  - "traefik.http.routers.secure-app.entrypoints=https"
  - "traefik.http.routers.secure-app.tls.certresolver=letsencrypt"
  - "traefik.http.routers.secure-app.middlewares=security-headers,basic-auth"
  
  # Security headers
  - "traefik.http.middlewares.security-headers.headers.frameDeny=true"
  - "traefik.http.middlewares.security-headers.headers.sslRedirect=true"
  - "traefik.http.middlewares.security-headers.headers.browserXssFilter=true"
  - "traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true"
  - "traefik.http.middlewares.security-headers.headers.forceSTSHeader=true"
  - "traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true"
  - "traefik.http.middlewares.security-headers.headers.stsPreload=true"
  - "traefik.http.middlewares.security-headers.headers.stsSeconds=31536000"
  
  # Basic authentication (generate with: htpasswd -nb username password)
  - "traefik.http.middlewares.basic-auth.basicauth.users=admin:$$2y$$10$$..."

速率限制

保护您的服务免受滥用:

labels:
  - "traefik.http.middlewares.rate-limit.ratelimit.average=100"
  - "traefik.http.middlewares.rate-limit.ratelimit.period=1m"
  - "traefik.http.middlewares.rate-limit.ratelimit.burst=50"
  - "traefik.http.routers.app.middlewares=rate-limit"

步骤 6:Systemd 集成和自动启动

创建 Systemd 服务

nano /etc/systemd/system/traefik-docker.service
[Unit]
Description=Traefik Docker Compose
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/traefik
ExecStart=/usr/bin/docker compose up -d
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=300
Restart=on-failure
RestartSec=30

[Install]
WantedBy=multi-user.target

启用自动启动

systemctl daemon-reload
systemctl enable traefik-docker.service
systemctl start traefik-docker.service

验证服务

systemctl status traefik-docker.service
docker ps | grep traefik

步骤 7:监控和日志

启用 Prometheus 指标

在您的 traefik.yml 中添加:

metrics:
  prometheus:
    addEntryPointsLabels: true
    addServicesLabels: true
    addRoutersLabels: true

访问指标: http://YOUR_SERVER_IP:8080/metrics

日志分析

监控 Traefik 活动:

# Real-time logs
docker logs -f traefik

# Access logs
tail -f /opt/traefik/logs/access.log

# Error patterns
grep -i error /opt/traefik/logs/traefik.log

健康检查

创建监控脚本:

nano /opt/scripts/traefik-health.sh
#!/bin/bash

# Check if Traefik container is running
if ! docker ps | grep -q traefik; then
    echo "ERROR: Traefik container not running"
    exit 1
fi

# Check if Traefik is responding
if ! curl -f -s http://localhost:80 > /dev/null; then
    echo "ERROR: Traefik not responding on port 80"
    exit 1
fi

# Check certificate expiry (basic check)
if [ -s /opt/traefik/data/acme.json ]; then
    echo "OK: Certificates present"
else
    echo "WARNING: No certificates found"
fi

echo "OK: Traefik health check passed"
chmod +x /opt/scripts/traefik-health.sh

步骤 8:备份和灾难恢复

自动备份脚本

nano /opt/scripts/backup-traefik.sh
#!/bin/bash

BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Backup Traefik configuration
tar -czf $BACKUP_DIR/traefik-config-$DATE.tar.gz \
    /opt/traefik/data/traefik.yml \
    /opt/traefik/data/acme.json \
    /opt/traefik/docker-compose.yml

# Backup all service configurations
tar -czf $BACKUP_DIR/services-config-$DATE.tar.gz \
    /opt/*/docker-compose.yml \
    --exclude=/opt/backups

# Keep only last 30 days of backups
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete

echo "Backup completed: $BACKUP_DIR/traefik-config-$DATE.tar.gz"
chmod +x /opt/scripts/backup-traefik.sh

定时备份

crontab -e

添加每天凌晨 2 点的备份:

0 2 * * * /opt/scripts/backup-traefik.sh

恢复程序

# Stop Traefik
systemctl stop traefik-docker.service

# Restore configuration
cd /opt
tar -xzf /opt/backups/traefik-config-YYYYMMDD_HHMMSS.tar.gz

# Fix permissions
chmod 600 /opt/traefik/data/acme.json

# Restart Traefik
systemctl start traefik-docker.service

常见问题排查

SSL 证书问题

问题:证书未生成

# Check Traefik logs
docker logs traefik | grep -i acme

# Common causes:
# 1. DNS not pointing to server
# 2. Port 80 blocked
# 3. Wrong email in configuration
# 4. Rate limits (5 certificates per domain per week)

解决方案:先使用测试证书:

certificatesResolvers:
  letsencrypt:
    acme:
      caServer: https://acme-staging-v02.api.letsencrypt.org/directory

服务不可访问

问题:服务返回 404 或 502

# Check if container is in proxy network
docker inspect CONTAINER_NAME | grep -A 10 Networks

# Check Traefik routing
docker logs traefik | grep -i "router"

# Verify labels
docker inspect CONTAINER_NAME | grep -A 20 Labels

复杂的 Traefik 配置可能涉及复杂的路由规则、中间件配置和跨多个服务的证书管理。如果您遇到持续的路由问题或需要帮助优化生产环境的 Traefik 部署,不要浪费时间独自排查 – 联系我们的基础设施团队获取专家指导。

性能问题

问题:响应时间缓慢

# Check resource usage
docker stats traefik

# Increase worker processes in traefik.yml
global:
  maxIdleConnsPerHost: 200

# Enable HTTP/2
entryPoints:
  https:
    address: ":443"
    http2:
      maxConcurrentStreams: 250

内存问题

问题:Traefik 消耗过多内存

# Add memory limits to docker-compose.yml
services:
  traefik:
    # ... existing config
    deploy:
      resources:
        limits:
          memory: 128M
        reservations:
          memory: 64M

安全最佳实践

防火墙配置

# Install UFW
apt install ufw

# Default policies
ufw default deny incoming
ufw default allow outgoing

# Allow SSH (change port if needed)
ufw allow 22

# Allow HTTP/HTTPS only
ufw allow 80
ufw allow 443

# Enable firewall
ufw enable

容器安全

# Run containers as non-root user where possible
# Add to docker-compose.yml:
services:
  app:
    user: "1000:1000"  # Use appropriate UID:GID
    security_opt:
      - no-new-privileges:true
    read_only: true
    tmpfs:
      - /tmp

定期安全更新

# Create update script
nano /opt/scripts/update-system.sh
#!/bin/bash

# Update system packages
apt update && apt upgrade -y

# Update Docker images
cd /opt/traefik && docker compose pull && docker compose up -d
cd /opt/whoami && docker compose pull && docker compose up -d

# Clean up old images
docker system prune -f

# Check for failed services
systemctl --failed

IP 白名单

对于管理界面,按 IP 限制访问:

labels:
  - "traefik.http.middlewares.admin-whitelist.ipwhitelist.sourcerange=192.168.1.0/24,10.0.0.0/8"
  - "traefik.http.routers.admin.middlewares=admin-whitelist"

性能优化

HTTP/2 和 HTTP/3

启用现代协议:

# In traefik.yml
entryPoints:
  https:
    address: ":443"
    http2:
      maxConcurrentStreams: 250
    # Experimental HTTP/3 support
    http3: {}

压缩

启用 gzip 压缩:

# Add middleware for compression
labels:
  - "traefik.http.middlewares.gzip.compress=true"
  - "traefik.http.routers.app.middlewares=gzip"

缓存头

为静态资源添加缓存:

labels:
  - "traefik.http.middlewares.cache-headers.headers.customresponseheaders.Cache-Control=public, max-age=31536000"
  - "traefik.http.routers.static.middlewares=cache-headers"

成本分析与投资回报

自托管与托管服务对比

月度成本对比:

服务托管解决方案自托管年度节省
负载均衡器$25/月€5-8/月$200+
SSL 证书$10/月免费$120
多域名$5/域名/月免费$300+
总计$40+/月€5-8/月$350+

盈亏平衡分析

  • 初始设置时间:4-6 小时
  • 月度维护:1-2 小时
  • 学习曲线:2-3 天达到完全熟练
  • 投资回报:大多数场景在 30-60 天内转正

扩展您的基础设施

多服务器设置

实现高可用性:

# Load balance between multiple backends
labels:
  - "traefik.http.services.app.loadbalancer.server.port=80"
  - "traefik.http.services.app.loadbalancer.healthcheck.path=/health"
  - "traefik.http.services.app.loadbalancer.healthcheck.interval=30s"

容器编排

准备好后迁移到 Docker Swarm 或 Kubernetes:

# Docker Swarm mode
version: '3.8'
services:
  traefik:
    image: traefik:v3.0
    deploy:
      replicas: 2
      placement:
        constraints:
          - node.role == manager

使用 Traefik 进行企业级扩展涉及复杂的负载均衡策略、健康检查配置和跨多台服务器的高可用设置。正在规划重大基础设施增长? 让我们讨论您的扩展需求 – 我们的团队专注于设计稳健的、面向未来的基础设施架构。

数据库集群

适用于关键任务应用:

# MariaDB Galera cluster example
services:
  db-cluster:
    image: mariadb:latest
    deploy:
      replicas: 3
    environment:
      - MYSQL_INITDB_SKIP_TZINFO=1
      - MYSQL_ROOT_PASSWORD=secure_password

专业基础设施支持

使用 Traefik 自托管提供了令人难以置信的灵活性和成本节省,但实施生产级反向代理基础设施需要仔细考虑安全性、性能和可扩展性需求。当有专家帮助可用时,为什么还要苦苦挣扎于复杂的配置?

专业支持可加速成功的复杂场景:

  • 多服务器负载均衡和高可用配置
  • 带 WAF 和 DDoS 防护的高级安全实施
  • 高流量应用的性能优化
  • 受监管行业的合规要求
  • 定制中间件开发和高级路由逻辑
  • 与现有企业基础设施的集成

准备好实施专业级基础设施了吗?

不要花费数周时间排查专家几天就能实施的配置。 无论您是在我们的 n8n 自托管基础之上构建还是实施全新的基础设施,专业指导确保从第一天起就获得最佳结果。

立即联系我们的基础设施专家 – 我们与各种规模的组织合作,实施稳健、可扩展的反向代理解决方案。从初始设置到高级企业部署,我们将确保您的自托管基础设施满足当前需求和雄心勃勃的增长计划。

总结

Traefik 将自托管从复杂的工作变为优雅的自动化过程。凭借自动 SSL 证书管理、服务发现和强大的路由能力,您可以以传统成本的一小部分运行企业级基础设施。

本教程与我们的 完整 n8n 自托管指南完美衔接 – 如果您已经按照那个教程操作,Traefik 已经在运行,现在您可以使用相同的反向代理设置将基础设施扩展到托管多个应用。

此设置的关键优势:

  • 经济高效:与托管解决方案相比每年节省数百美元
  • 零维护 SSL:自动证书生成和续期
  • 无限可扩展:添加服务无需更改配置
  • 生产就绪:在真实环境中经过实战检验的配置
  • 现代协议:包含 HTTP/2、WebSocket 和 gRPC 支持

此配置经过真实部署的精炼,为从个人项目到业务关键应用的一切提供了基础。

Traefik 的自动化能力与适当的监控、安全和备份程序的组合,创建了一个强大的自托管平台,在保持对基础设施完全控制的同时可与昂贵的托管服务相媲美。

关于 tva

tva 提供数据库系统、云环境和全球供应链的综合基础设施管理。我们系统化的方法将严格的安全协议与性能优化相结合,同时战略咨询服务实现数字能力和实物资产的精准协调——在所有业务中保持最高标准的卓越运营和合规水平。

访问 tva.sg 了解更多关于我们基础设施管理服务和更多自托管教程的信息。