
使用docker-compose一键部署headscale、derper和webui
之前在 sealos 上部署过 headscale、derper 和 webui,但是由于 sealos 的一些问题,导致 headscale 无法正常使用。最近申请的域名备案也成功通过了,所以这次我尝试使用 docker-compose 在阿里云上部署 headscale、derper 和 webui。
前提条件
- 一台具有公网 IP 的服务器
- 一个域名 (需要两个二级域名,一个用于 headscale 和 webui,一个用于 derper)
- 域名证书 (可以使用acme.sh申请免费证书)
- 占用以下端口
tcp 58080
(headscale server)tcp 57070
(headscale webui)tcp 56060
(headscale derp)udp 3478
(headscale derp stun)
部署 headscale、derper 和 webui
首先,需要在服务器上安装 docker 和 docker-compose。参考
然后,我们需要在服务器上创建一个目录,用于存放相关文件,结构如下。
➜ headscale tree
.
├── docker-compose.yaml
├── dockerfiles
│ └── derp.Dockerfile
├── headscale
│ └── config
│ ├── config.yaml
│ └── derp.yaml
└── nginx
├── derp.conf
└── headscale.conf
docker-compose.yaml
compose 文件仅部署了 headscale、headscale-admin、derp、client,请按需进行修改。
# docker-compose.yaml
version: "3.9"
networks:
private:
driver: bridge
ipam:
config:
- subnet: 172.20.200.0/24
services:
server:
image: headscale/headscale:latest-debug
container_name: headscale-server
networks:
- private
volumes:
- ./headscale/config:/etc/headscale
- ./headscale/data:/var/lib/headscale
- ./headscale/run:/var/run/headscale
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
ports:
- "58080:8080"
command: serve
restart: unless-stopped
depends_on:
- derp
webui:
image: goodieshq/headscale-admin:latest
container_name: headscale-ui
networks:
- private
environment:
PORT: 7070
ports:
- "57070:7070"
volumes:
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
restart: unless-stopped
derp:
build:
context: ./dockerfiles
dockerfile: derp.Dockerfile
container_name: headscale-derp
networks:
- private
environment:
DERP_DOMAIN: hsderp.example.com
DERP_ADDR: :6060
DERP_CERT_MODE: letsencrypt
DERP_VERIFY_CLIENTS: true
ports:
- "56060:6060" # derp port, TCP
- "3478:3478/udp" # STUN port, UDP
volumes:
- ./tailscale:/var/run/tailscale
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
restart: unless-stopped
client:
image: tailscale/tailscale:stable
container_name: tailscale-client
network_mode: "host"
privileged: true
environment:
TS_EXTRA_ARGS: --netfilter-mode = off
volumes:
- ./tailscale:/var/run/tailscale
- /usr/share/zoneinfo/Asia/Shanghai:/etc/localtime:ro
- /var/lib:/var/lib
- /dev/net/tun:/dev/net/tun
cap_add:
- net_admin
- sys_module
command: tailscaled
restart: unless-stopped
derp.Dockerfile
因 derp 镜像更新不及时,所以需要手动构建,需将 derp.Dockerfile 放入 dockerfiles 文件夹内。
FROM golang:alpine AS builder
WORKDIR /app
# https://tailscale.com/kb/1118/custom-derp-servers/
RUN go env -w GOPROXY=https://goproxy.io,direct
RUN go install tailscale.com/cmd/derper@latest
FROM alpine:3.21
WORKDIR /app
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
RUN apk add --no-cache ca-certificates iptables iproute2 ip6tables curl && \
mkdir /app/certs
RUN apk add gcompat
ENV DERP_DOMAIN=your-hostname.com
ENV DERP_CERT_MODE=letsencrypt
ENV DERP_CERT_DIR=/app/certs
ENV DERP_ADDR=:443
ENV DERP_STUN=true
ENV DERP_STUN_PORT=3478
ENV DERP_HTTP_PORT=80
ENV DERP_VERIFY_CLIENTS=false
ENV DERP_VERIFY_CLIENT_URL=""
COPY --from=builder /go/bin/* /usr/local/bin/
CMD /usr/local/bin/derper --hostname=$DERP_DOMAIN \
--certmode=$DERP_CERT_MODE \
--certdir=$DERP_CERT_DIR \
--a=$DERP_ADDR \
--stun=$DERP_STUN \
--stun-port=$DERP_STUN_PORT \
--http-port=$DERP_HTTP_PORT \
--verify-clients=$DERP_VERIFY_CLIENTS \
--verify-client-url=$DERP_VERIFY_CLIENT_URL
使用 docker-compose 部署
在 headscale 目录下执行以下命令,即可部署 headscale、derp 和 webui。
sudo docker-compose up -d
配置文件
...
server_url: https://hs.example.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090
grpc_listen_addr: 0.0.0.0:50443
...
derp:
...
urls: []
paths:
- /etc/headscale/derp.yaml
这里只展示 headscale/config/config.yaml 的部分配置,其他配置请参考config-example.yaml。
regions:
999:
regionid: 999
regioncode: cnbj
regionname: Aliyun Beijing
nodes:
- name: derp
regionid: 999
hostname: hsderp.example.com
stunport: 3478
stunonly: false
derpport: 443
nginx 配置
在 nginx.conf 的 http 块中 include 以下配置文件以实现反向代理。
server {
listen 443 ssl;
server_name hs.example.com;;
location ^~ / {
proxy_pass http://127.0.0.1:58080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
add_header X-Cache $upstream_cache_status;
add_header Strict-Transport-Security "max-age=31536000";
add_header Cache-Control no-cache;
}
location ^~ /admin {
proxy_pass http://127.0.0.1:57070;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
add_header X-Cache $upstream_cache_status;
add_header Strict-Transport-Security "max-age=31536000";
add_header Cache-Control no-cache;
}
}
server {
listen 80;
server_name hs.example.com;;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name hsderp.example.com;;
location ^~ / {
proxy_pass http://127.0.0.1:56060;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
add_header X-Cache $upstream_cache_status;
add_header Strict-Transport-Security "max-age=31536000";
}
}
server {
listen 80;
server_name hsderp.example.com;;
return 301 https://$host$request_uri;
}
测试
在浏览器中打开https://hs.example.com/admin 及 https://haderp.example.com 若均可看到相关页面,说明部署成功。
因为开启了 DERP_VERIFY_CLIENTS,所以在所有服务部署成功后,需要手动把 tailscale-client 添加到 headscale 中,derper 才能正常使用。 使用以下命令进入 tailscale-client 容器,在 headscale admin 页面点击 deploy 然后复制对应的命令以连接 headscale。
sudo docker exec -it tailscale-client /bin/sh
这是我部署使用后的 headscale admin 页面,所以已经有设备和用户,刚部署好的所有数字应该都是 0。