心梦后花园

Back

之前总有几个场景觉得别扭:临时想在另一台机器上传段代码、传个截图给朋友,或者往服务器上塞个小文件,翻来覆去要么开网盘、要么敲 scp。后来看到 fars.ee 和 hastebin 这类在线剪切板,就想着自己是不是也能整一个。用 Go 写了个 pastego,单个二进制,丢到服务器就能跑,前后端我一个人说了算,用起来顺手最重要。

开源在 git.liyp.cc/xmengnet/pastego,我自己部署的实例在 p.liyp.cc。下面把项目思路和用法记一下。

主要特性#

  • 多类型支持:文本、代码、图片、任意文件都可以传,按扩展名识别 mimetype,图片能直接在查看页渲染
  • 自动语法高亮:前端用 highlight.js 根据内容自动检测语言
  • 私有模式:公开的用 6-8 位 short 链接,私有的只生成 24 位不可猜测的长链接
  • 定时过期:1 小时 / 1 天 / 7 天 / 30 天 / 永久,后台 goroutine 每 60 秒清扫
  • CLI 工具:独立二进制,管道友好,脚本里随手 echo xxx | clip 就能发
  • 零依赖部署:单二进制 + 一个 SQLite 文件,前端用 go:embed 直接打进二进制里
  • 安全防护:限流、CSRF、XSS 兜底、安全响应头,为公网部署而做

技术选型#

层面技术
后端Go(标准库 net/http,没引 web 框架)
数据库SQLite(mattn/go-sqlite3
前端React + TypeScript + Tailwind(Vite)
渲染goldmark 渲染 Markdown(about 页面)
CIGitea Actions,打标自动出 Linux/Windows/Arch 包

后端只用标准库,连路由都是 http.NewServeMux(),没用 gin 之类的东西。依赖就三个:SQLite 驱动、UUID 和 goldmark,对一个服务来说算够克制了。

构建与启动#

编译#

git clone https://git.liyp.cc/xmengnet/pastego.git
cd pastego

# 后端
go build -ldflags="-s -w" -o pastego .

# 前端(构建产物会被 go:embed 打进二进制)
cd frontend && npm install && npm run build
bash

也可以直接下 release 里的预编译二进制,或者 Arch 用户直接装 pastego 包。项目 CI 打 tag 时自动交叉编译 Linux amd64/arm64、Windows amd64Arch x86_64 包

启动#

# 默认端口 4832
./pastego

# 自定义端口 / 数据库路径
./pastego -addr :8080 -dsn /data/pastego.db
bash

配置也支持环境变量(CLIP_ADDRCLIP_DSN 等),用 systemd 托管的话更直观。默认所有东西都在,前端界面在 http://localhost:4832,就是个 hastebin 风格的编辑器。

使用#

Web 界面#

打开就是个大编辑框,支持 Tab 缩进,底部任务栏能选语法类型(留空自动检测)、过期时间、是否私有模式。点 paste! 拿到链接:

pastego 编辑页

查看页自动高亮,还带个二维码方便手机上扫。比如把 pastego 的 README 传上去,代码高亮和 Markdown 表格都能正常展示:

pastego 查看页 - 代码高亮

CLI#

CLI 是独立二进制 clip,先配一下服务器地址:

export CLIP_SERVER=https://p.liyp.cc
# 或者写进配置
./clip config --server https://p.liyp.cc
bash

然后基本就是拿来即用:

# 管道上传,自动检测语言
echo "SELECT * FROM users" | ./clip

# 指定语法、带过期时间
./clip -f query.sql -s sql
echo "临时消息" | ./clip -t 3600   # 1 小时后过期

# 传文件 / 私有模式
./clip -f screenshot.png
cat secret.txt | ./clip --private

# 只看 URL,方便接脚本
echo "data" | ./clip -u
bash

查看、改、删:

./clip abc123           # 看原始内容
./clip abc123 --meta    # 看 JSON 元数据
./clip abc123 --open    # 浏览器打开
echo "new" | ./clip --update <uuid>
./clip --delete <uuid>
bash

设计与安全上的一些细节#

ID 体系#

一个剪切板有三套标识,各管一摊:

类型格式用途
short6-8 位 base62公开分享链接,私有模式为空
long_id24 位 base62私有访问链接,不可猜测
uuidUUID v4更新/删除认证,仅修改操作用

uuid 只出现一次#

出于安全考虑,uuid(唯一的写凭证)只在创建响应里返回一次,之后任何读取接口都不再带出 uuid/short/long。结果就是:只有创建者手里那份凭证能改/删自己的剪切板,别人拿到分享链接也看不了删除按钮,更没法通过读取接口扒出写凭证。这个设计我觉得挺关键,值得单独提一句。

限流别乱信代理头#

限流用的令牌桶,默认每秒 10 个、突发 20 个。默认不信任 X-Forwarded-For / X-Real-Ip——因为公网直连时这些头是能被伪造的,伪造了等于绕过 IP 限流。只有部署在反向代理后面才开 CLIP_TRUSTED_PROXY=1,让限流按真实客户端 IP 算。

一个前端的坑:markdown 表格断行#

前端高亮用 Prism,highlight.js 检测语言时,markdown 表格里带 display: table 的 token 会被拆开、导致表格被断成一行一行,很难看。最后是靠 CSS 强制行内排列把表格拉回一行显示的。

静态资源缓存策略#

前端构建产物文件名带内容 hash(index-xxxx.js),这类资源是 immutable 的,可以放心长缓存;index.htmlno-store 每次重新拉取,这样能拿到最新的 hash 资源,避免浏览器把旧 JS 包当新包用。

部署到生产#

公网裸奔还是建议套个反向代理 + HTTPS。几个环境变量按需配:

export CLIP_ORIGINS="p.liyp.cc"        # 启用 CSRF,只放行指定域名
export CLIP_TRUSTED_PROXY=1             # 在 Nginx/Caddy 后,保证限流按真实 IP
export CLIP_MAX_SIZE=10485760           # 单文件上限 10MB
bash

然后 Nginx 反代 4832 端口、配好证书就行。数据库就一个 pastego.db,定时备份一下就完事。

小结#

折腾下来最大的感受是:零依赖部署 + 双端入口(Web + CLI)这套组合真的很实用。要传个东西的时候,管道一接 | clip 链路就通了,比开网盘顺手得多。代码也没用重的框架,标准库就能撑起一个够用的服务,后期维护不大。

项目我还在慢慢加东西,有需要可以直接去仓库提 issue;部署在 https://p.liyp.cc 的这个实例就是它自己。

PasteGo:用 Go 写一个自托管的轻量在线剪切板
https://www.liyp.cc/blog/pastego-lightweight-online-clipboard
Author 万古一梦
Published at 2026年8月2日
Comment seems to stuck. Try to refresh?✨