Kutt:自建短链接服务
Kutt 是一款现代化的开源短链接服务,基于 Node.js + PostgreSQL + Redis 构建。除了基础的长链转短链,它还支持自定义短码、自有域名、点击统计、密码保护、过期时间、二维码以及完整的 REST API,可作为 bit.ly、t.cn 的自托管替代品。
一、决策建议:你真的需要自建短链吗?
短链服务听上去万能,但对个人用户而言,只有几个场景能体现真正价值。如果都用不上,直接用 bit.ly 或干脆贴原链反而更省心。
值得自建的核心场景:
- 品牌短链与防链接腐烂:用
s.yoursite.com/xxx替代bit.ly/xxx,社媒可信度与点击率更高。更重要的是当目标 URL 失效或迁移时,可在后台直接改向(destination),不必回去改所有已发布的帖子、邮件或印刷物。 - 二维码与线下物料:名片、易拉宝、播客封面、产品包装上的二维码,短链让码图更稀疏、扫码成功率更高。印刷品最大痛点是发出去就改不了,而短链让你随时切换跳转目标——做活动复用同一张海报变得可行。
- 多渠道分发的轻量分析:同一篇博文分别发到推特、朋友圈、Show Notes 时,各生成一个独立短链,回头对比哪个渠道点击多。比给每个 URL 拼 UTM 参数 + 接 GA 更轻量,适合个人博主和小型自媒体。
- 自动化工作流:通过 REST API 在 n8n、Huginn、Zapier 等流程里给 RSS 新文章、推送通知自动生成短链。
- 临时与受控分享:分享敏感内容时设置过期时间或密码,比搭一套完整鉴权轻量。如限时活动报名、内部测试链接、付费内容预览等。
不建议自建的情况:
- 个人用量极低(每月生成不到几条),维护 PostgreSQL + Redis 的成本远高于直接复制粘贴 bit.ly 短链。
- 仅想"让链接变短"。现代社媒(推特、微博)大多自动短链化或不计长度,单纯缩短意义不大。
- 把短链当作反爬或链接混淆手段。绝大多数爬虫会跟随 301/302,且自建短链域名一旦曝光更容易被针对。
更轻量的替代:Cloudflare Workers + KV
如果你的需求仅仅是「自有域名的短链 + 基础点击统计」,不涉及多用户、复杂权限和完整 API,直接用 Cloudflare Workers + KV 比自建 Kutt 更划算,对个人用户应作为首选:
- 零服务器成本:Workers 免费额度每天 10 万次请求、KV 每天 10 万次读取,对个人短链完全够用。
- 零运维:没有 PostgreSQL、Redis 要维护,不用担心 NAS 断电、数据库备份、镜像升级和安全漏洞。
- 天然 HTTPS + CDN 加速:跳转走 Cloudflare 全球边缘节点,比 NAS 直出快得多,且自带 DDoS 防护。
- 数据 + 域名一起管:DNS、SSL、Workers、KV 都在同一控制台。
推荐项目:
- Sink ——Cloudflare Workers + KV 短链服务,自带管理后台、点击分析、AI 短码生成、过期时间。
- 想完全自定义可参考官方 URL Shortener Worker 教程,几十行 JS 就能搭一个最小可用版本。
什么时候才回头选 Kutt:
- 需要多用户管理与权限隔离(团队场景,给每位成员独立配额)。
- 需要密码保护链接、自定义短码规则、统一的 REST API 与 Token 体系。
- 数据完全不愿过任何第三方(连 Cloudflare 都不信任)。
- 已有 NAS + PostgreSQL/Redis 在跑别的服务,多挂一个 Kutt 边际成本几乎为零。
二、部署代码
推荐通过 Docker Compose 部署 Kutt,详情请见 Docker Compose 部署教程。Kutt 依赖 PostgreSQL 和 Redis,以下是完整的配置示例:
version: "3"
services:
kutt:
image: kutt/kutt:latest
container_name: kutt
depends_on:
- postgres
- redis
ports:
- 5780:3000
env_file:
- .env
restart: unless-stopped
postgres:
image: postgres:14-alpine
container_name: kutt_postgres
environment:
POSTGRES_USER: kutt
POSTGRES_PASSWORD: change_me_to_strong_password
POSTGRES_DB: kutt
volumes:
- /volume1/docker/kutt/postgres:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
container_name: kutt_redis
volumes:
- /volume1/docker/kutt/redis:/data
restart: unless-stopped在同目录下创建 .env 文件,至少需要配置以下变量:
# 站点基础信息
SITE_NAME=Kutt
DEFAULT_DOMAIN=s.yoursite.com
JWT_SECRET=替换为足够长的随机字符串
# 数据库连接
DB_HOST=postgres
DB_PORT=5432
DB_NAME=kutt
DB_USER=kutt
DB_PASSWORD=change_me_to_strong_password
# Redis 连接
REDIS_HOST=redis
REDIS_PORT=6379
# 管理员账户(注册后将其设为管理员)
ADMIN_EMAILS=you@example.com
# 邮件服务(找回密码、邮箱验证必填)
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_SECURE=false
MAIL_USER=you@example.com
MAIL_FROM=you@example.com
MAIL_PASSWORD=your_smtp_password完整的环境变量清单见 官方 .env.example。
部署完成后通过浏览器访问 http://<你的服务器IP或域名>:5780,注册账号后即可使用。如配置了 ADMIN_EMAILS,对应邮箱注册的账号会自动获得管理员权限,可在后台管理所有短链、用户与自定义域名。
三、配置注意
反向代理与 HTTPS
短链服务的核心价值在于品牌域名,因此必须配合反向代理 + HTTPS 部署。在 Nginx Proxy Manager / Caddy 里把 s.yoursite.com 反代到 5780 端口即可。注意把 DEFAULT_DOMAIN 设置为反代后的最终域名(不含 https://),否则生成的短链会带上内网 IP 和端口。
自有域名 vs 多域名
Kutt 支持每个用户绑定独立的自有域名(Custom Domain)。如果只是个人使用,直接把 DEFAULT_DOMAIN 设为最常用的域名即可。若有多个项目想用不同域名(如 g.example.com 给 GitHub 项目、b.example.com 给博客),可在用户后台分别添加,并将这些域名的 DNS A 记录都指向同一台服务器。
API 使用
在用户后台 Settings 页面生成 API Key 后,可通过简单的 POST 请求创建短链:
curl -X POST https://s.yoursite.com/api/v2/links \
-H "X-API-Key: 你的API密钥" \
-H "Content-Type: application/json" \
-d '{"target": "https://newzone.top/posts/long-article", "customurl": "blog"}'返回的 link 字段即为生成的短链。结合 n8n 等自动化工具,可实现"博客发布 → 自动生成短链 → 推送到社交渠道"的完整流水线。