准备工作

  • 服务器:一台具有公网 ip 的服务器,离客户端地区最近优先

  • 域名:一个解析到服务器的域名,例如 dp.example.com

  • 防火墙配置:确保所需要的端口防火墙已放开,如3477/tcp3478/udp

Docker 部署

安装 Docker

curl -fsSL https://get.docker.com | bash -s docker

创建 Docker Compose 配置

创建工作目录并编写 docker-compose.yml

mkdir -p /opt/derper
cd /opt/derper

创建 docker-compose.yml 文件:

services:
  derper:
    image: fredliang/derper:latest
    container_name: derper
    restart: always
    ports:
      - "3477:3477"
      - "3478:3478/udp"
    environment:
      - DERP_DOMAIN=dp.example.com # 替换为你的域名
      - DERP_CERT_MODE=manual  # 使用手动证书
      - DERP_ADDR=:3477 # DERP 服务端口
      - DERP_STUN_PORT=3478  # STUN 端口
      - DERP_VERIFY_CLIENTS=true # 启用客户端验证
    volumes:
      # 启用客户端验证需映射
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
      # 挂载证书目录到容器内部(手动存放证书)
      - ./certs:/app/certs

      # -------------------------------------------------------
      # 自动挂载 NPM 的证书文件,根据需要选择
      # 注意:这里使用 NPM 申请的泛域名证书,当 NPM 自动续签证书后只需要重启 derper 容器即可
      # 注意:请将映射路径替换为 NPM 下泛域名证书的真实路径
      # -------------------------------------------------------
      # 映射公钥 (fullchain.pem -> dp.example.com.crt)
      - /opt/nginx-proxy-manager/letsencrypt/live/npm-1/fullchain.pem:/app/certs/dp.example.com.crt:ro
      # 映射私钥 (privkey.pem -> dp.example.com.key)
      - /opt/nginx-proxy-manager/letsencrypt/live/npm-1/privkey.pem:/app/certs/dp.example.com.key:ro

证书管理

自动申请证书

使用标准的 80/443 端口,Derper 可以自动申请和续期 Let's Encrypt 证书

docker-compose.yml 文件:

environment:
  - DERP_CERT_MODE=letsencrypt
  - DERP_ADDR=:443
  - DERP_HTTP_PORT=80

手动管理证书

使用自定义端口或已有证书,需要手动管理证书,证书放置在 ./certs 目录下,并且证书文件命名符合规则,例如:

derper.example.com.crtderper.example.com.key

客户端验证

启用客户端验证功能可以防止自建的 Derper 服务器被白嫖,只有在同一个 Tailscale 网络中的设备才能使用。

安装 Tailscale 客户端

在 Derper 服务器上安装 Tailscale 客户端:

# 安装 Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# 启动并加入网络
sudo tailscale up

启用验证

docker-compose.yml 文件:

environment:
  - DERP_VERIFY_CLIENTS=true
volumes:
  - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock

Tailscale 配置

登录 Tailscale Admin Console

进入 Access Controls 中选择 JSON 格式添加自定义 DERP 配置:

{
  // ... 其他配置 ...

  "derpMap": {
    "OmitDefaultRegions": false, // 是否忽略官方节点,建议 false,仅作补充
    "Regions": {
      "900": { // RegionID,建议选 900-999 之间的数字
        "RegionID": 900,
        "RegionCode": "myderp",
        "RegionName": "Custom Derper",
        "Nodes": [
          {
            "Name": "900a",
            "RegionID": 900,
            "HostName": "derper.example.com", // 你的域名
            "DERPPort": 3477,  // 如使用自定义端口,修改此处
            "STUNPort": 3478,  // 如使用自定义端口,修改此处
            "STUNOnly": false
          }
        ]
      }
    }
  }
}

最终测试

在任意一台连接了 Tailscale 的客户端上(例如你的 PC),运行命令:

tailscale netcheck

查看输出结果,类似如下输出说明配置成功:

Report:
	* Time: 2026-04-08T14:46:58.941345Z
	* UDP: true
	* IPv4: yes, 120.235.250.104:52940
	* IPv6: no, but OS has support
	* MappingVariesByDestIP: 
	* PortMapping: UPnP, NAT-PMP
	* CaptivePortal: false
	* Nearest DERP: Custom Derper
	* DERP latency:
		- myderp: 20.2ms  (Custom Derper)

可选配置

我的服务器项目一般都是通过 NginxProxyManager 进行反代,并且配置了泛域名证书,这里为了方便,直接挂载 NPM 的泛域名证书,按需选择

services:
  derper:
    image: fredliang/derper:latest
    container_name: derper
    restart: always
    ports:
      - "3477:3477"
      - "3478:3478/udp"
    environment:
      - DERP_DOMAIN=dp.example.com # 替换为你的域名
      - DERP_CERT_MODE=manual  # 使用手动证书
      - DERP_ADDR=:3477 # DERP 服务端口
      - DERP_STUN_PORT=3478  # STUN 端口
      - DERP_VERIFY_CLIENTS=true # 启用客户端验证
    volumes:
      # 启用客户端验证需映射
      - /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
      # 映射公钥 (fullchain.pem -> dp.example.com.crt)
      - /opt/nginx-proxy-manager/letsencrypt/live/npm-1/fullchain.pem:/app/certs/dp.example.com.crt:ro
      # 映射私钥 (privkey.pem -> dp.example.com.key)
      - /opt/nginx-proxy-manager/letsencrypt/live/npm-1/privkey.pem:/app/certs/dp.example.com.key:ro

注意:当 NPM 自动续签证书后需要重启 Derper 容器后才能完成更新