您的当前位置:首页正文

个人数据保全计划:部署joplin server笔记同步服务

2025-02-02 来源:个人技术集锦

前言

在这个数据爆炸的时代,个人数据的价值愈发凸显,成为我们生活与工作中无可替代的重要资产。上一篇文章里,我介绍了从印象笔记迁移至 Joplin 的过程,这是我寻求数据自主掌控的关键一步。在探索同步方案时,我尝试了 OneDrive,原以为它能提供稳定高效的同步服务,可实际使用时却发现它对小文件缺乏优化,同步速度极慢,极大影响了使用体验。虽说目前还不确定是否存在数据丢失问题,但这样的效率实在难以满足我的需求。

于是,我决定深入研究,最终将目光锁定在 Joplin Server 笔记同步服务上。这不仅是一次技术探索,更是构建个人数据保全计划的核心之举。部署专属的 Joplin Server,意味着数据安全将得到更可靠的保障,访问更加便捷,从此彻底告别第三方云服务带来的种种隐患,真正实现个人数据的自主管理与全方位守护。接下来,我就为大家分享这一过程,希望能给同样在数据同步中迷茫的你一些启发。

准备 docker-compose 配置

官网文档:

根据官网文档,我整理了一下 docker-compose 配置

version: '3'

services:
    app:
        image: joplin/server:latest
        ports:
            - "22300:22300"
        restart: unless-stopped
        networks:
            - pgsql
        environment:
            - APP_PORT=22300
            - APP_BASE_URL=${APP_BASE_URL}
            - DB_CLIENT=${DB_CLIENT}
            - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
            - POSTGRES_DATABASE=${POSTGRES_DATABASE}
            - POSTGRES_USER=${POSTGRES_USER}
            - POSTGRES_PORT=${POSTGRES_PORT}
            - POSTGRES_HOST=${POSTGRES_HOST}

networks:
  pgsql:
    external: true

PS:这里我用之前部署好的 PostgreSql 数据库,所以把网络桥接到 pgsql 的网络里

可以看到这个配置里面还有一些环境变量

需要在相同目录下创建一个 .env 文件,内容如下:

DB_CLIENT=pg
POSTGRES_PASSWORD=your_password
POSTGRES_DATABASE=joplin
POSTGRES_USER=joplin
POSTGRES_PORT=5432
POSTGRES_HOST=pgsql

创建数据库

在 PostgreSql 里创建一个数据库给 joplin 用。

创建 joplin 数据库:

在 psql 提示符下,执行:

CREATE DATABASE joplin;

创建 joplin 用户:

执行下面的 SQL 语句,其中 'your_password' 请替换为你希望设置的实际密码:

CREATE USER joplin WITH ENCRYPTED PASSWORD 'your_password';

注:如果希望该用户拥有创建数据库的权限,可以增加 CREATEDB 权限,例如:

CREATE USER joplin WITH ENCRYPTED PASSWORD 'your_password' CREATEDB;

授予 joplin 用户访问 joplin 数据库的权限:

执行:

GRANT ALL PRIVILEGES ON DATABASE joplin TO joplin;

配置QNAP的docker镜像

由于某些不可抗力因素,之前能用的国内docker镜像基本都挂了

我重新找了一个临时能用的(),先凑合着用,不知道啥时候就又停了

需要在 Container Station 里配置一下,(路径:属性 - Registry 服务器)

如果不行的话,可以在这个 gist 里找找有无其他可用镜像:

提取镜像

现在没法搜索镜像了(因为连不上 docker hub)

只能点右上角的「提取」按钮(相当于 docker pull 命令)

然后输入镜像名称 joplin/server

服务器记得选择刚才添加的国内镜像

点击提取,在右上角可以看到进度

配置存储(可选)

默认情况下,项目内容(笔记、标签等)存储在数据库中,无需额外步骤即可使其工作。

然而,由于该内容可能相当大,可以通过设置 STORAGE_DRIVER 环境变量选择将其存储在数据库外部。

继续编辑上面的 .env 文件

STORAGE_DRIVER=Type=Filesystem; Path=/joplin-storage

然后在 docker-compose 里映射一下

volumes:
  - ./storage:/joplin-storage

注意:使用QNAP NAS的话,请自行创建这个目录,让docker自动创建的话这个目录变成了 admin 用户,joplin容器无法访问。

使用 docker-compose 命令启动

QNAP 上的 docker 还是很老的版本

在配置文件所在的目录里执行 docker-compose up 启动

对了,如果还显示无法pull镜像

可以把 image 换成 docker.m.daocloud.io/joplin/server

时间错误问题

我启动的时候遇到以下报错

app_1  | 12:27:17 0|app    | Error: The device time drift is -32027ms (Max allowed: 2000ms) - cannot continue as it could cause data loss and conflicts on the sync clients. You may increase env var MAX_TIME_DRIFT to pass the check, or set to 0 to disabled the check.
app_1  | 12:27:17 0|app    |     at /home/joplin/packages/server/src/app.ts:292:11
app_1  | 12:27:17 0|app    |     at Generator.next (<anonymous>)
app_1  | 12:27:17 0|app    |     at fulfilled (/home/joplin/packages/server/dist/app.js:5:58)
app_1  | 12:27:17 0|app    |     at processTicksAndRejections (node:internal/process/task_queues:95:5)

这个错误提示说明 Joplin Server 在启动时检测到系统时间与预期时间之间存在较大偏差,具体偏差值为 -32027 毫秒(大约 32 秒),而默认允许的最大偏差为 2000 毫秒。这种时间漂移可能会导致同步客户端出现数据冲突或者数据丢失,所以服务出于安全考虑拒绝启动。

我的解决方法是同步 docker 时间+调整时间漂移检查参数

添加以下映射

volumes:
  - /etc/localtime:/etc/localtime:ro

添加以下环境变量

environment:
  - MAX_TIME_DRIFT=40000  # 允许 40 秒的时间漂移

再次启动就正常了

Invalid origin 问题

启动之后,我访问 NAS 上的 22300 端口,却提示 Invalid origin

这问题说难不难,主要是QNAP的反向代理需要再控制面板里面设置,但里面能配置的参数又太少了

看起来 QNAP 内置的 HTTP 服务器是 Apache,我参考了一下 github issues 里相同问题的 Request Header ,还是没解决

一开始我把环境变量设置为 APP_BASE_URL=http://localhost:22300

可以打开管理页面了,但静态资源无法加载

SSH隧道

这时候我想到了万能的 SSH 隧道

我把服务器上的 22300 端口转发到本地访问不就得了?

于是直接本地执行

ssh -L 22300:localhost:22300 用户名@NAS地址

结果提示

channel 3: open failed: administratively prohibited: open failed

很明显这是服务端拒绝了我的端口转发请求

到 NAS 上去检查一下 /etc/ssh/sshd_config 配置文件

发现了这行配置

#AllowTcpForwarding yes

OK,现在把这个注释去掉,重启 SSH 服务就行

不过我在 /etc/init.d/ 下面没找到 SSH 服务

据说使用下面这个命令可以重启全部服务,不过我没有尝试

参考:

/etc/init.d/services.sh restart

我试了下通过 QNAP 管理界面操作:

  • 登录 QNAP 的管理控制台。
  • 前往「控制面板」->「系统设置」->「网络与文件服务」中的「Telnet/SSH」设置页面。
  • 先关闭 SSH 服务,再重新启用,理论上似乎能达到重启服务的效果?

不过尝试之后很遗憾还是不行(摊手)

那就没有静态资源凑合使用吧… (所以说 QNAP 这系统是真的垃圾)

尝试使用 nginx 转发

我尝试了增加一个 nginx 容器做转发

services:
  nginx:
    image: nginx:stable-alpine
    container_name: nginx
    restart: unless-stopped
    networks:
      - default
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    ports:
      - 22380:8000
    depends_on:
      - app

nginx.conf 配置

upstream joplin {
    # 这里要指向 Joplin 容器的内部地址和端口
    server app:22300;
}

server {
    listen 8000;
    server_name joplin.dealiaxy.com;

    charset utf-8;
    client_max_body_size 100M;

    # 关键 CORS 配置
    add_header 'Access-Control-Allow-Origin' "$http_origin" always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
    add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' always;
    add_header 'Access-Control-Allow-Credentials' 'true' always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    if ($request_method = OPTIONS) {
        return 204;
    }

    location / {
        proxy_pass http://joplin;
        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_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Host $host;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server_tokens off;

不过折腾了半天还是没成功

参考:

重新配置QNAP的反向代理

最终还是在QNAP控制台里重新配置代理

把目标从 localhost:22300 改成 domain:22300 才搞定……

登录控制台

输入默认邮箱和密码登录

进入后台之后按照官方的建议选择创建个新用户来同步。

While the admin user can be used for synchronisation, it is recommended to create a separate non-admin user for it. To do so, navigate to the Users page - from there you can create a new user. Once this is done, you can use the email and password you specified to sync this user account with your Joplin clients.

虽然管理员用户可用于同步,但建议为它创建一个单独的非管理员用户。要这样做,请转到“用户”页面 - 从那里您可以创建新用户。完成此操作后,您可以使用您指定的电子邮件和密码将此用户帐户与您的 Joplin 客户端同步。

配置 joplin

在同步菜单里配置我们部署的 joplin server

回到主界面点击左下角的「同步」按钮,搞定!

这次的同步速度确实比OneDrive快多了

同步完成

没多久(十分钟差不多)就跑完了

来到管理后台可以看到已经占用了一些空间

看了下一万多条笔记在数据库里占用2G多的空间,还可以。

PS:介意的话可以单独启动一个数据库来存 joplin 的数据。

Top