TieZ 剪贴板同步自建教程:OpenList WebDAV + EMQX MQTT

TieZ 剪贴板同步自建教程:OpenList WebDAV + EMQX MQTT

_

TieZ 是一款基于 Tauri 的跨平台剪贴板管理器,下载和项目地址如下:

官方网站:https://tiez.name666.top
项目地址:https://github.com/jimuzhe/tiez-clipboard
移动端项目地址:https://github.com/jimuzhe/tiez-mobile

你可以直接复制到博客,再按自己情况替换。


一、方案说明

TieZ 剪贴板同步主要涉及两个服务:

WebDAV:用于剪贴板历史记录同步、跨设备拉取记录
MQTT:用于实时推送,尤其适合手机推送到电脑

简单理解:

只要历史同步 / 拉取记录:WebDAV 必须
只要实时推送更快:MQTT 推荐
完整体验:WebDAV + MQTT

本教程使用:

OpenList:提供 WebDAV
EMQX:提供 MQTT / MQTT WebSocket
Docker:部署服务
反向代理:提供 HTTPS / WSS 公网入口
frp:可选,用于 NAS 没有公网 IP 的情况

最终结构:

TieZ 手机 / 电脑 / 平板
    ├── WebDAV: https://dav.example.com/dav/
    └── MQTT:   wss://mqtt.example.com/mqtt

服务器 / NAS
    ├── OpenList: 5244
    └── EMQX:     8083 / 18083

二、Docker 部署 OpenList + EMQX

1. docker-compose.yml

创建一个目录,例如:

mkdir -p ./tiez-stack
cd ./tiez-stack

创建 docker-compose.yml:

services:
  tiez-openlist:
    image: openlistteam/openlist:v4.2.1
    container_name: tiez-openlist
    restart: unless-stopped
    user: "0:0"
    environment:
      - TZ=Asia/Shanghai
      - UMASK=022
      - OPENLIST_ADMIN_PASSWORD=请改成OpenList管理员强密码
    volumes:
      - ./openlist/data:/opt/openlist/data
      - ./openlist/storage:/storage
    ports:
      - "5244:5244"

  tiez-emqx:
    image: emqx:5.8.8
    container_name: tiez-emqx
    hostname: tiez-emqx
    restart: unless-stopped
    environment:
      - EMQX_NODE__NAME=emqx@tiez-emqx
      - EMQX_NODE__COOKIE=请改成一长串随机字符
    volumes:
      - emqx-data-fixed:/opt/emqx/data
      - emqx-log-fixed:/opt/emqx/log
    ports:
      - "1883:1883"
      - "8083:8083"
      - "18083:18083"

volumes:
  emqx-data-fixed:
  emqx-log-fixed:

启动:

docker compose pull
docker compose up -d

查看容器:

docker ps

正常应该看到:

tiez-openlist   Up
tiez-emqx       Up

2. 为什么 EMQX 要固定节点名

EMQX 建议固定节点名:

hostname: tiez-emqx
environment:
  - EMQX_NODE__NAME=emqx@tiez-emqx

如果不固定,EMQX 可能会使用 Docker 内部 IP 作为节点名,例如:

emqx@172.xx.xx.xx

容器重建后 IP 变化,可能导致 EMQX 读取不到原来的数据,表现为:

Dashboard 管理员密码突然不对
MQTT 用户突然失效
认证器配置丢失

固定成:

emqx@tiez-emqx

后,只要不删除 Docker 卷,数据会更稳定。


3. 为什么 EMQX 使用 Docker 命名卷

EMQX 使用:

volumes:
  - emqx-data-fixed:/opt/emqx/data
  - emqx-log-fixed:/opt/emqx/log

这样可以避免某些 NAS 的 Docker 目录权限问题。

如果使用本地目录映射,可能会遇到:

mkdir: cannot create directory ‘/opt/emqx/data/configs’: Permission denied

用 Docker 命名卷通常更省心。


三、配置 OpenList WebDAV

浏览器打开:

http://NAS_IP:5244

例如:

http://192.168.1.100:5244

管理员账号一般是:

admin

管理员密码是 compose 里的:

OPENLIST_ADMIN_PASSWORD

如果忘记管理员密码,可以进入容器终端执行:

cd /opt/openlist
./openlist admin set '新的管理员密码'

1. 添加本地存储

进入 OpenList 后台,添加一个本地存储:

驱动:本机存储 / Local
挂载路径:/tiez
根文件夹路径:/storage/tiez

保存后,OpenList 前台应该能看到 /tiez 目录。


2. 建议每台设备一个 OpenList 用户

如果多台设备共用同一个 WebDAV 用户,部分场景下可能出现:

登录一直转圈
WebDAV 401
WebDAV 429
某台设备反复认证失败

为了稳定和方便排查,建议一台设备一个 OpenList 用户。

例如:

tiez_pc      → 电脑
tiez_phone   → 手机
tiez_pad     → 平板

每个用户都设置:

基础路径 / 根目录:/tiez
权限:
- WebDAV Read
- WebDAV Management
- 上传
- 创建目录
- 删除
- 重命名

这样虽然账号不同,但都同步到同一个目录:

/tiez/tiez-sync

四、TieZ WebDAV 填法

如果 OpenList 用户的基础路径已经设置为:

/tiez

那么 TieZ 里这样填:

WebDAV 地址:https://dav.example.com/dav/
用户名:对应设备的 OpenList 用户
密码:对应设备的 OpenList 用户密码
同步目录 / BasePath:tiez-sync

电脑示例:

WebDAV 地址:https://dav.example.com/dav/
用户名:tiez_pc
密码:tiez_pc 的密码
同步目录:tiez-sync

手机示例:

WebDAV 地址:https://dav.example.com/dav/
用户名:tiez_phone
密码:tiez_phone 的密码
同步目录:tiez-sync

注意:如果用户基础路径已经是 /tiez,就不要再写成:

https://dav.example.com/dav/tiez/
BasePath: tiez-sync

否则路径可能重复。


五、配置 EMQX MQTT

浏览器打开 EMQX 后台:

http://NAS_IP:18083

默认账号一般是:

admin / public

首次登录后,先修改 Dashboard 管理员密码。


1. 创建 MQTT 认证器

进入:

Access Control → Authentication → Create

选择:

Mechanism:Password-Based
Backend:Built-in Database
账号类型:username
密码加密方式:sha256
加盐方式:suffix

保持默认即可,然后创建。


2. 建议每台设备一个 MQTT 用户

建议和 OpenList 一样,每台设备一个 MQTT 用户:

mqtt_pc
mqtt_phone
mqtt_pad

MQTT 这里最重要的是:

Topic 必须相同
Client ID 必须不同

例如所有设备共用同一个 Topic:

tiez/clip/随机字符串

电脑:

用户名:mqtt_pc
Client ID:tiez-pc-001

手机:

用户名:mqtt_phone
Client ID:tiez-phone-001

平板:

用户名:mqtt_pad
Client ID:tiez-pad-001

如果 Client ID 重复,MQTT 会出现互相踢下线的问题。


六、TieZ MQTT 填法

局域网测试:

协议:ws://
服务器:NAS_IP
端口:8083
WS 路径:/mqtt
用户名:对应设备的 MQTT 用户
密码:对应设备的 MQTT 密码
Topic:所有设备填同一个
Client ID:每台设备不同

公网最终填写:

协议:wss://
服务器:mqtt.example.com
端口:443
WS 路径:/mqtt
用户名:对应设备的 MQTT 用户
密码:对应设备的 MQTT 密码
Topic:所有设备填同一个
Client ID:每台设备不同

手机示例:

协议:wss://
服务器:mqtt.example.com
端口:443
WS 路径:/mqtt
用户名:mqtt_phone
密码:mqtt_phone 的密码
Topic:tiez/clip/随机字符串
Client ID:tiez-phone-001

七、没有公网 IP 时:frp 转发

如果服务部署在家里 NAS,而 NAS 没有公网 IP,可以用 frp 把 NAS 服务转发到公网 VPS。

1. frpc 配置示例

如果 frpc 跑在 NAS 本机:

[[proxies]]
name = "tiez-openlist"
type = "tcp"
localIP = "127.0.0.1"
localPort = 5244
remotePort = 15244

[[proxies]]
name = "tiez-emqx-ws"
type = "tcp"
localIP = "127.0.0.1"
localPort = 8083
remotePort = 18084

如果 frpc 跑在 Docker 里,或者 127.0.0.1 指不到 NAS 主机,则使用 NAS 的局域网 IP:

[[proxies]]
name = "tiez-openlist"
type = "tcp"
localIP = "NAS_IP"
localPort = 5244
remotePort = 15244

[[proxies]]
name = "tiez-emqx-ws"
type = "tcp"
localIP = "NAS_IP"
localPort = 8083
remotePort = 18084

重启 frpc。


2. VPS 上测试 frp 是否通

在 VPS 上执行:

curl -I http://127.0.0.1:15244

如果返回:

HTTP/1.1 405 Method Not Allowed

也算通。OpenList 对 HEAD 请求可能返回 405。

测试 MQTT WebSocket:

curl -I http://127.0.0.1:18084/mqtt

如果返回:

HTTP/1.1 400 Bad Request
server: Cowboy

通常也算通。普通 curl 不是 WebSocket 握手,所以 EMQX 返回 400 很正常。

如果没通,一般会看到:

Connection refused
Connection timed out
No route to host
502 Bad Gateway

八、普通 Nginx / OpenResty 反向代理

下面以普通 Nginx / OpenResty 反向代理为例。

假设:

OpenList 通过 frp 映射到 VPS:127.0.0.1:15244
EMQX WebSocket 通过 frp 映射到 VPS:127.0.0.1:18084

如果服务和反向代理在同一台机器上,也可以直接把端口改成实际本地端口:

OpenList: 127.0.0.1:5244
EMQX WS:  127.0.0.1:8083

1. WebDAV 反代配置

域名:

dav.example.com

Nginx 配置:

server {
    listen 80;
    server_name dav.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    http2 on;
    server_name dav.example.com;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    client_max_body_size 500m;

    location ^~ / {
        proxy_pass http://127.0.0.1:15244;

        proxy_http_version 1.1;

        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 X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port 443;

        proxy_request_buffering off;
        proxy_buffering off;

        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        proxy_connect_timeout 60s;
    }
}

WebDAV 不需要 WebSocket Upgrade,所以不要加:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

2. MQTT WebSocket 反代配置

域名:

mqtt.example.com

Nginx 配置:

server {
    listen 80;
    server_name mqtt.example.com;

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name mqtt.example.com;

    ssl_certificate     /path/to/fullchain.pem;
    ssl_certificate_key /path/to/privkey.pem;

    location ^~ /mqtt {
        proxy_pass http://127.0.0.1:18084;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        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 X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Port 443;

        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        proxy_connect_timeout 60s;

        proxy_buffering off;
    }
}

MQTT WebSocket 重点是:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

3. 检查 Nginx 配置

修改后检查:

nginx -t

如果使用 Docker 版 OpenResty,可能是:

docker exec openresty nginx -t

重载或重启:

nginx -s reload

或者:

docker restart openresty

九、公网测试

1. 测试 WebDAV

curl -I https://dav.example.com/dav/

如果返回 401 Unauthorized,通常说明反代通了,只是需要认证。

进一步测试:

curl -u 用户名:'密码' -X PROPFIND https://dav.example.com/dav/

正常可能返回:

207 Multi-Status

2. 测试 MQTT

curl -I https://mqtt.example.com/mqtt

如果返回:

400 Bad Request

通常也算通,因为普通 curl 不是 WebSocket 握手。

只要不是下面这些,一般反代链路就没问题:

502 Bad Gateway
Connection refused
Connection timed out

十、常见问题

1. EMQX 镜像拉取失败

错误:

manifest for emqx/emqx:5 not found

错误写法:

image: emqx/emqx:5

正确写法:

image: emqx:5.8.8

或者:

image: emqx:latest

推荐固定版本:

image: emqx:5.8.8

2. OpenList 镜像格式错误

错误:

openlistteam/openlist::v4.2.1
invalid reference format

原因是多写了一个冒号。

错误:

image: openlistteam/openlist::v4.2.1

正确:

image: openlistteam/openlist:v4.2.1

如果 Docker 图形界面分成镜像名和版本:

镜像名:openlistteam/openlist
版本:v4.2.1

版本栏不要写成:

:v4.2.1

3. EMQX Permission denied

错误:

mkdir: cannot create directory ‘/opt/emqx/data/configs’: Permission denied

解决:使用 Docker 命名卷:

volumes:
  - emqx-data-fixed:/opt/emqx/data
  - emqx-log-fixed:/opt/emqx/log

底部添加:

volumes:
  emqx-data-fixed:
  emqx-log-fixed:

4. EMQX admin 密码过一段时间失效

原因通常是 EMQX 节点名不固定。

错误日志类似:

EMQX_NODE__NAME [node.name]: emqx@172.xx.xx.xx

正确应固定为:

EMQX_NODE__NAME [node.name]: emqx@tiez-emqx

compose 中加入:

hostname: tiez-emqx
environment:
  - EMQX_NODE__NAME=emqx@tiez-emqx

警告:

WARNING: Default insecure Erlang cookie is in use

解决:

environment:
  - EMQX_NODE__COOKIE=一长串随机字符

成功后日志会显示:

EMQX_NODE__COOKIE [node.cookie]: ******

6. OpenList WebUI 登录一直转圈

可能原因:

多设备共用一个账号
某台设备 WebDAV 密码错误反复重试
触发 401 / 429
浏览器缓存或 token 异常

建议:

1. 停掉所有 TieZ 客户端同步
2. 重启 OpenList 容器
3. 使用无痕窗口登录
4. 必要时重置 admin 密码
5. 每台设备单独创建 OpenList 用户

如果日志里看到:

401
429

说明可能有设备账号密码错误,或者触发了限流。


7. OpenList 提示 storage not found

日志类似:

failed list /: storage not found; please add a storage first

说明还没有添加存储。

进入 OpenList 后台添加:

挂载路径:/tiez
根文件夹路径:/storage/tiez

8. WebDAV 401

含义:账号密码错误。

检查:

TieZ WebDAV 用户名
TieZ WebDAV 密码
OpenList 用户是否存在

9. WebDAV 403

含义:认证成功,但权限不足。

检查 OpenList 用户权限:

WebDAV Read
WebDAV Management
上传
创建目录
删除
重命名

10. WebDAV 405

如果是创建目录时出现:

MKCOL 405

可能是目录已经存在,不一定是错误。

如果首次创建就 405,检查 WebDAV 地址和 BasePath 是否写错。


11. MQTT 连接不上

重点检查:

服务器地址是否正确
端口是否是 443
协议是否是 wss://
路径是否是 /mqtt
用户名密码是否正确
Topic 是否所有设备相同
Client ID 是否每台设备不同
反代是否支持 WebSocket Upgrade

Nginx 必须包含:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

十一、最终推荐模板

电脑 TieZ

WebDAV:

URL:https://dav.example.com/dav/
用户名:tiez_pc
密码:tiez_pc 的密码
BasePath:tiez-sync

MQTT:

协议:wss://
服务器:mqtt.example.com
端口:443
路径:/mqtt
用户名:mqtt_pc
密码:mqtt_pc 的密码
Topic:tiez/clip/随机字符串
Client ID:tiez-pc-001

手机 TieZ

WebDAV:

URL:https://dav.example.com/dav/
用户名:tiez_phone
密码:tiez_phone 的密码
BasePath:tiez-sync

MQTT:

协议:wss://
服务器:mqtt.example.com
端口:443
路径:/mqtt
用户名:mqtt_phone
密码:mqtt_phone 的密码
Topic:tiez/clip/随机字符串
Client ID:tiez-phone-001

十二、经验总结

最稳配置:

OpenList:一台设备一个账号
EMQX:一台设备一个账号
MQTT Topic:所有设备相同
MQTT Client ID:每台设备不同
WebDAV BasePath:所有设备相同
OpenList 用户基础路径:全部设置为 /tiez

不要把管理员账号直接用于 TieZ 同步。

不要把真实密码、Token、Cookie、验证码长期保存在公开同步目录中。

公网访问建议全部走 HTTPS / WSS:

WebDAV:https://dav.example.com/dav/
MQTT:wss://mqtt.example.com/mqtt

这样 TieZ 的历史同步、远程拉取、实时推送都可以正常使用。

Windows OpenSSL 安装与生成自签证书 2026-05-03

评论区

© 2026 自用杂记