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
5. EMQX 默认 cookie 警告
警告:
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 的历史同步、远程拉取、实时推送都可以正常使用。