这是「Docker 好项目」系列的第 15 期。第 12 期装了 Miniflux,解决的是"新内容主动送上门"——RSS 订阅的是持续更新的站点。但还有另一类东西:一篇值得回访的教程、一个想用的开源项目、某天刷到的报价页面。它们不值得订阅,但丢进浏览器的收藏夹,换台电脑就没了,搜也只能搜标题。这一期补的就是这一环。

linkding 效果图

痛点开场

先盘点一下浏览器收藏夹的死法:

  • 锁死在一台设备上。Chrome 同步要登录谷歌账号,国内网络环境下这件事本身就是个坑;换浏览器(Chrome → Edge → Firefox)时收藏夹导出导入一轮,层级结构和顺序必乱
  • 只能搜标题。你记得那篇文章讲的是"家用 NAS 硬盘选型",但收藏时的标题是《2026 年了还有人买机械盘?》——文件夹翻三遍找不到
  • 链接会死。收藏的页面哪天 404 了、改版了、被删除了,你连它原来长什么样都回忆不起来
  • 没法分享。想把收藏的一批链接发给同事/客户,只能一个个复制

网盘收藏、微信收藏、稍后读服务(Pocket 已经关了)各有各的坑,共同点是:数据不在你手里,服务说停就停。

linkding 的定位非常克制:一个自托管的书签管理器,极简、快、五分钟部署完。名字来自 link(链接)+ Ding(德语"东西")——"链接小玩意"。11k+ stars,MIT 协议,一个 Django 应用加一个 SQLite 文件就能跑,是同类里部署负担最小的一个。

能力边界

能干什么

  • 书签管理:标签、批量编辑、Markdown 备注、"稍后读"(unread 状态)、归档
  • 自动补全元数据:存链接时自动抓标题、描述、favicon、预览图
  • 全文搜索:标题、描述、备注、URL 都能搜,支持布尔语法(#标签 and 关键词 not #已读),大小写不敏感(SQLite 加载了 ICU 扩展来做这件事,中文搜索没问题)
  • 网页快照(plus 镜像):服务端用 headless Chromium 把页面存成单个 HTML 文件,链接死了也能看原文
  • Internet Archive 快照(可选后台任务):自动把书签提交到 Wayback Machine 留档
  • 浏览器扩展:Firefox / Chrome 官方扩展 + bookmarklet,存书签不用离开当前页面
  • REST API:完整 API,设置页一键生成 Token;社区有 iOS/macOS 客户端
  • RSS 输出:/feeds/<key>/unread 之类的地址可以把"未读书签"变成 RSS 源——接上第 12 期的 Miniflux,收藏夹也能当订阅源用
  • 自动打标签:按 URL 规则自动加标签(比如 youtube.com video)
  • 导入导出:Netscape HTML 格式,所有浏览器都认,随时进得来出得去
  • 多用户:支持 OIDC 单点登录和反代认证(Authelia 等),也能把书签公开分享

不干什么

  • 不做全文网页检索。它搜的是你写的标题/备注/URL,不是网页正文(plus 的快照也只是存档,正文搜索不在功能范围)
  • 不是稍后读工具的完全替代。它没有阅读进度、高亮标注这些功能——存、搜、读,到此为止
  • 不做同步盘。它管的是"链接",不是文件本身(PDF 快照除外)
  • 没有内置告警。它不是监控工具,挂了它自己不会喊——这个老规矩还是交给第 1 期 Uptime Kuma

一句话:linkding 是你的第二个大脑入口,不是你的知识库本身。想存正文并检索正文的,出门左转第 14 期 Paperless-ngx。

部署前准备

  1. 一台能跑 Docker 的机器。官方镜像支持 amd64 / arm64 / armv7,树莓派都能跑。默认镜像内存占用极小,2 核 2G 的机器随便跑;如果你要上 plus 镜像(网页快照),官方要求至少 1 GB 额外内存给 Chromium
  2. 想好数据放哪。所有数据(数据库、图标、快照)都在一个 data 目录里,挂出来就行,不挑存储
  3. 规划域名,比如 bk.你的域名.com。可选,但强烈建议——浏览器扩展、API、多设备访问都依赖一个固定的对外地址
  4. 镜像。官方同时发布到 Docker Hub(sissbruecker/linkding)和 GitHub Container Registry(ghcr.io/sissbruecker/linkding),国内拉不动一个换另一个。

关于 tag,这期我实测了一遍(v1.47.0,2026-09-13 发布):

tag 结果
1 404,不存在
1.47 404,不存在
1.47.0 200
latest 200,与 1.47.0 digest 相同(sha256:e35cb50e…)
1.47.0-plus 200(digest 不同,是另一份镜像)
1.47.0-alpine 200(实验性)

它的 CI(.github/workflows/build.yaml)只发布完整版本号 + latest + 各变体,不滚动次版本 tag——跟第 8 期 Navidrome、第 12 期 Miniflux 一类,必须钉全量版本 1.47.0。别想当然写 :1.47,那个 tag 不存在,docker pull 直接报错。

变体怎么选:

变体 适合
1.47.0(默认) 只管存链接、搜链接。镜像小、内存省
1.47.0-plus 想要服务端网页快照(Chromium + single-file-cli + uBlock 内置)。镜像大 1 GB+,运行时至少多要 1 GB 内存
1.47.0-alpine 官方标注 🧪 实验性,生产别碰

建议先装默认版跑顺了,确实需要"存网页尸体"再换 plus——两个变体的数据目录格式一致,直接换镜像重启即可迁移。

docker run 一行版

这期是真正的"一行"——单容器、无外部依赖、SQLite 落盘:

mkdir -p /opt/linkding/data

docker run -d \
  --name linkding \
  -p 127.0.0.1:9090:9090 \
  -v /opt/linkding/data:/etc/linkding/data \
  -e TZ=Asia/Shanghai \
  -e LD_SUPERUSER_NAME=admin \
  -e LD_SUPERUSER_PASSWORD=换成你自己的强密码 \
  --restart unless-stopped \
  sissbruecker/linkding:1.47.0

几个必须知道的点:

  • -v …:/etc/linkding/data 是唯一要挂的卷。数据库 db.sqlite3、密钥 secretkey.txt、图标 favicons/、快照 assets/、任务队列 tasks.sqlite3 全在里面。这个目录丢了 = 全部书签没了
  • 端口映射成 127.0.0.1:9090 是留给反向代理的姿势;没有反代、纯内网用的话直接写 -p 9090:9090
  • LD_SUPERUSER_NAME + LD_SUPERUSER_PASSWORD 一起设,首次启动自动建管理员。官方镜像默认不带任何用户,两个变量缺一个:只写用户名不写密码时,会建出一个没有可用密码的账号(这是为反代认证准备的场景),登录页是进不去的
  • 密钥不用你管。首次启动时 bootstrap.sh 会自动生成 secretkey.txt 存进 data 目录——比第 14 期 Paperless-ngx 那个必填的 SECRET_KEY 省心
  • 容器健康检查镜像里自带(curl http://localhost:9090/health,30 秒一次),1Panel 的容器页能直接看到 healthy

docker-compose 推荐版

services:
  linkding:
    image: sissbruecker/linkding:1.47.0
    container_name: linkding
    restart: unless-stopped
    ports:
      - "127.0.0.1:9090:9090"     # 只绑本机,交给反向代理对外
    volumes:
      - ./data:/etc/linkding/data # 所有数据都在这里,备份就备它
    environment:
      TZ: Asia/Shanghai
      # 首次启动自动建管理员(两个都设才会带密码创建)
      LD_SUPERUSER_NAME: admin
      LD_SUPERUSER_PASSWORD: 换成你自己的强密码
      # 用了域名 + 反代就写上,否则登录时 CSRF 403
      LD_CSRF_TRUSTED_ORIGINS: https://bk.你的域名.com

就这么多——没有数据库容器、没有 broker、没有缓存,这是它跟 Immich、Paperless-ngx 那种"全家桶"最大的区别。个人规模的收藏量(几千到几万条)SQLite 绰绰有余。

真要用 Postgres 的话,加一段:

  db:
    image: postgres:18
    container_name: linkding-db
    restart: unless-stopped
    environment:
      POSTGRES_DB: linkding
      POSTGRES_USER: linkding
      POSTGRES_PASSWORD: 换成你自己的强密码
    volumes:
      # ⚠️ postgres:18 起数据目录是 /var/lib/postgresql(不是 /data)
      - pgdata:/var/lib/postgresql

  # linkding 服务里追加:
  #   LD_DB_ENGINE: postgres
  #   LD_DB_HOST: db
  #   LD_DB_DATABASE: linkding
  #   LD_DB_USER: linkding
  #   LD_DB_PASSWORD: 换成你自己的强密码

volumes:
  pgdata:

什么时候才值得上 Postgres:多人共用、数据量上万、或者你有现成的 Postgres 实例想统一备份。个人用,SQLite 是更省心的选择——备份就是一个文件的事。

配置项逐项解释

下面的默认值全部来自 v1.47.0 源码 bookmarks/settings/base.py 实测:

变量 默认值 说明 / 为什么这么写
LD_SUPERUSER_NAME 无 首次启动自动建超管的用户名。用户已存在时不做任何事(不会覆盖密码)
LD_SUPERUSER_PASSWORD 无 配套密码。不设则建出的账号没有可用密码,只能走反代/OIDC 登录
TZ UTC Django 的 TIME_ZONE 直接读它。不改的话"按添加时间排序"看着差 8 小时
LD_CSRF_TRUSTED_ORIGINS 空 过反代必配。格式必须带协议、不带路径:https://bk.example.com。不配的症状:页面能开,一登录 403
LD_USE_X_FORWARDED_HOST false 信任反代的 X-Forwarded-Host。Nginx 重写 Host 头时配合使用
LD_LOG_X_FORWARDED_FOR false 日志里记录真实客户端 IP。想接 fail2ban 就开
LD_DB_ENGINE sqlite postgres 才会启用下面那组 LD_DB_* 变量
LD_REQUEST_TIMEOUT 60 uwsgi 请求超时(秒)。导入超大书签文件时调大
LD_REQUEST_MAX_CONTENT_LENGTH 不限 POST 体积上限(字节)。公网暴露时可以设个值防滥用
LD_DISABLE_BACKGROUND_TASKS false 关掉后台任务(Wayback 快照提交等)。国内服务器建议 True,原因见踩坑清单
LD_SUPERVISOR_MANAGED false 实验特性:supervisor 同时管 web 和后台任务,任务日志改打容器 stdout。默认模式下任务日志写在容器内的 background_tasks.log(见踩坑)
LD_ALLOWED_INTERNAL_HOSTS 空 SSRF 防护白名单。默认禁止抓取内网地址(192.168.x.x、nas.local 等)的元数据/预览图。收藏内网服务就把它加白:192.168.31.0/24
LD_DISABLE_URL_VALIDATION false 关掉 URL 校验。带下划线的域名、chrome:// 这类协议会被默认校验拒收
LD_SESSION_COOKIE_AGE 1209600 登录会话时长(秒)= 14 天。嫌老要重新登录就调大
LD_FAVICON_PROVIDER Google 服务 默认 t1.gstatic.com 的 favicon 接口,国内服务器不可达。可换成 DuckDuckGo(同样要出网)或自建服务,详见踩坑清单
LD_ENABLE_REFRESH_FAVICONS true 是否允许刷新图标。图标拉不到的机器直接关,省得后台任务反复失败
LD_ENABLE_SNAPSHOTS false(plus 镜像内置 true) 服务端网页快照。只有 plus 镜像里有单文件工具,默认镜像设了也没用
LD_SINGLEFILE_TIMEOUT_SEC 120(源码值;官方文档页面还写着 60) 单次快照超时。弱网/大页面调大
LD_SNAPSHOT_PDF_MAX_SIZE 15 MB 快照转 PDF 的体积上限
LD_CORS_ALLOWED_ORIGINS 空 允许浏览器跨域调 API 的来源。自建前端才需要
LD_CONTEXT_PATH 空 子路径部署(如 example.com/linkding/),值必须以 / 结尾
LD_SERVER_PORT 9090 容器内监听端口,一般不动

1Panel 面板怎么搞

好消息:1Panel 应用商店里有 linkding(264 个应用里命中 linkding,分类"实用工具")。我核对了商店的编排文件,几个关键信息:

  • 商店版本是 1.47.0-plus(最新版,直接带网页快照功能)
  • 默认端口 9090,挂载 ./data:/etc/linkding/data
  • 表单里有管理员用户名/密码两项(默认值是 admin / passwd_1Panel——装之前务必改掉密码,这个默认值全网都知道)

商店安装路线:

  1. 1Panel 左侧 应用商店 → 搜 linkding → 安装
  2. 端口保持 9090(被占用就换一个),用户名密码改成你自己的
  3. 装完它挂在 1panel-network 网络里,容器名就是应用名

不想用商店(想用更省内存的默认镜像)就走 容器 → 编排,把上面那份 compose 贴进去。两种方式二选一,别同一个数据目录装两份,SQLite 文件被两个容器同时写是会损坏的。

两个 1Panel 实操提示:

  • 商店版是 plus 镜像,2G 内存的小机器上开快照功能要悠着点——Chromium 跑一次快照能吃掉几百 MB。可以在应用参数里不动它,但把 profile 设置里的快照选项关掉,等需要时再开
  • 反向代理用 1Panel 的 网站 → 反向代理 建,目标 http://127.0.0.1:9090,顺手申请 Let's Encrypt 证书

首次访问

  1. 确认容器健康:
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:9090/health
# 200
  1. 浏览器打开 https://bk.你的域名.com,用你设的管理员账号登录。compose 里没设 LD_SUPERUSER_* 的话,手动建一个:
docker exec -it linkding python manage.py createsuperuser --username=admin --email=you@example.com
# 会提示输密码
  1. 登录后长这样——左边是书签列表(标题、备注、标签、操作),右边是标签云,顶部搜索框支持布尔语法:

linkding 主界面

  1. 第一件事去 Settings → Integrations 页把 REST API Token 复制出来存好——浏览器扩展、手机 App、第 12 期的联动全靠它
  2. 装浏览器扩展:Firefox / Chrome 商店搜 "linkding extension",填服务地址 + Token,之后在任何页面点一下就能存书签
  3. 把老收藏搬进来:浏览器先导出 HTML(Chrome/Edge:书签管理器 → 导出书签),再在 linkding 的 Settings → General → Import 里选文件导入。去重是自动的(v1.46 起修复了导入不去重的问题),放心整包导入

最小可用配置

"能跑"和"顺手"之间,就差这几步。

1)定好搜索习惯,标签少而准。linkding 的搜索语法值得花两分钟学会(官方文档 search 页全文):

docker 自托管 #教程        → 标题/备注含 docker、自托管,且带"教程"标签
#已读 not #归档            → 两个标签做差集
"把书签搬回自己服务器"      → 精确短语
(#工具 or #教程) docker    → 括号分组

经验:标签标"类型"(教程/工具/报价页),"状态"交给 unread 开关,别建"2026年收藏"这种时间类标签——它有按时间筛。

2)批量打标签用自动规则。Settings → Profile → Auto Tagging:

github.com        开源项目
youtube.com       video
mp.weixin.qq.com  公众号

存链接时自动带上,比事后补标签省太多事。

3)国内服务器的 favicon 问题(重要)。默认图标源是 t1.gstatic.com(Google 家的),华为云国内机器拉不到,表现为:书签能存,图标永远空白,后台任务反复报错。三个选择:

# 方案 A:换 DuckDuckGo 的源(同样需要能出外网,华为云默认不通)
LD_FAVICON_PROVIDER=https://icons.duckduckgo.com/ip3/{domain}.ico

# 方案 B:有代理出口的话,给容器配 HTTP 代理再走默认源
# HTTP_PROXY=http://你的代理:7890

# 方案 C:干脆关掉自动刷新图标(profile 设置里也能关)
LD_ENABLE_REFRESH_FAVICONS=False

图标不影响搜索和链接本身,个人建议:先方案 C 用着,哪天有代理出口了再开。

4)想收藏内网服务的地址(比如 http://192.168.31.193:8099):

LD_ALLOWED_INTERNAL_HOSTS=192.168.31.0/24

不设的话 linkding 会拒绝为内网 URL 抓元数据——这是它的 SSRF 防护,不是 bug。

5)把"稍后读"用起来。存书签时勾 unread,列表里就有"未读"视图;读完点一下归档。这套流程比文件夹方案轻得多——收藏夹的熵增,靠状态字段解决,不靠建文件夹。

告警 / 通知配置

linkding 不是监控类工具,这节说三件事:它挂了谁告诉你、新收藏怎么送到眼前、链接死了谁兜底。

1)存活监控 → Uptime Kuma(第 1 期)

加一个 HTTP 监控,URL 填 https://bk.你的域名.com/health,期望状态码 200。这个端点无需登录(容器健康检查也在用它),是最干净的判据。告警通道的老规矩不再重复:别把监控告警和被监控服务放同一条链路上。

2)"新收藏"输出 → RSS 喂给 Miniflux(第 12 期)

linkding 每个用户自带三条 RSS 源(源码 bookmarks/urls.py 实测):

/feeds/<feed_key>/all      全部书签
/feeds/<feed_key>/unread   未读书签
/feeds/<feed_key>/shared   分享的书签

feed_key 在 Settings → Integrations 页能看到。把这个地址填进 Miniflux 的订阅里,"我在别处存了个书签"就会出现在你的 RSS 阅读流里——两个自托管服务就这么咬合上了。

3)Internet Archive 快照 —— 国内机器直接关

书签支持自动提交到 web.archive.org 留档(后台任务),想法很好,但 archive.org 在国内不可达,华为云国内机器上这个任务会反复失败刷日志。直接:

LD_DISABLE_BACKGROUND_TASKS=True

想给重要链接留"尸体",用 plus 镜像的本地快照替代——HTML 文件落在你自己的 data/assets/ 里,不依赖任何外网服务。

反向代理与 HTTPS

以 Nginx Proxy Manager(第 2 期)为例:

  • Forward Hostname:127.0.0.1,Port:9090,Scheme http
  • 勾 SSL,申请 Let's Encrypt 证书

NPM 默认会透传 Host 头,一般直接能登录。如果遇到 403 CSRF verification failed(官方 troubleshooting 页的第一条就是它),按顺序排查:

  1. compose 里补上 LD_CSRF_TRUSTED_ORIGINS: https://bk.你的域名.com(带协议、不带结尾斜杠)然后重建容器
  2. 自定义 Nginx 配置的场景,确认转发了真实 Host:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
  1. 还不行就开 LD_USE_X_FORWARDED_HOST=True,让 linkding 以反代传来的 Host 为准

Caddy 用户一行流:

bk.你的域名.com {
    reverse_proxy 127.0.0.1:9090
}

安全提醒:linkding 里存的可能不只是链接,还有备注里贴的账号信息、内网地址。公网暴露时三件事必须做齐:强密码、HTTPS、(可选)定期改 API Token。真要防爆破,把 LD_LOG_X_FORWARDED_FOR=True 打开,再用第 1 期的方式监控登录失败就行——它没有内置的登录限流。

踩坑清单

  1. :1.47 这个 tag 不存在。CI 只发完整版本号,写 sissbruecker/linkding:1.47 会直接 pull 失败。钉 1.47.0。
  2. 升级 = 换镜像 + 原数据目录重启。docker compose pull && docker compose up -d 即可,迁移自动跑。官方有个 install-linkding.sh 脚本可以一键干这事。升级前顺手备份 data/(见下一节)。
  3. 别给容器加 user: 指令。bootstrap.sh 每次启动都要 chown -R www-data 数据目录,非 root 启动会失败;uwsgi 本身会主动降权到 www-data 运行,让容器以默认 root 起即可。
  4. 后台任务日志默认不在 docker logs 里。默认模式下 Huey 任务进程的输出写到容器内的 /etc/linkding/background_tasks.log——这个路径不在 data 卷里,容器重建就没了。想在 docker logs 里直接看,加 LD_SUPERVISOR_MANAGED=True(experimental)。
  5. favicon 拉不到不是坏了,是国内访问不到 Google 的图标服务(默认源)。处理见"最小可用配置"第 3 条。
  6. LD_DISABLE_BACKGROUND_TASKS=True 的附带影响:Wayback 提交、favicon 刷新这类后台活全停。国内机器这是特性不是缺陷。
  7. URL 校验会拒收一些"看起来合法"的地址:带下划线的域名、没有顶级域名的地址、chrome:// 之类的协议。确认自己要存这类链接就设 LD_DISABLE_URL_VALIDATION=True。
  8. 导入大书签文件超时:几千条以上的 HTML 导入可能撞上 60 秒请求超时,临时加 LD_REQUEST_TIMEOUT=300,导完再去掉。
  9. plus 镜像快照失败常见三种:网站反爬(快照拿到的是验证页)、登录页面内容不对、超时。官方给的缓解手段是 LD_SINGLEFILE_OPTIONS=--user-agent="..." 换 UA 和调大 LD_SINGLEFILE_TIMEOUT_SEC。快照不是百分百可靠的,重要内容用浏览器 SingleFile 扩展手动存更稳(linkding 提供 /api/bookmarks/singlefile/ 接口直接接)。
  10. SQLite 直接 cp 有风险:数据库开了 WAL 模式,db.sqlite3 + db.sqlite3-wal 两个文件都要拷,或者干脆用官方的 full_backup 命令(下一节)。数据库正在写的时候裸拷文件,恢复时可能打不开。
  11. 别用 :latest:跟往期同一句话——它和完整版本号当前指向一致,但你不知道哪天它就跳到下一个 minor。
  12. 多容器共写一个 data 目录 = 数据损坏。1Panel 商店版和自建编排二选一,别叠着装。

备份

数据全在一个目录里,这是它对备份最大的友好:

# 官方全量备份(SQLite 场景专用,把数据库 + 图标 + 快照打包)
docker exec -it linkding python manage.py full_backup /etc/linkding/data/backup.zip

# 拷回宿主机
docker cp linkding:/etc/linkding/data/backup.zip ./linkding-backup.zip

注意 full_backup 产物本身写在 data 目录里——别把它和源数据放在同一块盘上就算完事,起码推到另一台机器(比如第 14 期那台)。

日常 cron 方案(数据目录整目录走 SQLite 在线备份 + 文件同步):

#!/usr/bin/env bash
set -euo pipefail
DATA=/opt/linkding/data
DEST=/backup/linkding/$(date +%F)
mkdir -p "$DEST"

# 1) 数据库在线备份(官方 full_backup 内部就是这么做的,事务安全)
docker exec linkding python manage.py full_backup /etc/linkding/data/backup.zip
mv "$DATA/backup.zip" "$DEST/backup.zip"

# 2) 配置和 compose 文件顺手带上
cp /opt/linkding/docker-compose.yml "$DEST/" 2>/dev/null || true

恢复:新机器起好容器(先别挂旧数据),把 backup.zip 解压成 data/ 目录,挂载重启即可。导入导出 HTML 那条路只适合救回链接本身(丢备注、丢快照关联),不能当主备份——官方备份文档里专门列了它的六条局限。

小结

适合谁

  • 收藏夹超过三位数、换过浏览器/电脑、经历过"收藏夹失忆"的人
  • 已经在跑 Miniflux(第 12 期)的人——RSS 管持续内容,linkding 管散装收藏,两件套刚好互补
  • 想给团队/客户维护一份"常用链接清单"的(它有分享和公开只读功能)
  • 树莓派/小主机党:镜像支持 arm 全家桶,默认镜像内存占用极低
  • 想要"链接死了也能看原文"的:plus 镜像一步到位

不适合谁

  • 想要网页正文全文检索、高亮标注的——那是 readwise/Omnivore 类工具的地盘,linkding 刻意不做
  • 收藏数只有几十条、且只用一台设备的——浏览器自带收藏夹 + 定期导出就够了
  • 想要多人协作共建知识库的——它的多用户是"各管各的 + 可分享",不是 Notion 那种协作

系列过半,回头看这 15 期的分工已经能拼出一张完整的自托管地图:Uptime Kuma 看门、NPM 开门、Vaultwarden 管钥匙、Immich 管照片、Navidrome 管音乐、Miniflux 管订阅、ntfy 管推送、Paperless-ngx 管纸、linkding 管链接。每个都是单点小工具,合起来是一套不打折的个人基础设施。

项目地址