Karakeep(前身 Hoarder)自托管书签应用全解析:AI 自动打标签、全文搜索与 Docker 部署实战
【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder
Karakeep(原名 Hoarder)是一个以"自托管优先"为设计理念的开源"书签一切"应用,支持收藏链接、速记笔记、图片与 PDF,并借助 AI 实现自动打标签与摘要、全文与语义搜索。本文以仓库根目录的 README.md 为骨架,结合 docker/docker-compose.yml、packages/shared/config.ts、apps/workers/index.ts 等源码与 docs 目录下的官方文档,完整梳理其功能全景、技术栈、Docker 部署步骤、环境变量与 AI 推理配置,帮助读者在自建服务器上一站式落地这套"数据囤积者"的收藏工作流。
项目定位与命名来源
Karakeep 的定位是"self-hostable bookmark-everything app with a touch of AI for the data hoarders"——一个面向数据囤积者的、带一点 AI 能力的自托管收藏应用。它不只是收藏链接,还可以承载笔记、图片、PDF,并围绕收藏内容提供搜索、归档、协作与自动化能力。
项目名称 Karakeep 的灵感来自阿拉伯语单词"كراكيب"(karakeeb),这是一个口语化词汇,泛指杂七杂八、看似凌乱却往往承载个人价值或潜在用处的小物件,类似于"装满了舍不得扔的东西的抽屉"。这个命名精准呼应了产品的核心使用场景:把散落各处、难以归类的内容统一收进来,供日后随时翻找。
功能特性全景
README 中列出的功能覆盖了从"收藏"到"消费"再到"自动化治理"的完整链路,逐项展开如下:
收藏与内容捕获
- 收藏链接、速记笔记、图片与 PDF:三种基础内容类型(link / note / asset),并支持批量操作(Bulk actions)。
- 自动抓取链接标题、描述与图片:由爬虫工作器完成,链接被收藏后自动补充元数据与预览图。
- Mark 并保存收藏内容中的高亮(highlights):可以在已收藏的阅读内容上标记高亮片段并保存。
- 浏览器扩展快速收藏:提供 Chrome 插件、Firefox 扩展与 Safari 扩展,对应源码位于 apps/browser-extension。
- iOS / Android 原生应用:源码位于 apps/mobile,并支持移动端离线阅读。
- 导入器:支持从 Chrome、Pocket、Linkwarden、Omnivore、Tab Session Manager 导入收藏,并可借助 floccus 与浏览器书签自动同步。
组织、检索与消费
- 列表(Lists):将收藏整理进不同的列表,并支持多人协作同一个列表。
- 全文与语义搜索:基于 Meilisearch 的全文索引,加上 embedding 向量化后的语义搜索,覆盖所有已存储内容。
- AI 自动打标签与摘要:基于 LLM(支持通过 Ollama 使用本地模型),自动为收藏内容生成标签和摘要,标签语言可通过
INFERENCE_LANG配置。 - 规则引擎:基于规则的自动化管理,例如按条件自动打标签、归档等,由独立的
ruleEngine工作器驱动(见 apps/workers/index.ts)。 - OCR 图片文字提取:默认基于 tesseract.js,也可切换为 LLM 驱动的 OCR。
- RSS 自动囤积(Auto hoarding):订阅 RSS 源后自动把新内容收藏入库。
- REST API 与多客户端:项目提供 OpenAPI 规格 与官方 SDK,docs/docs/api 下收录了完整的 API 文档。
归档与防链接腐坏
- 整页归档(Full page archival):使用 monolith 将页面完整保存为单文件 HTML,抵御链接腐坏(link rot)。
- 自动视频归档:使用 yt-dlp 下载页面视频。
- 爬虫可选的PDF 快照、全页截图、banner 图本地缓存等,均在环境变量文档中有对应开关(见下文"爬虫配置")。
平台与体验
- 多语言支持:通过 Weblate 管理翻译。
- SSO 支持:支持 OIDC 兼容的 OAuth 登录。
- 暗色模式、自托管优先的设计哲学。
技术栈与仓库结构
README 明确列出的技术栈如下:
| 组件 | 用途 |
|---|---|
| Next.js(App Router) | Web 应用主体 |
| Drizzle | 数据库 ORM 与迁移 |
| NextAuth | 认证 |
| tRPC | 客户端与服务端通信 |
| Puppeteer | 爬取收藏的网页 |
| OpenAI | AI 打标签等推理(可通过 Ollama 换本地模型) |
| Meilisearch | 全文内容搜索 |
仓库是一个 pnpm + Turbo 的 monorepo,根 package.json 提供pnpm dev、pnpm build、pnpm db:migrate等脚本。官方 目录结构文档 给出了清晰的模块划分:
- 应用层:
apps/web(主 Web 应用)、apps/workers(后台工作器)、apps/mobile(React Native 移动应用)、apps/browser-extension(浏览器扩展)、apps/landing(落地页)。 - 共享包:
packages/db(数据库 schema 与迁移)、packages/trpc(大部分业务逻辑以 tRPC 路由形式存在)、packages/shared(各应用共享的日志与配置)、packages/shared-server(队列、资产存储等仅服务端可用的服务)、packages/plugins(可插拔服务实现,如文件系统与 S3 存储)。 - 工具链:
tooling/typescript、tooling/eslint、tooling/prettier、tooling/tailwind存放共享配置。
从 apps/workers/index.ts 可以看到,后台按职责拆成了 12 类工作器:crawler、lowPriorityCrawler、embeddings、inference、search、adminMaintenance、video、feed、assetPreprocessing、webhook、ruleEngine、backup,外加一个import轮询工作器;它们各自消费独立的队列(如LinkCrawlerQueue、OpenAIQueue、SearchIndexingQueue),并通过WORKERS_ENABLED_WORKERS/WORKERS_DISABLED_WORKERS两个环境变量按需启停。
Docker 部署实战
Docker Compose 是官方推荐、也是最快上手的部署方式,详见 Docker 安装指南。
1. 创建目录并下载 compose 文件
新建一个目录(例如karakeep-app),把官方提供的 docker/docker-compose.yml 放进去。该文件定义了三个服务:
- web:主应用,镜像为
ghcr.io/karakeep-app/karakeep:${KARAKEEP_VERSION:-release},端口3000:3000,数据卷data:/data,并通过环境变量把MEILI_ADDR指向 meilisearch、BROWSER_WEB_URL指向 chrome 服务;DATA_DIR固定为/data(官方注释强调"不要改",要改数据目录应改卷映射)。 - chrome:爬虫用的 headless 浏览器容器,镜像
ghcr.io/karakeep-app/karakeep-chrome:release,启动参数包含--disable-gpu、--disable-dev-shm-usage、--hide-scrollbars等。 - meilisearch:搜索服务,镜像
getmeili/meilisearch:v1.41.0,启用MEILI_NO_ANALYTICS: "true",数据卷meilisearch:/meili_data。
2. 填写 .env 环境变量
在 compose 文件同目录创建.env,最小可用配置如下:
KARAKEEP_VERSION=release NEXTAUTH_SECRET=super_random_string MEILI_MASTER_KEY=another_random_string NEXTAUTH_URL=http://localhost:3000要点:
- 两个随机字符串务必替换,可用
openssl rand -base64 36生成;MEILI_MASTER_KEY建议用openssl rand -base64 36 | tr -dc 'A-Za-z0-9'生成(避免特殊字符)。 NEXTAUTH_URL要指向你实际访问 Karakeep 的地址,否则登出等场景会跳转到错误地址。KARAKEEP_VERSION=release会拉取最新稳定版;要控制升级节奏可固定到具体版本(如0.10.0)。- 每次修改
.env后都需要重新执行docker compose up使配置生效。
3. 配置 AI(可选但强烈推荐)
要启用自动打标签,在.env中追加OPENAI_API_KEY=<key>即可。也可以改用其他 OpenAI 兼容服务或本地 Ollama,见下文"AI Provider 配置"一节。
4. 启动与验证
docker compose up -d随后访问http://localhost:3000即可看到登录页。持久化存储与服务间联调(web ↔ chrome ↔ meilisearch)已由 compose 文件处理。
5. 升级
升级方式取决于KARAKEEP_VERSION的取值:
- 固定版本:改版本号后重新
docker compose up -d拉取新镜像; - 使用
release:执行docker compose up --pull always -d强制拉取最新版本。
若自定义 compose 仍在使用旧版 Alpine Chrome 镜像,需参考 Chrome 镜像迁移指南;升级/迁移 Meilisearch 版本时,可参考 故障排查文档。
环境变量配置详解
Karakeep 以环境变量为主要配置入口,全部变量统一定义在 packages/shared/config.ts(使用 zod schema 做解析、默认值与校验),完整参数说明见 环境变量文档。以下是按功能域划分的核心变量:
基础与安全
| 变量 | 必填 | 默认值 | 说明 |
|---|---|---|---|
PORT | 否 | 3000 | Web 服务监听端口;用 Docker 时不要改它,改外部端口映射即可 |
WORKERS_PORT | 否 | 0(随机) | 工作器导出 Prometheus 指标的端口(/metrics) |
WORKERS_HOST | 否 | 127.0.0.1 | 指标监听地址,容器内运行需改为可外部访问的地址 |
WORKERS_ENABLED_WORKERS | 否 | 未设置 | 逗号分隔的工作器白名单:crawler,inference,search,adminMaintenance,video,feed,assetPreprocessing,webhook,ruleEngine,backup |
WORKERS_DISABLED_WORKERS | 否 | 未设置 | 逗号分隔的工作器黑名单,优先级高于WORKERS_ENABLED_WORKERS |
LOG_LEVEL | 否 | debug | 按 winston 的日志级别定义,生产环境建议notice或warning |
DATA_DIR | 是 | 未设置 | 持久数据目录(数据库所在处),未设置ASSETS_DIR时资产也存于此 |
ASSETS_DIR | 否 | ${DATA_DIR}/assets | 爬取资产的存储路径 |
NEXTAUTH_URL | 是 | 未设置 | 服务器对外地址 |
NEXTAUTH_SECRET | 是 | 未设置 | 用于签名 JWT 的随机串 |
MEILI_ADDR | 否 | 未设置 | Meilisearch 地址,未设置则搜索被禁用 |
MEILI_MASTER_KEY | 仅生产 + 启用搜索 | 未设置 | Meilisearch 主密钥,开发环境不需要 |
MAX_ASSET_SIZE_MB | 否 | 50 | 允许上传的资产大小上限(MB) |
DB_WAL_MODE | 否 | false | 为 SQLite 开启 WAL 模式提升性能;数据库在网络盘上时不要开启 |
DISABLE_NEW_RELEASE_CHECK | 否 | false | 关闭管理面板中的新版本检查 |
认证与注册
| 变量 | 默认值 | 说明 |
|---|---|---|
DISABLE_SIGNUPS | false | 禁止新用户注册 |
DISABLE_PASSWORD_AUTH | false | 仅允许 OAuth 登录 |
EMAIL_VERIFICATION_REQUIRED | false | 注册需邮箱验证(需配置 SMTP) |
OAUTH_WELLKNOWN_URL | 未设置 | OAuth 提供商的 OpenID 配置地址 |
OAUTH_CLIENT_ID/OAUTH_CLIENT_SECRET | 未设置 | OAuth 客户端凭证 |
OAUTH_ID_TOKEN_SIGNED_RESPONSE_ALG | 未设置 | ID token 的 JWS 签名算法,可选RS256…EdDSA;与提供商实际算法不符会导致回调报 JWT 算法错误 |
OAUTH_SCOPE | openid email profile | 请求的 scope 列表(空格分隔) |
OAUTH_PROVIDER_NAME | Custom Provider | 登录页显示的提供商名 |
OAUTH_AUTO_REDIRECT | false | 仅 OAuth 认证时自动跳转提供商 |
OAUTH_TIMEOUT | 3500 | 等待提供商响应毫秒数,遇outgoing request timed out可调大 |
注意:仅支持 OIDC 兼容的 OAuth 提供商,且回调地址需配置为<NEXTAUTH_URL>/api/auth/callback/custom。
资产存储:本地磁盘 vs S3
默认使用本地文件系统,传入 S3 端点后自动切换为 S3 兼容对象存储:
| 变量 | 说明 |
|---|---|
ASSET_STORE_S3_ENDPOINT | S3 端点 URL(如 MinIO),设置即启用 S3 |
ASSET_STORE_S3_REGION | S3 区域 |
ASSET_STORE_S3_BUCKET | 桶名(使用 S3 时必填) |
ASSET_STORE_S3_ACCESS_KEY_ID/ASSET_STORE_S3_SECRET_ACCESS_KEY | S3 认证凭证 |
ASSET_STORE_S3_FORCE_PATH_STYLE | MinIO 等需设为true |
文档明确警告:存储后端一经写入数据即不可随意切换,否则需要手工迁移既有资产,部署前应规划好存储方案。
爬虫配置(Crawler)
| 变量 | 默认值 | 说明 |
|---|---|---|
CRAWLER_NUM_WORKERS | 1 | 并发爬取任务数 |
BROWSER_WEB_URL/BROWSER_WEBSOCKET_URL | 未设置 | 浏览器调试地址;都不设置时退化为纯 HTTP 请求,跳过截图与 JS 执行 |
CRAWLER_STORE_SCREENSHOT | true | 存储网页截图(作为图片提取失败的兜底) |
CRAWLER_FULL_PAGE_SCREENSHOT | false | 存储整页截图(磁盘占用高,默认关闭) |
CRAWLER_STORE_PDF | false | 存储页面 PDF 快照(默认关闭) |
CRAWLER_FULL_PAGE_ARCHIVE | false | 整页本地归档(默认关闭,仅归档可读文本) |
CRAWLER_VIDEO_DOWNLOAD | false | 用 yt-dlp 下载页面视频 |
CRAWLER_VIDEO_DOWNLOAD_MAX_SIZE | 50 | 视频最大体积(MB),-1禁用限制 |
CRAWLER_JOB_TIMEOUT_SEC | 60 | 爬取任务超时 |
CRAWLER_ENABLE_ADBLOCKER | true | 爬虫内置广告拦截 |
CRAWLER_ENABLE_AUTOCONSENT | true | 自动选择退出支持的同意弹窗 |
CRAWLER_YTDLP_ARGS/CRAWLER_MONOLITH_ARGS | [] | 追加 yt-dlp / monolith 参数,多个参数用%%分隔 |
BROWSER_COOKIE_PATH | 未设置 | 加载到浏览器上下文的 cookie JSON 文件路径(数组,name/value必填,domain、expires、httpOnly、sameSite等可选) |
OCR 配置
| 变量 | 默认值 | 说明 |
|---|---|---|
OCR_CACHE_DIR | $TEMP_DIR | tesseract 模型下载目录 |
OCR_LANGS | eng | 逗号分隔的语言码,置空可禁用 OCR |
OCR_CONFIDENCE_THRESHOLD | 50 | 置信度阈值(0–100),低于阈值不保存识别文本 |
OCR_USE_LLM | false | 改用推理模型(OpenAI/Ollama)做 OCR,复杂图片效果更好 |
Webhook 配置
| 变量 | 默认值 | 说明 |
|---|---|---|
WEBHOOK_TIMEOUT_SEC | 5 | webhook 请求超时 |
WEBHOOK_RETRY_TIMES | 3 | 重试次数 |
Webhook 触发时请求头携带Authorization: Bearer <WEBHOOK_TOKEN>,请求体为包含jobId、type、bookmarkId、userId、url、operation的 JSON。
SMTP 与代理
- SMTP:
SMTP_HOST、SMTP_PORT(默认587)、SMTP_SECURE、SMTP_USER、SMTP_PASSWORD、SMTP_FROM,用于注册邮箱验证等邮件功能。 - 代理:
CRAWLER_HTTP_PROXY/CRAWLER_HTTPS_PROXY(支持逗号分隔多代理随机选用,作用于爬取、RSS 拉取与 webhook)、CRAWLER_NO_PROXY(绕过列表)、CRAWLER_ALLOWED_INTERNAL_HOSTNAMES(默认拦截解析到内网/回环/link-local 地址的请求,用点前缀支持域名通配)。
可观测性
| 变量 | 默认值 | 说明 |
|---|---|---|
OTEL_TRACING_ENABLED | false | 启用 OpenTelemetry 分布式追踪 |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT | 未设置 | 追踪 OTLP 端点,未设置则打到控制台 |
OTEL_SAMPLE_RATE | 1.0 | 追踪采样率 |
EVENT_LOGS_ENABLED | false | 结构化事件日志(登录、书签创建等) |
PROMETHEUS_AUTH_TOKEN | 随机 | /api/metrics的 Bearer 认证令牌 |
AI Provider 配置:从 OpenAI 到本地 Ollama
AI 能力(自动打标签、摘要、语义搜索的 embedding)是本项目的核心卖点之一。配置全貌见 AI Provider 指南,核心规则是:OPENAI_API_KEY与OLLAMA_BASE_URL至少设置其一,自动打标签才会启用。
OpenAI(默认)
只需设置OPENAI_API_KEY;默认推理模型为gpt-5.6-luna(文本)、gpt-4o-mini(图片),embedding 默认text-embedding-3-small/ 1536 维,均可在.env中覆盖:
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx # INFERENCE_TEXT_MODEL=gpt-4.1-mini # INFERENCE_IMAGE_MODEL=gpt-4o-mini # EMBEDDING_TEXT_MODEL=text-embedding-3-small # EMBEDDING_DIMENSIONS=1536补充说明:OPENAI_BASE_URL可指向任意 OpenAI 兼容 API(Azure、Gemini、OpenRouter、Perplexity、Cloudflare 等均可用此方式接入);OPENAI_TIMEOUT_SEC未设置时沿用 OpenAI SDK 默认 10 分钟;OPENAI_SERVICE_TIER=flex可换取更低成本(响应更慢、偶发资源不可用);OPENAI_REASONING_EFFORT控制推理模型的思考强度。
Ollama 本地推理
Ollama 提供两种接入方式,且地址必须能被 Karakeep 容器访问(不能用 localhost):
方式一:OpenAI 兼容端点(推荐),走/v1chat 接口,消息格式化更可靠:
OPENAI_API_KEY=ollama OPENAI_BASE_URL=http://ollama.mylab.com:11434/v1 INFERENCE_TEXT_MODEL=gemma3 INFERENCE_IMAGE_MODEL=llava EMBEDDING_TEXT_MODEL=embeddinggemma EMBEDDING_DIMENSIONS=768 EMBEDDING_CONTEXT_LENGTH=2048方式二:原生 Ollama API,注意此时绝不能设置OPENAI_API_KEY(否则优先走 OpenAI):
OLLAMA_BASE_URL=http://ollama.mylab.com:11434 # INFERENCE_OUTPUT_SCHEMA=plain # 模型不支持结构化输出时需要OLLAMA_KEEP_ALIVE控制模型在内存中的驻留时长(如5m、-1m永久驻留、0即时卸载);INFERENCE_FETCH_TIMEOUT_SEC(默认 300)针对 Ollama 请求超时。
其他 OpenAI 兼容提供商
文档还给出了可直接套用的配置模板:Gemini(OPENAI_BASE_URL=https://generativelanguage.googleapis.com/v1beta,示例模型gemini-2.5-flash-lite)、OpenRouter(https://openrouter.ai/api/v1)、Perplexity(https://api.perplexity.ai)、Azure(模型名即部署名)、Cloudflare Workers AI(建议INFERENCE_OUTPUT_SCHEMA=json)。
Embedding 与语义搜索
- 三个关键变量:
EMBEDDING_TEXT_MODEL、EMBEDDING_DIMENSIONS(向量维度,必须与模型一致)、EMBEDDING_CONTEXT_LENGTH(默认 8000 字符,超出截断)。 - Embedding 可独立使用另一家 OpenAI 兼容提供商:
EMBEDDING_OPENAI_API_KEY、EMBEDDING_OPENAI_BASE_URL,未设置时回落到对应的OPENAI_*变量。 - 支持可变维度的模型可设
EMBEDDING_TEXT_MODEL_DIMENSION_OVERRIDE,其值必须等于EMBEDDING_DIMENSIONS,否则 Karakeep 启动失败。 - 配置好 embedding 后需开启
EMBEDDING_ENABLE_AUTO_INDEXING=true;SEMANTIC_SEARCH_ENABLED(默认true)控制混合/语义搜索模式(实验性)。 - 重要提醒:不同模型的向量互不兼容,更换 embedding 模型或维度后,需要为全部书签重新生成向量。
打标签/摘要相关调优
INFERENCE_CONTEXT_LENGTH(默认 2048 token)决定送入模型的内容量,调大提升标签质量但更费钱/费资源;INFERENCE_MAX_OUTPUT_TOKENS(默认 2048)控制生成长度;INFERENCE_LANG(默认english)指定标签语言;INFERENCE_ENABLE_AUTO_TAGGING(默认true)与INFERENCE_ENABLE_AUTO_SUMMARIZATION(默认false)分别开关自动打标签与摘要;INFERENCE_OUTPUT_SCHEMA(默认structured,可选json/plain)适配模型的结构化输出能力。此外可在"用户设置 → AI Settings"中给自动打标签的 prompt 追加自定义指令,并支持$tags、$aiTags、$userTags三个占位符(分别替换为全部标签、AI 标签、人工标签)。
体验 Demo 与快速上手
官方提供了在线 Demo:访问https://try.karakeep.app,使用demo@karakeep.app/demodemo登录。Demo 预置了示例内容,但处于只读模式以防滥用——适合在部署前先直观感受界面与交互。部署完成后,可以继续阅读 docs 下的使用指南(书签、列表、标签、搜索语法、导入、快速分享等),以及 命令行工具 与 MCP 服务 的接入文档,实现"LLM Agent 友好"的自动化工作流。
项目背景、动机与生态
- 构建动机:作者长期在手机端浏览 Reddit/Twitter/Hacker News,需要把值得稍后细读的内容收藏下来;在尝试 Pocket、memos 等工具后,发现它们缺少"链接预览 + 自动打标签"的组合能力,于是决定自建。README 中也客观列举了作者参考过的同类工具(memos、mymind、raindrop、Pocket、Linkwarden、Wallabag、Shiori),这些内容可作为选型时的背景参考。
- 翻译:项目通过 Weblate 管理多语言翻译,欢迎贡献。
- 托管云服务:若不想自托管,官方提供 Karakeep Cloud 托管服务,订阅收入用于支持项目开发。
- 社区渠道:官方 Discord 与 Twitter(@karakeep_app)是主要的交流渠道。
- 许可证:项目采用 AGPL-3.0 协议(见 LICENSE)。
总结
Karakeep 把"收藏 + AI 治理 + 全文/语义检索 + 归档防腐坏"整合进一个自托管优先的 monorepo 中:Web 端由 Next.js + tRPC + Drizzle 驱动,后台按队列模型拆分成 12 类可独立启停的工作器,资产存储支持本地磁盘与 S3 双后端,AI 推理既可直连 OpenAI 也能通过 Ollama 完全本地化。对个人用户而言,按 Docker 安装指南 三步即可完成部署;对开发者而言,目录结构文档、环境变量文档 与 packages/shared/config.ts 提供了从配置到源码的完整索引,是一套相当适合自托管与二次开发的书签基础设施。
【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考