前言

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

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

准备 docker-compose 配置

官网文档: https://github.com/laurent22/joplin/blob/dev/packages/server/README.md

根据官网文档,我整理了一下 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镜像基本都挂了

我重新找了一个临时能用的(https://docker.m.daocloud.io),先凑合着用,不知道啥时候就又停了

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

如果不行的话,可以在这个 gist 里找找有无其他可用镜像: https://gist.github.com/y0ngb1n/7e8f16af3242c7815e7ca2f0833d3ea6

提取镜像

现在没法搜索镜像了(因为连不上 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 ,还是没解决

https://github.com/laurent22/joplin/issues/6008

一开始我把环境变量设置为 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 服务

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

参考: https://neolee.com/2023/11/05/威联通:重启服务

/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;

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

参考: https://github.com/laurent22/joplin/issues/6350

重新配置QNAP的反向代理

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

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

登录控制台

By default, Joplin Server will be setup with an admin user with email admin@localhost and password admin. For security purposes, the admin user's credentials should be changed. On the Admin Page, login as the admin user. In the upper right, select the Profile button update the admin password.

输入默认邮箱和密码登录

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

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 的数据。

个人数据保全计划:部署joplin server笔记同步服务的更多相关文章

  1. 个人数据保全计划:(2) NAS基础知识

    前言 距离去年国庆入手了NAS至今有好几个月时间了,NAS折腾起来有点麻烦,且实际作用因人而异,并没有想象中的好用,所以说好的这个系列一直没有更新~ 还有另一方面的原因,这些NAS的系统基于Linux ...

  2. 个人数据保全计划:(1) NAS开箱

    前言 从几年前第一个硬盘故障导致参赛的文件丢失之后,我就开始意识到数据安全的重要性,开始用各种云盘做备份,当时还不是百度云一家独大,我们也都没意识到网盘备份是极其不靠谱的行为,直到因为某些不可抗力因素 ...

  3. Rancher Server HA的高可用部署实验-学习笔记

    转载于https://blog.csdn.net/csdn_duomaomao/article/details/78771731 Rancher Server HA的高可用部署实验-学习笔记 一.机器 ...

  4. 三——第二部分——第二篇论文 计划建设SQL Server镜像

    本文接着前面的章节:SQL Server镜像简单介绍 本文出处:http://blog.csdn.net/dba_huangzj/article/details/27203053 俗话说:工欲善其事必 ...

  5. 第三篇——第二部分——第二文 计划搭建SQL Server镜像

    原文:第三篇--第二部分--第二文 计划搭建SQL Server镜像 本文紧跟上一章:SQL Server镜像简介 本文出处:http://blog.csdn.net/dba_huangzj/arti ...

  6. 运维监控-基于yum的方式部署Zabbix Server 4.0 版本

    运维监控-基于yum的方式部署Zabbix Server 4.0 版本 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.如何选择zabbix版本 1>.打开zabbix官方 ...

  7. 微软ASP.NET网站部署指南(2):部署SQL Server Compact数据库

    1. 综述 对于数据库訪问,Contoso University程序要求以下的软件必须随程序一起部署.由于不属于.NET Framework: SQL Server Compact (数据库引擎) A ...

  8. HVR数据复制软件部署之(一)--HUB端部署

    HVR数据复制软件部署之(一)--HUB端部署 本文环境: OS: RHEL5.9 x86-64bit DB: Oracle 12.1.0.2 x86-64bit HVR:highgohvr-4.7. ...

  9. VMware Vsphere 6.0安装部署 vCenter Server安装

    几个不同的组件 vCenter Server:对ESXi主机进行集中管理的服务器端软件,安装在windows server 2008R2或以上的操作系统里,通过SQL 2008R2 或以上版本的数据库 ...

  10. 部署Ambari Server实战案例

    部署Ambari Server实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.准备三台虚拟机(需要自行安装jdk环境) 1>.角色分配 NameNode节点: h ...

随机推荐

  1. 用 300 行代码手写提炼 Spring 核心原理 [3]

    系列文章 用 300 行代码手写提炼 Spring 核心原理 [1] 用 300 行代码手写提炼 Spring 核心原理 [2] 用 300 行代码手写提炼 Spring 核心原理 [3] 上文 中我 ...

  2. ubuntu 安装使用 mytop

    apt搜索一下 $ sudo apt search mytop Sorting... Done Full Text Search... Done mytop/focal,focal,now 1.9.1 ...

  3. Java深度历险(三)——Java线程​:基本概念、可见性与同步

    开发高性能并发应用不是一件容易的事情.这类应用的例子包括高性能Web服务器.游戏服务器和搜索引擎爬虫等.这样的应用可能需要同时处理成千上万个请求.对于这样的应用,一般采用多线程或事件驱动的架构.对于J ...

  4. ClickHouse之基础使用

    [安装] [YUM] 1.添加官方存储库 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://packag ...

  5. vue之项目部署

    一.将vue项目打包同步文件到远程服务器 1. 打包 默认情况下,使用vue-cli创建的项目,package.json里的script应该已经配置了build指令,直接执行yarn build 或者 ...

  6. Java Class 文件中Method的存储

    class文件是java编译后的文件类型.其代表一个类,其有专门的存储格式.其中会存放数据也会存放方法,而所谓的方法存放就是将方法中的调用都转换成java字节码指令.所方法调用从机器的角度看就是对于寄 ...

  7. 【返回值】定义泛型JSON

    /** * 定义统一的Json结构 * 由于封装的Json数据的类型不确定,所以在定义统一的json结构时,我们需要用到泛型. * 统一的json结构中属性包括:数据.状态码.提示信息即可. * 构造 ...

  8. 使用阿里的ARTHAS跟踪方法耗时

    使用命令跟踪一个方法的耗时 在arthas 命令行下输入命令 trace 类全路径 监控的方法 trace com.redxun.bpm.core.service.BpmInstServiceImpl ...

  9. 探索实用的Java工具类

    1.排序 有时需要对集合进行排序.此时可以使用Collections的sort方法. List<Integer> list = new ArrayList<>(); list. ...

  10. COS数据工作流+云函数最佳实践 - 自定义音视频转码

    01 背景 音视频作为信息传播中流量占比最大的部分在各行业的业务中都弥足重要,而不同的业务场景中对音视频的处理逻辑可能具备行业的特殊性. 公有云虽然提供大量的视频处理服务供用户选择,但依然不能做到全面 ...