
1. 项目概述为什么我们需要一个开源的 AFFINE如果你和我一样是个重度笔记和知识管理工具依赖者那么 Notion 的体验你一定不陌生。它强大的块编辑器、灵活的数据库和优雅的页面关系几乎重新定义了个人和团队的信息组织方式。然而随着使用深入一些痛点也浮出水面数据完全托管在云端对于涉及敏感信息的团队或个人隐私和安全始终是个心结网络依赖性强在信号不佳或需要离线深度工作时体验大打折扣再者作为闭源商业产品其功能演进和定价策略完全由厂商决定用户缺乏自主权。正是在这种背景下AFFINE 进入了我的视野。简单来说AFFINE 是一个立志成为 Notion、Miro 和 Trello 结合体的开源、本地优先Local-First协作平台。它承诺提供 Notion 式的块编辑与数据库能力同时将数据的所有权和隐私完全交还给用户。你可以把它部署在自己的服务器、NAS 甚至个人电脑上实现数据的完全私有化。这对于开发者、技术团队、注重隐私的个人以及任何希望将核心知识资产掌握在自己手中的人来说具有天然的吸引力。最近随着“本地部署”、“私有化”成为技术圈的热词从大模型到办公套件大家越来越倾向于将关键服务握在自己手里。AFFINE 正是这股潮流在生产力工具领域的典型代表。它不仅仅是一个“替代品”更代表了一种理念工具应该服务于人而非将人锁定于某个服务。接下来我将结合自己从零部署到深度使用的全过程为你拆解 AFFINE 的核心特性、多种部署方案的选择逻辑、详细的操作步骤以及那些官方文档里不会写的“踩坑”实录与性能调优心得。2. 核心特性与架构解析AFFINE 何以成为“替代品”在决定投入时间部署一个工具前我们必须先搞清楚它到底能做什么以及其技术架构是否足够稳健。AFFINE 并非一个简单的模仿者它在设计理念和技术实现上都有其独到之处。2.1 核心功能特性拆解AFFINE 的核心价值体现在以下几个维度我们可以将其与 Notion 进行一个直观的对比特性维度AFFINENotion (作为参照)对用户的意义数据所有权完全私有。数据存储在你自己控制的服务器或本地。托管在厂商云端。彻底解决隐私顾虑满足合规性要求如GDPR、网络安全法。访问模式本地优先 (Local-First)。应用启动后所有操作优先在本地进行响应极快。纯云端。获得桌面应用般的流畅体验支持离线编辑网络中断不影响创作。核心编辑器块编辑器 (Block-Based)。支持文本、标题、列表、待办、代码块、引用等丰富块类型。块编辑器。提供与 Notion 相似且友好的内容组织方式学习成本低。数据库能力支持 (Table/Board视图)。可以创建关联数据库但目前功能深度和视图丰富度较 Notion 有差距。强大且成熟的数据库系统。能满足基础的看板Kanban、表格管理需求适合轻量级项目跟踪。协作功能实时协作。基于 CRDT 技术支持多用户同时编辑同一页面。实时协作。满足小型团队的协同编辑需求是开源工具中协作体验的佼佼者。白板功能集成白板 (Edgeless Mode)。可以在页面中嵌入无限画布自由放置文本、形状、便签、连接线。需集成 Miro 等第三方工具。将结构化笔记与自由绘图结合适合头脑风暴、架构设计、流程图绘制。开源与可扩展MIT 协议开源。代码完全公开可自行修改、二次开发或集成。闭源。拥有最高程度的自由可以根据自身业务需求进行深度定制。成本免费。部署所需的服务器资源成本自担。个人免费团队及高级功能付费。长期使用成本可控尤其对于团队避免了按人头付费的持续支出。从表格可以看出AFFINE 的核心优势在于“控制权”和“流畅性”。它的短板则在于生态成熟度比如模板市场、第三方集成、移动端体验目前主要通过网页适配等方面尚在发展初期。2.2 技术架构浅析与选型考量理解 AFFINE 的架构有助于我们做出更合理的部署决策。AFFINE 是一个前后端分离的现代化 Web 应用。前端基于React和TypeScript构建提供了我们直接交互的块编辑器和白板界面。后端核心是Node.js服务。它处理用户认证、文档的实时同步与持久化。数据同步与存储这是 AFFINE 的精华所在。它采用CRDT (无冲突复制数据类型)作为底层同步算法。这意味着当你在设备A上编辑一段文字同时在离线状态的设备B上编辑另一段重新联网后两边的更改可以自动、无冲突地合并无需人工解决版本冲突。数据最终持久化到IndexedDB (浏览器端)和你部署的后端存储中。部署形态AFFINE 提供了两种主要形态桌面客户端直接下载安装开箱即用数据默认存储在本地。适合纯个人、单机使用。自托管服务通过 Docker 或直接运行 Node.js 服务部署到一个可通过网络访问的服务器上。这是实现团队协作、多设备同步和真正私有化的必由之路。注意AFFINE 仍处于快速迭代阶段本文基于其稳定版本撰写。这意味着新功能会不断加入但偶尔也可能遇到小问题。将其用于核心生产环境前建议先在小范围或非关键项目中试用。3. 部署方案全解析从桌面版到云端服务器部署是使用 AFFINE 的第一步也是决定其可用性、稳定性和协作能力的关键。我将从最简单到最复杂逐一分析每种方案的适用场景、优缺点和核心步骤。3.1 方案一桌面客户端最快上手这是体验 AFFINE 核心功能最快捷的方式适合个人用户快速尝鲜。适用场景个人笔记、离线写作、快速体验 AFFINE 编辑器。优点一键安装无需配置完全离线性能最佳。缺点数据仅限单机无法多设备同步无法团队协作。操作步骤访问 AFFINE 官网的 Releases 页面。根据你的操作系统Windows, macOS, Linux下载对应的安装包。像安装普通软件一样完成安装并启动。首次启动会创建本地数据仓库之后即可开始使用。实操心得桌面版的数据存储路径通常位于用户目录下的 AppData 或应用支持目录中。定期备份这个目录就等于备份了你的全部笔记。对于开发者还可以通过命令行参数指定自定义的数据存储路径。3.2 方案二Docker 部署推荐兼顾简便与灵活Docker 是当前自托管服务的主流选择它能将应用及其依赖环境打包实现“一次构建处处运行”极大简化了部署和迁移的复杂度。适用场景个人在多设备间同步、小型团队协作、希望长期稳定私有化部署。优点环境隔离部署简单升级和迁移方便社区支持好。缺点需要基础的 Docker 知识需要一台长期运行的服务器。前置准备一台服务器云服务器、家庭NAS、旧电脑均可安装好 Docker 和 Docker Compose。一个域名可选但推荐用于提供固定的访问地址。如果对外网开放建议配置 SSL 证书HTTPS。3.2.1 使用 Docker Compose 一键部署这是最优雅的部署方式通过一个docker-compose.yml文件定义所有服务。创建部署目录在服务器上创建一个目录例如~/affine并进入。mkdir -p ~/affine cd ~/affine编写docker-compose.yml文件使用文本编辑器创建该文件。version: 3.8 services: affine: image: ghcr.io/toeverything/affine-self-hosted:latest container_name: affine restart: unless-stopped ports: - 3000:3000 # 主机端口:容器端口 environment: - AFFINE_SERVER_PORT3000 - AFFINE_SERVER_HOST0.0.0.0 # 以下为数据库配置使用内置SQLite可忽略如需使用PostgreSQL请配置 # - DATABASE_URLpostgresql://username:passwordpostgres:5432/affine volumes: - ./data:/app/data # 将容器内数据持久化到主机 # 如果使用独立PostgreSQL取消注释以下部分 # depends_on: # - postgres # networks: # - affine-network # PostgreSQL 数据库可选用于生产环境 # postgres: # image: postgres:16-alpine # container_name: affine-postgres # restart: unless-stopped # environment: # POSTGRES_USER: affine # POSTGRES_PASSWORD: your_strong_password_here # POSTGRES_DB: affine # volumes: # - ./postgres_data:/var/lib/postgresql/data # networks: # - affine-network # 如果启用PostgreSQL取消注释 # networks: # affine-network: # driver: bridge这个配置做了几件关键事拉取最新官方镜像将容器的3000端口映射到主机的3000端口设置了自动重启策略并通过volumes将应用数据挂载到主机的./data目录防止容器删除后数据丢失。启动服务docker-compose up -d执行后Docker 会拉取镜像并启动容器。使用docker-compose logs -f可以查看实时日志确认启动无误。访问服务在浏览器中访问http://你的服务器IP:3000。你应该能看到 AFFINE 的欢迎界面。重要提示默认配置使用了内置的 SQLite 数据库这对于个人或小团队初期完全够用。但如果预期有频繁的协作或大量数据建议启用配置中注释掉的 PostgreSQL 部分以获得更好的并发性能和可靠性。只需取消相关注释设置一个强密码并创建对应的数据卷目录如./postgres_data即可。3.2.2 使用反向代理Nginx与 HTTPS直接通过 IP 和端口访问既不安全也不方便。我们通常使用 Nginx 或 Caddy 作为反向代理并配置 HTTPS。安装 Nginx如果尚未安装# Ubuntu/Debian sudo apt update sudo apt install nginx # CentOS/RHEL sudo yum install nginx申请 SSL 证书可以使用 Let‘s Encrypt 的 certbot 工具免费申请。sudo apt install certbot python3-certbot-nginx # Ubuntu/Debian sudo certbot --nginx -d your-domain.com # 替换为你的域名按照提示操作certbot 会自动修改 Nginx 配置并安装证书。配置 Nginx 反向代理编辑 Nginx 站点配置文件如/etc/nginx/sites-available/affine。server { listen 80; server_name your-domain.com; # 你的域名 return 301 https://$server_name$request_uri; # 强制跳转HTTPS } server { listen 443 ssl http2; server_name your-domain.com; ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem; # 其他SSL优化配置... location / { proxy_pass http://localhost:3000; # 指向Docker容器的端口 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; # 以下配置对WebSocket支持很重要用于实时协作 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 86400; # 长连接超时设置 } }启用配置并重启 Nginxsudo ln -s /etc/nginx/sites-available/affine /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置语法 sudo systemctl reload nginx现在你就可以通过https://your-domain.com安全地访问你的私有 AFFINE 了。踩坑记录最初部署时我忽略了 Nginx 中关于 WebSocket 的配置Upgrade和Connection头导致实时协作功能无法正常工作。页面可以打开但多人同时编辑时看不到彼此的光标和更改。这是部署协作类 Web 应用时需要特别注意的一点。3.3 方案三从源码构建与部署适合开发者如果你想紧跟最新开发进度、进行二次开发或深度定制从源码构建是唯一途径。适用场景开发者贡献代码、测试最新特性、进行定制化开发。优点完全掌控代码可定制任何部分。缺点步骤繁琐对环境依赖要求高稳定性可能不如发布版。简要步骤克隆仓库git clone https://github.com/toeverything/AFFiNE.git安装依赖项目采用 pnpm 作为包管理器需全局安装pnpm然后在项目根目录运行pnpm install。环境配置复制环境变量示例文件并配置数据库连接等。构建与启动开发模式pnpm dev会同时启动前端和后端开发服务器。生产构建运行pnpm build然后pnpm start。部署将构建生成的dist目录前端和启动好的 Node.js 服务通过 PM2 等进程管理工具部署到生产服务器。个人建议对于绝大多数用户Docker 部署是最佳平衡点。它屏蔽了环境差异提供了标准化的运行方式且官方镜像更新及时。除非你有明确的开发需求否则不建议从源码开始。4. 核心使用教程从入门到精通成功部署后我们终于可以进入 AFFINE 的世界了。它的界面设计简洁对于 Notion 用户来说几乎可以无缝切换。但一些细节和高级功能仍需探索。4.1 工作空间与页面管理首次进入 AFFINE你会创建一个“工作空间”Workspace。你可以把它理解为一个顶级的笔记本或项目集合。创建页面点击侧边栏的 “” 号或使用快捷键Ctrl/Cmd N。页面是内容的载体。页面组织AFFINE 采用“无限层级”的页面嵌套。你可以在一个页面内通过输入/并选择 “Page” 来创建子页面。这种层级关系会清晰地展示在左侧的页面树Page Tree导航中。两种视图模式这是 AFFINE 的特色。页面模式 (Page Mode)传统的线性文档编辑视图专注于写作和结构化记录。无边模式 (Edgeless Mode)点击页面顶部的“无穷大”图标切换。这是一个自由画布你可以将任何内容块文本、形状、图片随意拖放、缩放、连接非常适合做思维导图、项目规划图或架构草图。两种模式下的内容是互通的。实操技巧善用“模板”功能。虽然 AFFINE 没有官方的模板市场但你可以在一个页面中设计好常用的结构如会议记录、项目计划、周报然后将其“复制为模板”。新建页面时选择“从模板导入”即可快速复用。4.2 块编辑器的深度使用块编辑器是 AFFINE 的生产力核心。所有内容都由“块”构成。基础块类型文本、标题H1-H3、待办列表、项目符号列表、编号列表、引用块、代码块、分页符等。输入/可以唤出完整的块菜单。高级块与嵌入数据库输入/database可以创建一个新的数据库。你可以选择“表格”或“看板”视图。每个数据库实际上是一个特殊的页面其中的每条记录Row也是一个可以点进去编辑的独立页面。这构成了 AFFINE 知识关联的基础。多媒体支持直接拖拽或粘贴图片、PDF、视频支持嵌入在线视频链接。文件会上传到你部署的后端。公式支持 LaTeX 语法输入/math即可插入。Mermaid 图表这是一个杀手级功能输入/mermaid可以直接用代码绘制流程图、时序图、甘特图等。这对于技术文档撰写者来说极其方便。块操作拖拽鼠标悬停在块左侧的“抓手”图标上可以拖动块来调整顺序或层级缩进。转换选中文本或块弹出的浮动工具栏或右键菜单可以快速转换块类型如将普通文本转为待办事项。引用与提及输入可以提及一个页面或一个日期创建内部链接。输入[[可以快速搜索并链接到已有页面。避坑指南在协作编辑时尽量避免多人同时操作同一个“块”的内部结构比如同时修改同一个列表项的不同部分。虽然 CRDT 能处理大部分合并但复杂操作仍可能导致意外的格式错乱。建议的协作模式是各自负责不同的页面或同一页面的不同章节块。4.3 数据库功能实战数据库是构建个人或团队知识系统的骨架。AFFINE 的数据库目前虽然不如 Notion 强大但已具备核心功能。创建与属性定义新建一个数据库后点击表格视图顶部的 “” 添加列。支持的属性类型包括文本、数字、单选标签、多选标签、日期、人员、文件、复选框、URL 等。合理定义属性是高效检索和筛选的关键。视图管理同一个数据库可以拥有多个视图。例如你可以创建一个“表格视图”来总览所有条目再创建一个“看板视图”根据“状态”属性如“待办/进行中/已完成”将条目可视化。每个视图的筛选、排序和分组规则都是独立的。关联页面数据库的每一行都可以点开成为一个完整的页面。你可以在里面添加详细的描述、子任务、相关资料等。这种“数据库行即页面”的设计使得概览和细节可以完美结合。筛选与查询在视图顶部可以添加筛选器例如“标签包含‘重要’且截止日期在今天之后”。这能帮你快速聚焦于当前最重要的任务。性能心得当单个数据库内条目过多例如超过1000条时在前端进行复杂筛选和排序可能会感到卡顿。建议通过创建多个更具体的数据库或者利用标签进行粗粒度分类来避免单个数据库过于臃肿。4.4 协作与分享设置AFFINE 的协作体验是其作为 Notion 替代品的重要一环。邀请成员在工作空间左侧栏底部点击“邀请”图标输入被邀请人的邮箱目前需要对方也使用 AFFINE 并验证邮箱。被邀请者会收到通知接受后即可加入该工作空间。权限控制目前版本的权限系统相对简单主要是“成员”角色拥有对工作空间内所有页面的编辑权限。更细粒度的页面级权限可能在后续版本中完善。实时协作成员加入后打开同一页面即可看到彼此的实时光标和编辑内容。所有更改会自动保存和同步。页面分享你可以将任何一个页面发布到网上生成一个公开的只读链接。点击页面右上角的“分享”按钮开启“发布到网络”即可。这对于撰写博客、发布公开文档非常有用。5. 数据备份、迁移与高级维护将核心知识资产放在自托管服务上备份是重中之重。同时你也可能需要在不同实例间迁移数据。5.1 数据备份策略AFFINE 的数据主要分为两部分应用数据包括页面内容、块数据、用户信息等存储在数据库SQLite/PostgreSQL中。上传的媒体文件图片、PDF等默认存储在服务器文件系统的指定目录Docker 部署中我们挂载的./data卷里的uploads子目录。全量备份方案基于 Docker Compose备份非常简单就是备份整个./data目录和docker-compose.yml文件。# 进入部署目录 cd ~/affine # 停止服务确保数据一致性 docker-compose down # 打包备份 tar -czvf affine-backup-$(date %Y%m%d).tar.gz data/ docker-compose.yml # 重新启动服务 docker-compose up -d将生成的.tar.gz文件传输到安全的异地存储如另一台服务器、云存储。基于 PostgreSQL如果使用了独立的 PostgreSQL需要额外备份数据库。# 进入PostgreSQL容器执行导出 docker exec affine-postgres pg_dump -U affine affine affine-db-backup-$(date %Y%m%d).sql然后将这个 SQL 文件一并加入备份包。自动化备份可以编写一个简单的 Shell 脚本结合cron定时任务实现每日自动备份并清理旧文件。#!/bin/bash BACKUP_DIR/path/to/your/backup DEPLOY_DIR/home/yourname/affine cd $DEPLOY_DIR docker-compose down tar -czvf $BACKUP_DIR/affine-$(date \%Y\%m\%d).tar.gz data/ docker-compose.yml docker-compose up -d # 保留最近7天的备份 find $BACKUP_DIR -name affine-*.tar.gz -mtime 7 -delete5.2 数据迁移与恢复从备份恢复在新服务器上安装好 Docker 和 Docker Compose。将备份的tar.gz文件解压到一个新目录。确保docker-compose.yml中的配置特别是端口和卷路径符合新环境。运行docker-compose up -dAFFINE 就会带着所有数据和文件原地复活。从 Notion 迁移目前 AFFINE 没有提供官方的 Notion 导入工具。社区有一些第三方脚本或工具尝试解决但都不完美。最可靠的方式仍然是手动复制粘贴或者先导出 Notion 为 Markdown再导入到 AFFINE。AFFINE 对 Markdown 的兼容性相当不错能较好地保留标题、列表、代码块等基础格式。5.3 性能监控与优化随着使用深入你可能需要关注服务的健康状况。资源监控使用docker stats affine可以查看容器的 CPU、内存使用情况。如果内存占用持续过高可以考虑为 Docker 容器设置资源限制在docker-compose.yml中添加mem_limit。日志查看docker-compose logs -f affine是排查问题的第一现场。关注是否有频繁的错误或警告信息。升级版本AFFINE 更新活跃。升级前务必先进行完整备份。升级步骤通常很简单cd ~/affine docker-compose down docker-compose pull # 拉取最新镜像 docker-compose up -d如果docker-compose.yml有版本更新需要先对照官方仓库的更新说明进行调整。6. 常见问题与故障排查实录在实际部署和使用中你几乎一定会遇到下面这些问题。这里是我和社区遇到的一些典型情况及其解决方案。6.1 部署阶段问题Q1: 访问http://ip:3000显示 “无法连接” 或 “连接被拒绝”。检查防火墙确保服务器安全组或本地防火墙放行了 3000 端口。例如在 Ubuntu 上sudo ufw allow 3000。检查容器状态运行docker-compose ps确认affine容器的状态是 “Up”。如果不是运行docker-compose logs affine查看错误日志。常见原因是端口冲突尝试修改docker-compose.yml中的主机端口映射如改为- 8080:3000。检查镜像拉取首次运行docker-compose up -d可能因为网络问题拉取镜像失败。可以尝试手动拉取docker pull ghcr.io/toeverything/affine-self-hosted:latest。Q2: 页面可以打开但实时协作多人光标不生效。这是 WebSocket 问题99% 的原因出在反向代理配置。请严格按照本文 3.2.2 节中 Nginx 的配置确保包含了proxy_set_header Upgrade和proxy_set_header Connection upgrade;这两行。配置修改后务必重载 Nginx。检查 Docker 网络如果你使用了自定义的 Docker 网络确保 Nginx 容器和 AFFINE 容器在同一个网络中或者 Nginx 能正确解析到 AFFINE 容器的服务名。Q3: 上传图片或文件失败。检查存储卷权限Docker 容器内的进程通常以非 root 用户运行。确保主机上挂载的./data目录对 Docker 进程是可写的。可以尝试chmod -R 755 ./data或chown -R 1000:1000 ./data1000 是常见的容器内用户UID。检查磁盘空间使用df -h命令查看服务器磁盘是否已满。6.2 使用阶段问题Q4: 页面加载速度慢特别是数据库条目多的时候。前端优化AFFINE 作为富前端应用首次加载资源较多。确保服务器带宽足够并可以考虑配置 Nginx 开启 gzip 压缩静态资源。数据库优化如果使用 SQLite 且数据量大可以考虑迁移到 PostgreSQL。SQLite 在并发写入和高负载查询时性能会下降。客户端缓存AFFINE 是本地优先首次加载后后续操作会非常流畅。慢主要是初次打开工作空间或页面时的数据同步阶段。Q5: 如何重置管理员密码或处理账户问题目前 AFFINE 的自托管版本第一个注册的用户即为工作空间管理员。如果忘记密码没有直接的图形界面重置。需要通过操作数据库来解决。SQLite备份后使用sqlite3命令行工具打开./data/affine.db找到users表更新对应邮箱用户的password字段密码是加盐哈希过的直接设置新密码很麻烦。更稳妥的方式是如果你知道原密码可以在应用内直接修改。PostgreSQL同理通过psql连接数据库进行操作。强烈建议妥善保管好第一个注册账户的密码或者定期在应用内修改密码。社区正在讨论增加更完善的管理后台。Q6: 移动端体验如何目前 AFFINE 没有原生移动 App。但你可以通过手机浏览器访问部署好的地址。页面针对移动端做了响应式适配基础编辑和查看是可行的但复杂操作如拖拽块、白板绘制体验不如桌面端。可以将网页“添加到主屏幕”获得类似 App 的图标入口。部署和使用 AFFINE 的过程是一个典型的“用可控的复杂度换取完全自主权”的技术决策。它可能不像 SaaS 产品那样开箱即用、无忧无虑你需要扮演一部分运维的角色。但换来的是对自己数据百分百的掌控、无网络焦虑的流畅写作以及一个可以根据社区和自身需求不断进化的工具。对于愿意折腾、重视隐私和长期主义的数字创作者来说这份投入是值得的。我的 AFFINE 实例已经稳定运行了数月它成为了我记录技术思考、规划项目进度的核心枢纽。每当我在断网的高铁上依然能流畅地写下这些文字时都会再次确信这个选择的价值。