1. 为什么我又把团队知识库从 Notion 搬回了 Outline团队 wiki 这个东西说起来都是泪。我们团队从最早的 Word 共享文件夹到后来的语雀、Notion再到现在的 Outline前后折腾了不下五次。每次迁移都有人骂街但每次迁移完大家都觉得值。今天就把这套折腾经验完整倒出来尤其是那些正在被 Notion 按人头收费、或者被各种协作工具限制卡得难受的朋友这篇内容应该能帮你省下不少时间和预算。先说结论Outline 是一个 40K Star 级别的开源知识库工具支持完全自部署界面和编辑体验非常接近 Notion但你可以把它跑在自己的服务器上团队规模再大也不会多花一分钱。它解决的核心问题就一个——让中小团队在不牺牲编辑体验的前提下把知识库的长期成本压到接近于零。适合谁看三类人一是被 SaaS 工具按席位收费搞烦的技术负责人二是想自己掌控数据、不想把公司文档放在别人服务器上的团队三是单纯想折腾一套私有 wiki 的开发者。我自己第一次接触 Outline 是在一个六人小团队里当时用 Notion 免费版块数限制卡得我们连会议纪要都不敢多写。后来换到 Outline 自部署一台 2 核 4G 的轻量服务器跑了一年多团队扩到二十多人也没加过配置。这篇文章我会把选型逻辑、部署细节、踩过的坑、以及和 Notion 的真实对比全部讲清楚你照着做基本能一次跑通。2. 选型之前先想清楚团队 wiki 到底在选什么2.1 知识库工具的三个核心维度很多人选 wiki 工具只看界面好不好看这是最容易踩坑的地方。我总结下来团队知识库的选型其实就三个维度在互相拉扯编辑体验、数据掌控、长期成本。编辑体验决定了团队成员愿不愿意写。一个卡顿的编辑器、一个不支持 Markdown 快捷输入的界面会让写文档变成一种折磨。Notion 之所以流行很大程度上就是它的块编辑器体验做得足够顺滑拖拽、嵌套、数据库视图都很自然。数据掌控决定了你的文档到底属于谁。SaaS 工具的数据存在厂商服务器上你导出的时候经常发现格式丢失、附件链接失效。自部署工具的数据在你自己的数据库和对象存储里想备份就备份想迁移就迁移。长期成本是最容易被低估的。Notion 的团队版按人头收费一个人一个月几十块二十人的团队一年就是小一万。而且这个成本是随团队规模线性增长的人越多越肉疼。自部署工具的前期投入是一台服务器加一些配置时间之后无论多少人用成本基本不变。2.2 为什么 Outline 在这三个维度上比较均衡Outline 的定位很聪明它没有试图做一个全能工具而是把“文档协作”这一件事做到接近 Notion 的水平然后把部署自由度和成本控制交给用户。编辑体验上Outline 用的是富文本编辑器支持 Markdown 快捷语法、斜杠命令、拖拽排序、嵌套文档、评论、提及。你从 Notion 迁过来基本不需要重新学习快捷键都差不多。它没有 Notion 的数据库视图和看板功能但对于纯文档 wiki 来说这些功能其实用得很少。数据掌控上Outline 支持 PostgreSQL 作为主数据库附件可以存本地磁盘也可以对接 S3 兼容的对象存储。整个应用可以跑在 Docker 里备份就是备份数据库和附件目录非常直接。成本上一台 2 核 4G 的服务器一年也就几百块域名和对象存储如果用量不大成本可以忽略。团队从 5 人扩到 50 人服务器配置不用动这是 SaaS 工具做不到的。2.3 什么情况下不建议选 OutlineOutline 不是万能的。如果你的团队重度依赖 Notion 的数据库、看板、日历视图那迁移过来会很难受因为 Outline 没有这些。如果团队完全没有技术人员没人愿意维护服务器那自部署的隐性成本可能比 SaaS 订阅还高。如果团队需要复杂的权限体系比如按部门、按项目做细粒度隔离Outline 的权限模型相对简单可能不够用。我的建议是纯文档型 wiki、团队有至少一个能跑 Docker 的人、对数据掌控有要求这三个条件满足两个以上Outline 就值得考虑。3. Outline 部署实操从零到能用的完整流程3.1 部署前的准备工作先把需要的东西列清楚避免做到一半发现缺东西。服务器方面最低配置建议 2 核 4G系统用 Ubuntu 22.04 或 Debian 12 都行。磁盘至少 40G因为 Docker 镜像和数据库会占一些空间。如果团队文档里图片多磁盘要相应加大或者直接对接对象存储。域名方面需要一个能解析到服务器 IP 的域名因为 Outline 的登录和协作依赖 HTTPS用 IP 直接访问会有各种问题。证书用 Lets Encrypt 免费申请就行。软件依赖方面服务器上需要装好 Docker 和 Docker Compose。这两个的安装网上教程很多我就不展开了只提醒一点Docker Compose 要用 v2 版本命令是docker compose而不是老的docker-compose很多老教程还在用 v1 的写法照抄会报错。第三方服务方面Outline 需要一个 OIDC 兼容的身份认证服务来处理登录。官方推荐的是自己再部署一个认证服务但这对新手来说太重了。我的做法是用一个轻量的 OIDC 服务配置简单跑起来也快。具体选型我在下一节讲。3.2 核心配置文件怎么写Outline 的部署核心是一个docker-compose.yml文件和一个.env环境变量文件。我先把完整的 compose 文件贴出来然后逐段解释。version: 3.8 services: outline: image: outlinewiki/outline:latest restart: always ports: - 3000:3000 env_file: - .env depends_on: - postgres - redis volumes: - ./data/outline:/var/lib/outline/data postgres: image: postgres:15 restart: always environment: POSTGRES_USER: outline POSTGRES_PASSWORD: your_strong_password POSTGRES_DB: outline volumes: - ./data/postgres:/var/lib/postgresql/data redis: image: redis:7 restart: always volumes: - ./data/redis:/data这个文件定义了三个服务Outline 主应用、PostgreSQL 数据库、Redis 缓存。三个服务都挂了本地目录做持久化这样容器重启数据不会丢。然后是.env文件这是配置的重点我按重要性排序讲。# 基础配置 NODE_ENVproduction SECRET_KEYyour_random_secret_key_here UTILS_SECRETanother_random_secret_here # 数据库连接 DATABASE_URLpostgres://outline:your_strong_passwordpostgres:5432/outline REDIS_URLredis://redis:6379 # 访问地址 URLhttps://wiki.yourdomain.com PORT3000 # 认证配置 OIDC_CLIENT_IDoutline OIDC_CLIENT_SECRETyour_oidc_secret OIDC_AUTH_URIhttps://auth.yourdomain.com/authorize OIDC_TOKEN_URIhttps://auth.yourdomain.com/token OIDC_USERINFO_URIhttps://auth.yourdomain.com/userinfo OIDC_USERNAME_CLAIMpreferred_username OIDC_DISPLAY_NAME团队登录 # 文件存储 FILE_STORAGElocal FILE_STORAGE_LOCAL_ROOT_DIR/var/lib/outline/dataSECRET_KEY和UTILS_SECRET这两个必须用随机字符串可以用openssl rand -hex 32生成。很多人图省事直接写个固定值这在生产环境是安全隐患别偷懒。URL必须和你实际访问的域名完全一致包括协议。如果这里写错登录回调会失败表现是点登录后跳转到一个空白页或者报错。OIDC_*这一组是认证配置最容易出问题的地方。OIDC_USERNAME_CLAIM决定了用哪个字段作为用户名显示不同认证服务返回的字段名不一样常见的有preferred_username、email、name要对着你的认证服务实际返回的字段来填。3.3 身份认证服务的选型与配置这是整个部署里最绕的一环我单独拿出来讲。Outline 本身不提供账号密码登录它必须依赖一个 OIDC 服务。官方文档推荐的是自己部署一个认证服务但那个方案对新手来说配置量太大。我的做法是用一个轻量的 OIDC 服务它支持 Docker 部署配置一个客户端就能用。核心配置就几项客户端 ID、客户端密钥、回调地址。回调地址要填https://wiki.yourdomain.com/auth/oidc.callback这个路径是 Outline 固定的填错就登录不了。配置好之后在认证服务里创建一个用户然后用这个用户去登录 Outline。第一个登录的用户会自动成为管理员后面再邀请其他人。注意认证服务的回调地址必须和 Outline 的 URL 完全匹配包括末尾不能有多余的斜杠。我在这上面卡了两个小时最后发现是多了一个斜杠导致回调失败。3.4 反向代理和 HTTPS 配置Outline 跑在 3000 端口对外要通过反向代理暴露。我用的是 Nginx配置不复杂但有几个细节要注意。server { listen 443 ssl http2; server_name wiki.yourdomain.com; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; location / { proxy_pass http://127.0.0.1:3000; 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_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } }Upgrade和Connection这两行是给 WebSocket 用的Outline 的实时协作依赖 WebSocket不配这两行的话多人同时编辑会出问题。X-Forwarded-Proto也要带上不然 Outline 可能生成错误的回调地址。证书用 certbot 申请就行一条命令的事。申请完记得设置自动续期不然三个月后证书过期整个 wiki 就打不开了。4. 从 Notion 迁移到 Outline 的实操细节4.1 迁移前的数据整理直接导出导入往往会一团糟我的经验是先在 Notion 里做一轮整理。把不需要迁移的页面归档把嵌套层级过深的页面拍平把数据库视图里的内容导出成普通表格。这一步花的时间会在导入后省回来。Notion 的导出格式选 Markdown CSV会得到一个包含所有页面的压缩包。解压后你会看到一堆.md文件和对应的附件文件夹。附件的引用路径需要检查一下Notion 导出的路径有时候和实际文件位置对不上。4.2 导入 Outline 的两种方式Outline 支持两种导入方式一种是直接在界面里上传 Markdown 压缩包适合文档量不大的情况另一种是用命令行工具批量导入适合几百个页面以上的场景。界面导入很简单在设置里找到导入选项上传压缩包等它处理完就行。但这种方式对附件路径的处理不太智能经常出现图片丢失的情况。命令行导入更可控。Outline 提供了一个导入脚本可以指定源目录和目标集合。我实测下来命令行导入对附件路径的处理更准确而且可以分批导入避免一次性导入太多导致超时。实操心得导入之前先在 Outline 里建好对应的集合结构导入时直接映射过去比导入后再整理要省事得多。我第一次导入没建集合结果所有页面都堆在默认集合里手动整理花了半天。4.3 迁移后的检查和修复导入完成后一定要抽查。重点检查三类内容图片和附件是否正常显示、代码块格式是否保留、内部链接是否还能跳转。图片丢失是最常见的问题原因是 Notion 导出的附件路径和 Outline 期望的路径不一致。解决办法是手动把附件上传到 Outline 的附件目录然后批量替换 Markdown 里的图片链接。代码块格式问题通常是语言标识丢失Notion 导出的代码块有时候不带语言标记导入后变成纯文本。这个只能手动补或者写个脚本批量处理。内部链接失效是因为 Notion 的页面 ID 和 Outline 的文档 ID 不一样导入后链接指向就断了。Outline 在导入时会尽量保留链接关系但跨集合的链接经常断。我的做法是导入后跑一遍链接检查把断掉的链接列出来手动修。5. 常见问题排查与避坑经验5.1 部署阶段的高频问题问题现象可能原因解决办法登录后跳转空白页URL 配置和实际访问地址不一致检查 .env 里的 URL确保协议和域名完全匹配回调报错 invalid_redirect_uri认证服务回调地址配错确认回调地址是https://域名/auth/oidc.callback容器启动后立即退出数据库连接失败检查 DATABASE_URL 里的密码和 postgres 服务配置是否一致上传图片失败文件存储目录权限不对给 data/outline 目录设置正确的读写权限多人编辑冲突WebSocket 没配好检查 Nginx 配置里的 Upgrade 和 Connection 头5.2 使用阶段的踩坑记录搜索功能对中文支持一般。Outline 的全文搜索基于 PostgreSQL 的全文检索对中文的分词支持不如英文。如果你的文档以中文为主搜索体验会打折扣。我的应对办法是在文档标题和关键段落里手动加一些英文关键词提高搜索命中率。附件存储要提前规划。如果团队文档里图片和视频多本地磁盘很快会满。建议一开始就对接 S3 兼容的对象存储国内几家云厂商都有成本也不高。切换存储方式需要改配置并迁移已有附件最好一开始就定好。备份策略不能省。我见过太多团队自部署之后从来不备份服务器一出问题数据全没。最低限度要每天备份 PostgreSQL 数据库附件目录可以每周同步一次到另一个地方。备份脚本写个 cron 任务就行不复杂但必须有。版本升级要谨慎。Outline 更新比较频繁但跨大版本升级有时候会有数据库迁移。升级前一定要先备份然后在测试环境跑一遍。我有一次直接在生产环境升级结果数据库迁移卡住服务停了半小时。5.3 性能优化的几个实用技巧服务器配置不高的情况下可以做一些优化。PostgreSQL 的连接数不要设太大Outline 默认的连接池配置对 4G 内存的机器来说够用了。Redis 可以设置内存上限避免缓存占满内存。Nginx 开启 gzip 压缩能明显减少页面加载时间。如果团队人数多、同时在线编辑频繁可以考虑把 PostgreSQL 和 Redis 拆到独立服务器上Outline 主应用只负责处理请求。这样架构复杂一些但性能瓶颈会少很多。6. 成本对比与长期维护的真实账本6.1 和 Notion 的成本对比拿一个 20 人的团队来算。Notion 团队版按人头收费一个人一个月大概几十块一年下来小一万。这还不算如果要用 AI 功能或者其他高级特性的额外费用。Outline 自部署的成本服务器一年几百块域名一年几十块对象存储如果用量不大一年也就百来块。加起来一年不到一千块。而且团队扩到 50 人成本基本不变。当然自部署有隐性成本主要是维护时间。但如果你本来就有服务器在跑其他服务Outline 只是多跑几个容器维护成本很低。我的实际体验是稳定运行之后每个月花在维护上的时间不超过半小时。6.2 长期维护要做的事定期更新镜像但不要追最新版等一个小版本稳定了再升。监控磁盘和内存使用快满了就清理或者扩容。检查备份是否正常执行我建议每个月手动恢复一次备份到测试环境确保备份真的能用。用户管理方面Outline 的权限模型比较简单主要是集合级别的读写权限。团队大了之后要规划好集合结构不然权限管理会很乱。我的做法是按部门或项目建集合每个集合指定管理员日常权限调整由集合管理员自己处理。6.3 什么情况下该考虑换方案如果团队规模超过一百人对权限和审计有强需求Outline 可能不够用这时候可以考虑更企业级的方案。如果团队完全没有技术人员维护服务器变成负担那还是用 SaaS 工具省心。如果文档类型以数据库、看板为主Outline 也不合适。工具没有绝对的好坏只有适不适合。Outline 的价值在于它在一个特定场景下——纯文档 wiki、中小团队、有技术能力自部署——做到了体验和成本的平衡。这个平衡点对很多团队来说刚刚好。我自己用下来最深的体会是自部署工具最大的价值不是省钱而是数据掌控带来的安心感。团队的所有文档都在自己的服务器上想怎么备份就怎么备份想怎么迁移就怎么迁移这种自由度是 SaaS 工具给不了的。当然这份自由也需要你付出相应的维护精力值不值得得看你团队的具体情况。