关于 AI、软件、系统与持续思考的个人笔记

知乎姨姨

Joplin Server 自建教程:同步电脑和手机上的笔记

用 Docker Compose 部署 Joplin Server 和 PostgreSQL,通过两台设备验证笔记与附件同步,区分 JEX 导出和服务器备份。

文章目录

电脑上写了笔记,手机却迟迟看不到更新,通常需要先分清客户端、网络和同步服务出了什么问题。Joplin Server 提供的是 Joplin 客户端的同步端点。它的网页主要用于账号管理,编辑笔记仍在桌面端或手机端完成。

把服务搬到 VPS,意味着同步地址、数据库和备份由自己维护。开始时用一个测试账号和几条新笔记把流程跑通,比直接迁入多年积累的笔记库更容易发现问题。

数据库与同步服务放在同一个 Compose 项目

以下示例面向已安装 Docker Engine、Compose 和宿主机 Caddy 的 Linux VPS。准备 joplin.example.com 域名并配置 DNS。Joplin 的 APP_BASE_URL 必须与客户端实际访问的 HTTPS 地址一致,本文不使用子目录部署。

Joplin 的服务器同时保存笔记和附件,选 VPS 时要考虑数据库占用、附件增长和设备到服务器的连接。准备新同步实例,可以在雨云查看云服务器配置,优惠码 KuZhuJi。按客户端所在位置选择区域,确认公网访问和 Linux 系统条件,再用少量笔记验证往返同步;同步量小时也可以先复用现有 VPS。

mkdir -p ~/apps/joplin
cd ~/apps/joplin
umask 077
docker pull joplin/server:latest
printf 'JOPLIN_IMAGE=%s\n' "$(docker image inspect --format '{{index .RepoDigests 0}}' joplin/server:latest)" > .env
printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 32)" >> .env
printf 'APP_BASE_URL=https://joplin.example.com\n' >> .env

把 .env 中的域名换成自己的,确认镜像值为 仓库@sha256:…。数据库密码用十六进制随机值,避免连接配置中出现需要额外转义的符号。

保存为 compose.yml:

services:
  db:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_DB: joplin
      POSTGRES_USER: joplin
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?请设置数据库密码}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U joplin -d joplin"]
      interval: 10s
      timeout: 5s
      retries: 10
  app:
    image: ${JOPLIN_IMAGE:?请固定镜像摘要}
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "127.0.0.1:22300:22300"
    environment:
      APP_PORT: 22300
      APP_BASE_URL: ${APP_BASE_URL:?请填写正式访问地址}
      DB_CLIENT: pg
      POSTGRES_HOST: db
      POSTGRES_PORT: 5432
      POSTGRES_DATABASE: joplin
      POSTGRES_USER: joplin
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}

官方配置支持 PostgreSQL,本文保留默认的数据库内容存储,不另外开启文件系统或 S3 存储,也不部署转录服务。数据库没有映射公网端口;应用通过服务名 db 连接它。

docker compose config --quiet
docker compose up -d
docker compose ps
docker compose logs --tail=100 app db

宿主机 Caddy 的站点配置:

joplin.example.com {
    reverse_proxy 127.0.0.1:22300
}

域名、80 和 443 端口以及证书签发条件都准备好后,验证并重载 Caddy。若使用容器内代理,应改用共同 Docker 网络中的服务名,不能把宿主机的 127.0.0.1 配置直接套进去。

先改管理员凭据,再给客户端建立普通账号

首次开放域名时,先在反向代理限制到自己的来源 IP。按当前服务器登录页和官方安装说明完成管理员登录,立即修改初始凭据,再调整正式访问范围。不要把管理员账号作为所有设备的日常同步账号;新建一个普通用户,使用它配置 Joplin 客户端的“Joplin Server”同步目标。

客户端填写同一个 HTTPS 地址及用户邮箱、密码,先运行连接检查,再同步一条带唯一标题的测试笔记。增加一个小附件后,在另一台设备用同一用户同步,确认标题、正文和附件均出现。随后从第二台设备改一句话,让第一台设备再次同步。

这个往返过程能检查写入、下载和更新。只看到登录页面,或客户端只显示一次“同步完成”,都不足以说明整个笔记库可以迁移。

如果出现 Invalid origin,优先检查 APP_BASE_URL 的协议、域名和端口是否与访问地址一致,代理是否保留正确的 Host。修改 .env 后执行 docker compose up -d 重建应用;单纯 restart 不会应用新的环境变量。

同步、客户端导出和服务器备份各自解决什么

同步会传播修改和删除。如果某台设备误删内容,删除也可能进入服务器和其他客户端。迁移前保留客户端 JEX 导出,服务器端则保存完整数据库备份,两者不要互相替代。

默认存储模式下,笔记和附件内容位于数据库。可以短暂停止应用写入,再导出:

mkdir -p backups
umask 077
docker compose stop app
docker compose exec -T db pg_dump -U joplin -d joplin -Fc > "backups/joplin-$(date +%Y%m%d-%H%M%S).dump"
docker compose start app

确认命令成功、文件非空,并用 pg_restore -l 检查归档可读。还要保存 .env、Compose、代理配置与镜像摘要。如果以后启用文件系统或对象存储,备份范围随之增加,数据库导出不再包含全部内容。

恢复到隔离实例时,先使用原来的 PostgreSQL 主版本和 Joplin 镜像,将归档导入空数据库,再验证账号、笔记和附件。给测试实例配置独立地址,不要让日常客户端误连过去。升级数据库主版本必须单独安排迁移,不能把 postgres:16 改成更高版本后继续挂载同一数据目录。

服务部署与存储方式见 Joplin Server 官方安装说明,环境变量与数据库配置可对照 官方 Compose 示例。

继续阅读 · 自托管 返回顶部