【实用的开源工具】OTS:发完就销毁的密码分享链接

阅读约 9 分钟
【实用的开源工具】OTS:发完就销毁的密码分享链接

「实用的开源工具」系列:我只收集值得用的开源项目,写清楚它能做什么、怎么部署、有哪些坑,并在文末标明出处。内容整理自官方文档,核对日期 2026-10-31,具体版本以官方为准。命令和配置都摘自官方 README、Wiki 和仓库里的 Compose 文件,本文没有做实机测试,请先在测试环境里走一遍。

项目信息卡

项目说明
名称OTS(仓库名 Luzifer/ots),One-Time-Secret 一次性密文分享平台
做什么密文在浏览器里用 256 位 AES 对称加密后再发给服务器,生成含“密文 ID + 密码”的链接;第一次读取后密文立即删除
许可证Apache-2.0
仓库github.com/Luzifer/ots
最近版本v1.23.1(2026-10-23 发布,查询于 2026-10-31)
维护状态未归档,最近一次推送 2026-10-30;SECURITY.md 写明只支持最新发布版,master 分支被标为不稳定
运行方式单个二进制或容器,默认监听 3000 端口;存储后端可选 mem(内存)或 redis
镜像ghcr.io/luzifer/ots,仓库自带的 Compose 文件用的是 ghcr.io/luzifer/ots:v1.23.1
官方公共实例ots.fyi(作者自己托管)。官方建议用公共实例时不要信任作者,要先自己加密

它能做什么

  • 浏览器端加密:密文在你的浏览器里加密后才发给服务器,密码不会发给服务器,所以服务器没有办法在合理代价内解密它保存的内容。
  • 读一次就删除:密文在第一次被读取时立即删除。
  • 过期时间:用 SECRET_EXPIRY 控制密文的存活时间(秒)。
  • 命令行工具 OTS-CLI:可以在脚本里创建和读取密文。
  • 可定制:通过 --customize 加载一个 YAML 文件,改标题、图标、过期选项等。

典型用法:要把服务器密码、API 密钥、临时账号发给同事或客户时,不直接贴在聊天记录里,而是发一个只能打开一次的链接。

注意它只是“少留痕”,不是万能的:链接发出去之后,谁先打开谁就拿到了内容,所以链接本身仍然要发给对的人。

部署

官方仓库里自带一个 docker-compose.yml,用 Valkey(Redis 兼容)存放密文。先建目录:

bash
mkdir -p /opt/ots && cd /opt/ots

docker-compose.yml(内容取自官方仓库,我只改了端口绑定):

yaml
services:
  app:
    image: ghcr.io/luzifer/ots:v1.23.1
    restart: always
    environment:
      # Optional, see "Customization" in README
      #CUSTOMIZE: '/etc/ots/customize.yaml'
      # See README for details
      REDIS_URL: redis://valkey:6379/0
      # 168h = 1w
      SECRET_EXPIRY: "604800"
      # "mem" or "redis" (See README)
      STORAGE_TYPE: redis
    depends_on:
      - valkey
    ports:
      - 127.0.0.1:3000:3000
  valkey:
    image: docker.io/valkey/valkey:9.1.3-alpine
    restart: always
    volumes:
      - ./data:/data

要点:

  1. 版本:这是官方文件里写的标签(查询时与最新发布版一致)。升级时记得先确认新标签存在。
  2. STORAGE_TYPE:官方 README 说明有两种后端,mem 是内存存储,服务重启就清空;redis 把密文存在一个 hash 里,用 REDIS_URL 连接,REDIS_KEY 控制键名前缀(默认 io.luzifer.ots)。
  3. SECRET_EXPIRY:单位是秒,默认 0,表示不过期。上面的 604800 就是一周。
  4. 端口:官方文件是 3000:3000,对所有网卡开放。这里绑定 127.0.0.1,交给反向代理。
  5. valkey 没有发布端口,只能被同一个 Compose 网络里的 app 访问,这样比较稳妥。

启动:

bash
docker compose up -d
docker compose logs -f app

不想用 Docker,官方 Wiki 的说法是下载 Releases 里的二进制,配合 systemd 单元和环境文件运行,Wiki 里有完整示例,用到的环境变量有 LISTEN、STORAGE_TYPE、REDIS_URL、SECRET_EXPIRY、CUSTOMIZE。

第一次使用

  1. 浏览器打开 http://127.0.0.1:3000/(远程服务器可以先用 SSH 端口转发)。
  2. 输入要分享的内容,创建后会得到一个链接。链接里包含密文 ID 和密码,形如 https://ots.example.com/#密文ID|密码。官方解释:# 后面的部分浏览器不会发给服务器,服务器只会看到 https://ots.example.com/,然后页面里的脚本用 ID 取回密文并在本地解密。
  3. 把完整链接发给对方。对方打开读取之后,密文就会被删除,再打开就没有了。

所以:自己别用这个链接去“测试能不能打开”,打开一次,密文就没了。测试请用一条无关紧要的内容。

用命令行创建

官方提供 OTS-CLI,可以在 Releases 页面下载,也可以用 Go 工具链从仓库的 ./cmd/ots-cli 目录构建。官方 README 里的用法:

bash
echo "my password" | ots-cli create --instance https://ots.example.com
ots-cli fetch 'https://ots.example.com/#...|...'
  • create 从标准输入或指定文件读取内容,把链接输出到标准输出;fetch 把密文打印到标准输出,附件存到指定目录。
  • 日志走标准错误输出,可用 --log-level=fatal 关闭。
  • 常用的实例地址可以放到环境变量 OTS_INSTANCE,就不用每次写 --instance。
  • 如果你的实例给 /api/create 加了认证,官方的做法是像 curl 一样传:-u myuser:mypass 做 Basic 认证,或 -H 'Authorization: Token abcde'。
  • 其他参数看 ots-cli create --help 和 ots-cli fetch --help。

用 curl 自己加密(官方强烈推荐用于公共实例)

官方 README 还介绍了一种做法:先在本地加密,再把密文交给接口。这样即使对方的服务器是别人搭的,也读不到内容。官方示例:

bash
echo "my password" | openssl aes-256-cbc -base64 -pass pass:mypass -pbkdf2 -iter 300000 -md sha512
curl -X POST -H 'content-type: application/json' -i -s \
  -d '{"secret": "上一步输出的密文"}' https://ots.example.com/api/create

接口返回的 JSON 里有 secret_id,最终要发给对方的链接是 https://ots.example.com/#<secret_id>|mypass。注意 -pass pass:mypass 会把密码留在 shell 历史里,这是通用的注意点,不是官方提示。

反向代理(Nginx)

官方 Wiki 的 HTTPS 部分给的是下面这份配置(Wiki 里 listen 80,让你再用 Let's Encrypt 加证书)。下面是在其基础上补了 443 的写法,代理部分保持原样:

nginx
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name ots.example.com;

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

    location / {
        add_header X-Robots-Tag noindex;

        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 $scheme;

        proxy_pass http://127.0.0.1:3000/;
    }
}

如果开放了附件功能,上传大小要在这里限制。官方 Wiki 写明:附件大小的上限(maxAttachmentSizeTotal)只在前端检查,想真正限制别人能发来的数据量,要在代理里设置请求体大小上限,也就是 Nginx 的 client_max_body_size(具体数值自己定)。

定制与限制

通过 --customize=路径 或环境变量 CUSTOMIZE 加载一个 YAML。下面这些键来自官方 Wiki 的 Customization 页:

yaml
appTitle: ''                 # 页面标题,留空用默认的 "OTS - One Time Secrets"
disableExpiryOverride: false # 关掉用户自选过期时间的下拉框和对应的接口能力
expiryChoices: [300, ...]    # 下拉框里的过期时间选项,单位秒
disableFileAttachment: false # 关闭附件功能(仅前端层面)
maxAttachmentSizeTotal: 0    # 附件总大小(字节);0 表示内部上限 64 MiB,仅前端检查
maxSecretSize: 121168782     # 服务器端拒绝超过此大小的密文(这是 Wiki 里写的内部默认值)
metricsAllowedSubnets: []    # 允许访问 /metrics 的网段,默认全部拒绝
overlayFSPath: /path/to/ots-customization  # 覆盖前端资源的目录

完整键列表请看 Wiki 原文。

更新与卸载

更新:改 docker-compose.yml 里 app 的版本标签(先去 Releases 和镜像库确认新标签存在),然后:

bash
cd /opt/ots
cp -a data data.bak-$(date +%F)    # 通用做法:升级前先备份
docker compose pull
docker compose up -d

官方 SECURITY.md 的说法是旧版本不再维护,建议尽快升级到最新发布版,还可以用 GitHub 的 Watch 功能关注新发布。

卸载:

bash
cd /opt/ots
docker compose down

这只会删除容器。./data 里是 Valkey 的数据(尚未被读取的密文),确认不需要后再手动删除:

bash
rm -rf /opt/ots/data    # 不可恢复,确认后再执行

踩坑清单

  1. 链接必须完整。 密码是链接里 | 后面的那段,不会发给服务器,也就没法找回。丢了、被聊天软件截断了,这条密文就读不出来了。
  2. 打开即销毁。 第一次读取后密文立即删除,包括你自己点开测试那一次。
  3. 默认存储是内存。 官方 README 说 mem 在服务重启后清空。要保留重启前的密文,用 redis(上面的 Compose 就是这种)。
  4. 默认不过期。 SECRET_EXPIRY 默认 0,表示不过期。没被读取的密文会一直躺在存储里,建议设一个期限。用户可选的过期时间由 expiryChoices 控制,想统一规定就开 disableExpiryOverride。
  5. 创建接口默认谁都能用。 谁能访问你的实例,谁就能创建密文、占用你的存储。官方 Wiki 给的做法:在代理上给 /api/create 和 /api/isWritable 加访问控制(比如只让登录了公司 SSO 的人访问);没有权限访问 /api/isWritable 的人,创建界面也会被关掉。
  6. 文件类型限制不是安全措施。 acceptedFileTypes、disableFileAttachment、maxAttachmentSizeTotal 都只作用于前端。服务器看不到内容,无法判断是大密文还是小密文加附件。要限制数据量,请在代理里限制请求体大小。
  7. 改了 overlayFSPath 里的文件要重启。 官方说明:否则文件的完整性哈希对不上,浏览器会拦截这些资源。
  8. /metrics 在代理后面要小心。 它按客户端地址判断是否放行,而经过反向代理时看到的是代理的地址,所以官方提醒:除非代理那一层也限制了 /metrics,否则不要把代理的网段加进 metricsAllowedSubnets。
  9. 只用最新发布版。 SECURITY.md 写明 master 不稳定、旧版本不再维护,所以固定到最新发布版本,而不是 master 或随手拉旧镜像。
  10. 务必走 HTTPS。 官方 Wiki 明确建议在前面加 Nginx 和 Let's Encrypt 这样的传输层加密。另外这类工具的安全性建立在“网页脚本没被篡改”之上,通用做法是别把它随便放在不受信任的环境里。
  11. Docker 发布的端口会绕过 ufw 之类的防火墙。 所以示例绑定到 127.0.0.1。这是 Docker 的通用行为,不是 OTS 特有的。
  12. 公共实例要先自己加密。 官方对 ots.fyi 的态度是:别把明文交给作者的服务器,而是用上面的 openssl + curl 方式先加密再提交。你自己搭的实例同理,对方并不知道你的服务器是否可信,涉及特别敏感的内容时可以参照这种做法。

出处

想要类似的东西?网站、Telegram 机器人、运维工具,说说你的需求。
发布需求

有想法或问题?去留言板留言 →