
家里笔记本电脑、办公室台式机、手机上的笔记软件装了四五套数据东一份西一份真要找点东西还要靠微信“文件传输助手”中转。后来狠下心把所有笔记统一迁到一套自托管方案上——Joplin Joplin Server。这套组合的好处是笔记数据完全握在自己手里同步走自己的服务器端到端加密也开着跨平台客户端覆盖 macOS、Windows、Linux、iOS、Android。这篇文章就完整记录我自己从零搭建到日常维护的过程包括部署参数、踩坑记录、备份策略尽量做到照着操作就能复现。Joplin 本身是一个开源笔记应用主打 Markdown 编辑内置端到端加密。Joplin Server 是官方推出的同步服务端专门用来替代第三方的同步存储比如各类云盘、WebDAV 服务核心价值在于你掌握了同步链路的全部环节数据不再经过第三方存储服务。如果你对笔记数据比较敏感或者经常在多个设备之间切换工作这套方案的最大意义就是“同步稳定 数据可控 离线可用”而不是为了追求折腾的快感。1. 为什么非要有自己的笔记服务1.1 从一次数据丢失说起我之前用某云笔记软件用了三年多某天突然提示格式不支持、部分笔记打不开客服反馈是数据库损坏恢复无果。里面存了大量工作相关的技术文档、会议记录、随笔虽然不是全部无法找回但那种“数据不在自己手里”的无力感确实让人后怕。从那以后我给自己定了一条规矩重要的数据必须落在自己能掌控的存储环境里。笔记作为日常输入输出最频繁的数据自然第一时间纳入改造范围。市面上主流的笔记工具可以分成三类纯本地笔记、第三方云同步笔记、自托管同步笔记。纯本地方案比如纯本地 Markdown 文件夹完全没有跨设备能力不符合实际使用场景第三方云同步虽然省事但你不知道数据副本存在哪儿也不知道服务商哪天变更策略自托管则介于两者之间既有云同步的便利又把数据主权攥在自己手里。Joplin 的定位正好合适。它本身是开源软件数据以纯文本 Markdown 资源附件的形式存储在本地既可以用自带同步器对接多种后端也可以干脆直接拿目录当文件管理用。配合 Joplin Server等于同时解决了“同步能力”和“数据归属”两个核心问题。1.2 同步后端方案横向对比在选定 Joplin Server 之前我把 Joplin 支持的几种同步方式挨个理了一遍下面这个表格是我当时的真实对比记录。同步方式数据链路维护成本速度体验稳定性官方 Joplin CloudJoplin 官方服务器零维护较快稳定第三方 WebDAV云盘或自建 WebDAV视服务而定一般一般对象存储S3/MinIOS3 兼容服务中等较快稳定Joplin Server自建自己的服务器中等取决于服务器稳定文件系统 / 手动同步本地 / U盘 / Syncthing低较慢不稳定Joplin Cloud 虽然省事但数据仍然在别人手里而且免费额度有限对重度用户来说空间是个问题。第三方 WebDAV 方案最麻烦的地方在于Joplin 客户端要维护多设备间的数据一致性依赖服务端正确处理 PUT/DELETE 请求有些云盘的 WebDAV 实现并不完整偶尔会出现“数据库不一致”的提示。对象存储方案门槛稍微高一点配置轮询、分片策略还要额外处理订阅通知普通用户没必要上来就选这条路。所以综合来看Joplin Server 是自托管需求下的最优解。它官方维护协议天然匹配客户端逻辑部署形态又是轻量级服务跑在低配服务器上也能轻松胜任。2. 部署前的关键准备2.1 硬件要求与操作系统选择很多人的直觉是“自建服务必须有一台高配服务器”实际上 Joplin Server 远没有那么吃资源。它本质上是 Node.js 写的后端服务数据库默认可以用 SQLite对内存和 CPU 的要求都很低。我目前跑在一台 1 核 1G 内存的服务器上系统是 Ubuntu 22.04 LTS还同时跑着 Nginx 反向代理日常内存占用稳定在 400MB 左右完全够用。硬件选型时注意几个点CPU单核就够。笔记同步本身不是计算密集型任务。内存服务器空闲内存低于 512MB 时建议加一下 swap避免构建或并发同步时 OOM。磁盘取决于笔记总量。纯文本 Markdown 占用极小但如果你习惯大量粘贴图片附件体积会慢慢涨上来。建议预留 20GB 以上空间。网络带宽建议 4Mbps 以上。同步体验差距主要在这里带宽太低的话单次全量同步会很痛苦。操作系统我推荐 Debian 系理由是 Docker 安装、防火墙配置、Let‘s Encrypt 证书申请都有大量现成资料可查遇到问题好搜。理论上 Joplin Server 可以裸机部署但强烈建议用 Docker Compose 来管升级回滚都省事。2.2 域名与反向代理我第一次部署时图省事直接通过 IP 端口访问。用了几天就发现问题Joplin 客户端配置同步时要求填写完整 URLIP 地址一旦变更就要重新配置所有设备另外自签 HTTPS 证书在移动端非常折腾iOS 和部分 Android 版本对自签证书不友好用手机会话登录Joplin Server 支持邮箱验证登录时浏览器经常拦截证书告警。所以如果你希望长期稳定使用建议提前准备一个域名并用 Nginx 或 Caddy 做反向代理和 HTTPS 终结。我当时为 Joplin Server 规划了以下网络结构用户设备 - 域名joplin.yourdomain.com - 443端口HTTPS - Nginx - 本机22300端口Joplin ServerJoplin Server 默认监听 22300 端口Nginx 收到 80/443 的请求后转发到 22300。HTTPS 证书用 Let‘s Encrypt 免费申请就好。如果你不想单独维护 Nginx 和证书直接用 Caddy 会自动申请证书和反代配置文件也更简练我后面会给出一个 Caddy 的替代配置示例。2.3 数据库选型SQLite 还是 PostgreSQLJoplin Server 官方支持 SQLite 和 PostgreSQL。我的建议很简单个人使用、单实例部署直接 SQLite多人协作、高并发、或你对数据可靠性有更高要求选 PostgreSQL。前期我直接用 SQLite 跑了两个月完全没问题。SQLite 单文件形式的备份非常直观只需要把数据库文件复制一份就能完成冷备。后来因为使用频率变高我干脆切到了 PostgreSQL理由主要有两点并发写入能力更强。Joplin Server 的日志记录、会话管理、项目信息都落在数据库里多设备同时同步时 SQLite 偶尔有锁等待。备份工具链更成熟。pg_dump 可以做到一致性备份不必担心冷拷贝时文件被写坏。不过这里也强调一下如果你只是想自己一个人同步若干台设备别因为看了这篇文就盲目上 PostgreSQL。徒增维护成本收益有限。3. 用 Docker Compose 搭建 Joplin Server3.1 核心服务架构与镜像说明Joplin Server 整个服务分为两个进程一个是主服务 joplin-server负责 API、认证、数据读写另一个是数据库服务SQLite 时没有独立进程PostgreSQL 时需要单独的容器。我现在的部署配置由四个服务组成joplin-server主应用postgres数据库nginx反向代理 HTTPSwatchtower可选用于镜像自动更新其中 watchtower 属于个人偏好不是必须组件。如果你偏好手动控制版本变化建议不要启用自动更新避免某个上游版本出现兼容性问题时被被动升级。3.2 编写 docker-compose.yml下面是我当前使用的 docker-compose 配置PostgreSQL 版你直接复制后按需修改环境变量即可version: 3.8 services: db: image: postgres:16-alpine container_name: joplin-db restart: unless-stopped environment: POSTGRES_USER: joplin POSTGRES_PASSWORD: your_strong_password POSTGRES_DB: joplin volumes: - ./data/postgres:/var/lib/postgresql/data healthcheck: test: [CMD-SHELL, pg_isready -U joplin] interval: 10s timeout: 5s retries: 5 app: image: joplin/server:latest container_name: joplin-app restart: unless-stopped depends_on: db: condition: service_healthy environment: APP_BASE_URL: https://joplin.yourdomain.com APP_PORT: 22300 APP_LOGLEVEL: info DB_CLIENT: pg POSTGRES_PASSWORD: your_strong_password POSTGRES_USER: joplin POSTGRES_PORT: 5432 POSTGRES_HOST: db ports: - 127.0.0.1:22300:22300 volumes: - ./data/joplin:/home/joplin nginx: image: nginx:stable-alpine container_name: joplin-nginx restart: unless-stopped depends_on: - app ports: - 80:80 - 443:443 volumes: - ./data/nginx/conf.d:/etc/nginx/conf.d:ro - ./data/letsencrypt:/etc/letsencrypt:ro配置里的几个关键点解释一下APP_BASE_URL必须以 https:// 开头写完整域名Joplin Server 会用它生成回调地址和分享链接。如果这个值和实际访问地址不匹配邮件验证、会话登录都会出问题。我故意没有把 22300 直接暴露到公网而是绑到127.0.0.1。这样 Nginx 才是唯一的外部入口少一个公网暴露面。Postgres 容器没有对外发布端口只在内网通过db主机名互相访问避免数据库端口被乱扫。./data/joplin这个目录用于存放 Joplin Server 的配置、日志、资源文件务必持久化。3.3 Nginx 反向代理配置在./data/nginx/conf.d/下创建joplin.conf写入server { listen 80; server_name joplin.yourdomain.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name joplin.yourdomain.com; ssl_certificate /etc/letsencrypt/live/joplin.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/joplin.yourdomain.com/privkey.pem; client_max_body_size 500M; location / { proxy_pass http://app:22300; 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; } }client_max_body_size要调得足够大否则你粘贴一个几十 MB 的 PDF 或视频附件上传时会直接被 Nginx 拒绝客户端会长时间卡在“上传中”的状态很难排查。如果不想用 NginxCaddy 的配置可以简化成四行joplin.yourdomain.com { reverse_proxy app:22300 }Caddy 会自动申请证书、自动续期对新手相当友好。缺点是国内服务器上 acme 请求偶尔不稳如果遇到证书申请失败大概率要检查 DNS 和防火墙更详细的排查后面会讲。3.4 证书申请与首次启动检查证书申请我习惯先用 Certbot 手动确认一次确认链路通畅后再交给环境自动续期。命令参考apt install certbot certbot certonly --standalone -d joplin.yourdomain.com注意如果 Nginx 已经占用了 80 和 443 端口--standalone方式申请会失败。可以用--webroot模式或者先把 Nginx 停掉再申请申请成功后再启动 Nginx。首次启动前先做一件事防火墙放行端口。ufw allow 80/tcp ufw allow 443/tcp然后启动服务docker compose up -d docker compose logs -f app看到类似Server is now running on port 22300的日志说明服务已经跑起来了。接下来打开https://joplin.yourdomain.com应该能看到 Joplin Server 的登录页面。首次访问时页面会提示没有账户你需要通过注册页创建一个管理员账号。4. 客户端接入与多端同步配置4.1 桌面端 Joplin 配置Joplin 桌面端从官网下载安装即可。首次启动后会进入欢迎向导选择“同步”时不要选默认的“Joplin Cloud”改为“Joplin Server自托管”。需要填写三个关键信息同步目标 URLhttps://joplin.yourdomain.com邮箱你在 Joplin Server 上注册的邮箱密码对应的登录密码填完后点击“Check synchronisation configuration”客户端会发一个请求到服务器验证配置。如果提示成功就直接开始首次同步。首次同步时客户端会创建一份本地数据库的基线快照并上传到服务器笔记量大的话建议在稳定网络环境下执行。配置完成后每次打开 Joplin客户端会自动执行增量同步。我们可以通过菜单“工具 - 选项 - 同步”调整自动同步间隔默认是每 5 分钟一次重度用户也可以改成 1 分钟但会略微增加手机续航压力。4.2 移动端配置移动端的配置流程基本和桌面端一致。iOS 和 Android 的 Joplin App 都支持自托管同步。需要注意的点有两个手机端首次同步内存开销较大如果笔记数量上万条建议确保手机剩余空间充足并连接 Wi-Fi 后再同步。如果之前已经用其它同步方式初始化过记得先在“配置 - 切换同步目标”里切换到 Joplin Server不要直接在旧数据库上做同步否则可能产生冲突文件。移动端的一个便利之处是支持 Web Clipper。把网页剪藏内容发送到 Joplin 时需要通过手机浏览器访问剪藏服务的本地端口。这个功能对做资料收集的朋友来说很实用我自己就有很多技术笔记是用剪藏功能从网页上收集的配合 Markdown 排版比直接拷贝页面要规整得多。4.3 同步状态验证与多设备一致性配置完成后如何确认同步确实在工作我一般用两种方式验证在客户端界面底部查看“已同步”时间戳确认是最新时间。在桌面端新建一条测试笔记写几个字等十几秒后在手机端刷新看能否立刻出现。有一次我发现手机端没有及时出现新笔记刷新也没反应。排查了一圈最后发现是因为手机端剪藏服务占用了 41180 端口而且 Joplin App 在后台的同步开关被系统杀掉了。Android 的电池优化策略对不同 App 影响差别很大解决办法是在系统设置里把 Joplin 的“后台运行”和“省电策略”都设为“不限制”。5. 日常维护、备份策略与问题排查5.1 数据库备份与恢复演练备份是私有云方案里最容易被忽略的部分也是我从一次意外中吸取的教训。某次我在清理服务器时误删了./data/postgres目录要不是提前做了备份几年的笔记数据就全没了。目前我采用的备份策略是每天凌晨 3 点用pg_dump导出数据库全量备份。每周一次把备份文件同步到另一台机器或对象存储。每月手动做一次恢复演练。数据库备份命令docker exec joplin-db pg_dump -U joplin -F c joplin joplin_$(date %Y%m%d).dump恢复命令docker exec -i joplin-db pg_restore -U joplin -d joplin joplin_20250301.dumpBash 脚本简单写出来就是#!/bin/bash BACKUP_DIR/home/backup/joplin DATE$(date %Y%m%d_%H%M%S) mkdir -p $BACKUP_DIR docker exec joplin-db pg_dump -U joplin -F c joplin $BACKUP_DIR/joplin_$DATE.dump find $BACKUP_DIR -name *.dump -mtime 14 -delete这个脚本保留了最近 14 天的备份超过时间自动清理。建议不要只依赖服务器本地备份至少把备份文件同步到一个外部位置。我的做法是定时把$BACKUP_DIR里的文件 rclone 同步到另一个存储空间。5.2 升级注意事项Joplin Server 的发版节奏比较频密我一般保持“滞后一个版本再升级”的习惯。具体操作是先拉取新镜像观察官方 changelog 有没有破坏性变化手动测试后再更新。升级命令很简单docker compose pull app docker compose up -d app但有几个坑要特别注意升级前务必备份数据库。Joplin 在启动时会主动做一次数据库迁移如果迁移中途失败可能需要回滚到升级前的数据库版本。看日志确认启动成功后再切走旧容器。如果服务启动失败可以执行docker compose stop app再换回旧镜像。如果你开了 watchtower 自动更新务必配置只让指定镜像自动更新否则某天上游同步策略变化你甚至不知道是哪次更新带来的问题。5.3 常见问题与排查技巧实录这里我挑几个真实影响体验的问题按频率排序整理成速查表。问题现象可能原因排查思路同步提示“无法连接服务器”域名解析异常 / Nginx 未启动 / 防火墙拦截先curl https://joplin.yourdomain.com看返回再逐段排查 DNS、Nginx、iptables同步到一半提示“数据库已损坏”多设备冲突处理异常 / 旧版本客户端同步状态不一致先备份本地笔记库再清空本地数据库并重新全量同步上传附件超时Nginx 包体大小限制 / 服务器带宽不足检查client_max_body_size或减小单文件体积手机端收不到新笔记系统省电策略杀后台在系统设置中允许 Joplin 后台运行关闭电池优化登录页面能打开但注册不了账号数据库未初始化 / PostgreSQL 连接失败查看docker compose logs app确认 POSTGRES_USER/PASSWORD 与数据库一致客户端配置校验成功但无法同步URL 少了 https / 端口不对确认APP_BASE_URL与客户端填写的 URL 完全一致且不包含路径前缀另外有一个类目中经常被忽略的坑如果你在 Nginx 里开启了 HTTP/2而旧版本 Joplin 客户端对 HTTP/2 的兼容性不是很好可能导致长轮询同步卡住。遇到这种情况可以把 Nginx 配置里的http2暂时去掉试试或者升级客户端到最新版。5.4 关于安全加固的几点补充私有云部署虽然爽但安全问题必须重视。我总结了几条适合个人的安全实践启用 Joplin Server 的“强制 HTTPS”选项确保所有回调地址都是 HTTPS。设置一个复杂的管理员密码同时关闭注册功能如果你只是自己用。Joplin Server 管理后台支持设为“禁止新用户注册”这样别人扫到你的域名也无法创建账号。定期更新系统、Docker 镜像和客户端。如果条件允许在 Nginx 层开启 fail2ban 限制暴力破解登录接口。这个只针对暴露公网的服务如果你只在局域网使用可以跳过。做安全备份时建议把数据库 dump 文件加密后再存放。写个脚本用 gpg 对称加密即可不增加太多维护成本。我自己的部署环境里还额外用了一套监控方案每天检查磁盘使用率和服务存活状态超过 80% 自动发告警邮件。对于个人笔记服务来说这些可能稍微有点“重”但考虑到笔记数据不可再生多做一些保障措施不会错。6. 最后的实用建议与长期使用心得整个 Joplin Joplin Server 方案我用了一年多整体非常满意但有几个体会想特别分享给准备入坑的朋友。第一别一上来就追求“完美架构”。如果你只有一台 Windows 电脑那先在本地装 Docker Desktop 跑起来验证 Joplin 的编辑体验和同步流程再考虑要不要买服务器、搞域名。很多人在构建环境上花了大量精力结果核心的“笔记功能”还没实际用两天热情就被折腾磨没了。第二Joplin 的 Markdown 编辑器体验经过几个大版本迭代已经非常顺手但如果你经常需要插入复杂表格、引用 PDF 内嵌标注它可能不是最佳选择。实话实说Joplin 强在格式标准、数据开放、同步可控弱在富文本排版和 PDF 批注这类封闭生态功能。在选型前先拿一周时间把日常记录习惯模拟一遍看看能不能适应。第三数据库备份不是备了就行要定期演练恢复。我见过不少朋友“备份文件”一大堆真出问题时才发现 dump 文件损坏或者缺依赖。每个月抽 10 分钟在本地新启动一个临时容器把备份文件恢复进去验证一下这笔时间花得非常值。最后再分享一个小技巧如果你有多个设备且某些设备长期离线建议把 Joplin 客户端的“同步间隔”拉长一点或者采用“手动同步 快捷键”的方式。原因很简单每次打开客户端如果都自动全量比对离线上万条笔记的设备会产生大量变更记录同步链路容易卡住。改为手动同步后你可以选择在网络空闲时统一做一次全量更新体验会顺滑很多。私有云笔记这条路核心价值不是技术上的折腾而是把个人知识资产从“平台租赁”变成“自有产权”。从这一天起你写下的每一段文字、收集的每一条资料都可能成为真正伴随你很久的财富。