Sign inSign up

mooloco/clipboard-hub

By mooloco

•Updated 19 days ago

Share text, screenshots and files across devices on your LAN. No auth, amd64 + arm64.

Image
0

83

mooloco/clipboard-hub repository overview

⁠📋 LAN Clipboard Hub(局域网剪贴板)

局域网内跨设备共享的消息板 —— Windows、Android、iPhone、平板打开同一个网页,共享一份消息列表。发文字、Ctrl+V 贴截图、拖文件、一键复制、大图预览、下载、删除。替代「为了传一段文字或一张图必须开微信」的流程。

⚠️ 这是纯内网工具。 没有任何登录、令牌或会话认证,能访问到端口的人都能读写全部内容。只绑定内网地址使用,切勿做端口映射 / DMZ / UPnP 暴露到公网。

⁠特性

  • 文字消息发布,一键复制(内网 HTTP 下也有回退路径,见下)
  • Ctrl/⌘+V 直接粘贴截图上传,或选择文件 / 拖放上传
  • 图片内联预览 + 大图查看,附件下载
  • 单条删除、整板清空(附件随之清理,不留孤儿文件)
  • SSE 实时同步:任一设备发的内容,其他设备立刻出现,断线自动重连补拉
  • 游标分页、每 IP 写限流、运行时 gzip
  • 单容器、非 root(UID 10001)、read_only + cap_drop ALL 加固
  • 数据全在挂载目录,直接复制即完成备份

⁠一条命令跑起来(单容器)

# 数据目录属主必须是 10001(容器内运行用户)
mkdir -p data && sudo chown -R 10001:10001 data

docker run -d \
  --name clipboard-hub \
  --restart unless-stopped \
  -p 192.168.1.50:5012:8080 \
  -v "$PWD/data:/data" \
  -e TZ=Asia/Shanghai \
  --read-only --tmpfs /tmp:size=16m,mode=1777 \
  --cap-drop ALL --security-opt no-new-privileges:true \
  mooloco/clipboard-hub:latest

-p 左侧写这台机器在局域网里的地址(示例为 192.168.1.50:5012)。 写 -p 5012:8080 等于绑 0.0.0.0,会暴露到所有网卡(含 VPN 网段),不符合本项目的安全边界。

然后浏览器打开 http://<你的内网地址>:5012。

⁠docker compose

存成 docker-compose.yml,与 data/ 同级:

services:
  clipboard-hub:
    image: mooloco/clipboard-hub:latest
    container_name: clipboard-hub
    restart: unless-stopped
    ports:
      # 左侧改成这台机器在局域网里的地址,不要用 0.0.0.0
      - "192.168.1.50:5012:8080"
    environment:
      TZ: Asia/Shanghai
      MAX_UPLOAD_SIZE: "20971520"   # 单文件 20 MiB
      MAX_MESSAGE_LENGTH: "100000"  # 单条文字上限
      WRITE_RATE_PER_MIN: "120"     # 每 IP 每分钟写操作
    volumes:
      - ./data:/data
    read_only: true
    tmpfs:
      - /tmp:size=16m,mode=1777
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    stop_grace_period: 10s
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/api/v1/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 5s
mkdir -p data && sudo chown -R 10001:10001 data
docker compose up -d

首次启动若报 创建目录 /data/uploads 失败: permission denied,说明 data 属主不对,执行一次 sudo chown -R 10001:10001 data 即可。docker compose down 不会删除 ./data。

⁠镜像与平台

标签latest、v1.0
平台linux/amd64、linux/arm64(docker 按机器架构自动选择)
基础镜像alpine:3.22,镜像约 32 MB
docker manifest inspect mooloco/clipboard-hub:latest           # 查看包含的平台
docker pull --platform linux/arm64 mooloco/clipboard-hub:latest # 手动指定架构

⁠⚠️ 内网 HTTP 下的「复制」按钮

浏览器的 navigator.clipboard 只在安全上下文存在(https:// 或 localhost)。http://192.168.x.x 不是安全上下文,直接调用会静默失效。

本项目不引入 TLS,而是分层回退:

方向HTTP 非安全上下文下
粘贴(读剪贴板)paste 事件正常可用 —— Ctrl/⌘+V 贴图无需任何补丁
复制文字(写)回退 textarea + document.execCommand('copy')
复制图片(写)回退把 <img> 选中后 execCommand;再失败则退化为复制图片链接

页面顶部会显示当前实际走的是哪条路径,避免「点了没反应」的困惑。

已知取舍:execCommand 已被标记废弃。在非安全上下文里,除它之外没有任何能写系统剪贴板的 Web 手段(ClipboardItem 同样要求安全上下文)。

⁠配置(环境变量)

变量默认值说明
LISTEN_ADDR0.0.0.0:8080容器内监听地址
DATA_DIR/data数据根目录(SQLite + 附件)
MAX_UPLOAD_SIZE20971520单文件字节上限(20 MiB)
MAX_MESSAGE_LENGTH100000单条文字字符上限
WRITE_RATE_PER_MIN120每 IP 每分钟写操作上限
TZAsia/Shanghai仅影响日志时间戳

⁠数据与备份

数据全部在挂载的 ./data 下(SQLite 元数据 + 附件文件),直接复制即完成备份:

docker compose stop
tar czf clipboard-hub-$(date +%F).tar.gz data/
docker compose start

SQLite 使用 WAL 模式,data/ 下可能同时有 clipboard.db、clipboard.db-wal、clipboard.db-shm,打包整个目录即可,不要只复制 .db 一个文件。

⁠技术栈

层选型
后端Go 标准库 net/http(1.22+ ServeMux,无第三方路由)
存储SQLite(modernc.org/sqlite,纯 Go、免 CGO)
附件文件系统(只存服务端随机名,原始文件名仅作展示)
实时SSE(只推轻量事件,不推二进制)
前端原生 HTML/CSS/JS,零构建、零依赖,go:embed 打进二进制

⁠安全边界(重要)

本项目有意不做身份认证,安全完全交给网络边界:

  • 只绑定 LAN 地址,不做端口映射 / DMZ / UPnP,不放进公网可达的反向代理
  • 上传的图片按原始字节返回并带 X-Content-Type-Options: nosniff
  • 非图片附件一律 Content-Disposition: attachment 并附 Content-Security-Policy: default-src 'none'; sandbox
  • 服务端不信任客户端声明的 MIME 作为路径依据、不按用户文件名拼路径、不暴露上传目录

未实现(明确不做):登录/令牌/会话认证、TLS、PWA/离线、消息 TTL 自动过期、系统剪贴板读取、Windows 托盘常驻、Android 原生 App、多用户/多看板隔离。

Tag summary

Content type

Image

Digest

sha256:cc4bfc505…

Size

8.5 MB

Last updated

19 days ago

docker pull mooloco/clipboard-hub