前言

在这个数据爆炸的时代,个人数据的价值愈发凸显,成为我们生活与工作中无可替代的重要资产。上一篇文章里,我介绍了从印象笔记迁移至 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. php字符串练习题

    把以前发给别人的练习题邮件备份记录一下 1.用php编写统计二维数组内某个字符出现的次数的一个函数.给定二维数组和字符串,返回这个字符串在二维数组中出现的次数. 例: 数组如下: $array=arr ...

  2. Python:pygame游戏编程之旅三(玩家控制的小球)

    上一节实现了小球自由移动,本节在上节基础上增加通过方向键控制小球运动,并为游戏增加了背景图片. 一.实现: # -*- coding:utf-8 -*- import os import sys im ...

  3. golang之context

    context 用来解决 goroutine 之间退出通知.元数据传递的功能. context 使用起来非常方便.源码里对外提供了一个创建根节点 context 的函数: func Backgroun ...

  4. Django Admin之常用功能汇总

    1.字段支持下拉搜索框 1)在admin中新增字段autocomplete_fields autocomplete_fields = ("field1","field2& ...

  5. mysqldump+binlog备份脚本

    mysqldump是一种逻辑备份工具 , 可以对数据库进行全量备份 , 和binlog增量备份共同使用可以进行数据库备份 , 基于此写了一个备份的脚本 #!/bin/bash all_path=&qu ...

  6. 十、Spring Boot集成Spring Security之HTTP请求授权

    目录 前言 一.HTTP请求授权工作原理 二.HTTP请求授权配置 1.添加用户权限 2.配置ExceptionTranslationFilter自定义异常处理器 3.HTTP请求授权配置 三.测试接 ...

  7. asp.net 简单日志收集

    做开发的都知道,完整的日志记录对问题的解决,回溯是多么的重要,多么的不可缺少. 那么我们怎么记录完整的日志? 今天,我们来说一说问题:从哪里开始记录呢?在哪里保存呢? IHttpModule,这个大家 ...

  8. Konva.js

    1.前言 简介:Konva.js - 适用于桌面/移动端应用的 HTML5 2d canvas 库 个人体验:原生的canvas只支持绘制基本的直线,矩形,文字,图片,扇形等,如果要支持更复杂的功能, ...

  9. u-chart

    1.前言 uni-app能用的图表插件太少,这是唯一能用,虽然官方声称 傻瓜式 配置,但是在我看来异常繁琐,可选的配置项一大堆统统堆到demo里面,导致上手非常困难.既然踩了坑,我就记录下来. 2.基 ...

  10. Qt在linux下实现程序编译后版本号自增的脚本

    #! /bin/bash rm -rf temp.cpp num=0 while read line do if [ $num -eq 3 ];then array=(`echo $line | tr ...