背景
Joplin 是一款笔记软件,官网在这,这里就不过多介绍了。它有许多优势,例如
- 开源免费
- 拥有全平台客户端
- 多种同步方式,还可自建服务器(Joplin Server)
- Markdown 语言记录
- 若部署在 Joplin Server 上,可生成外链发布笔记(别人点击链接就可以直接访问)
- 有社区,可开发第三方插件
本教程主要完成的是在 fnos 上使用 docker 进行 Joplin Server 的部署。实际上网上也有挺多相关的教程了,毕竟 docker 的可移植性摆在这里。这里主要分享一下在飞牛上部署的时候遇到的一些坑。
准备工作
首先,都要部署 joplin server 了,估摸着 ddns、公网访问、反向代理这些都玩得差不多了,这里就不再赘述,默认大家都已经能熟练配置了。
这里就假设飞牛的内网 ip 为 192.168.1.100,Joplin Server 的内网端口为 22300。公网 域名为 fn.example.com,欲通过外部端口 23333 来访问 Joplin Server。
Docker 部署步骤
-
镜像仓库先拉取两个镜像,postgres:latest,joplin/server:latest


-
创建 Docker Compose 项目,选择一个项目目录,然后 docker-compose.yml 配置如下,创建后不要立即启动
services:
db:
image: postgres:latest
volumes:
- ./data/postgres:/var/lib/postgresql/data
ports:
- "${POSTGRES_PORT}:5432"
restart: always
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DATABASE}
app:
image: joplin/server:latest
depends_on:
- ${POSTGRES_HOST}
ports:
- "${APP_PORT}:${APP_PORT}"
restart: always
environment:
- APP_PORT=${APP_PORT}
- APP_BASE_URL=${APP_BASE_URL}
- DB_CLIENT=${DB_CLIENT}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DATABASE=${POSTGRES_DATABASE}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PORT=5432
- POSTGRES_HOST=${POSTGRES_HOST}
-
在自己电脑上新建一个 .env 文件,放置自定义变量,重点注意变量 POSTGRES_PORT 不能是 5432,要选一个别的不冲突的端口,比如 5433
APP_BASE_URL=https://fn.example.com:23333
APP_PORT=22300
DB_CLIENT=pg
POSTGRES_PASSWORD=joplinServerPw
POSTGRES_DATABASE=joplinServerDb
POSTGRES_USER=joplin
POSTGRES_PORT=5433
POSTGRES_HOST=db
-
然后把 .env 文件上传到之前选的项目文件夹下,即和 docker-compose.yml 文件在同一目录下(截图里的 data 文件夹是容器运行后生成的)

-
运行 docker compose 项目,会生成两个运行的容器

-
这时候查看 joplin-app-1 的运行日志,如果在 Trying to connect to database... 的后面没有报错,那说明与数据库容器(joplin-db-1)的通信是正常的了

-
稍等一小会,出现这一行时,说明 server 已经初始化完成了

-
如果没出什么问题的话,此时在内网尝试访问 http://192.168.1.100:22300/,会出现下面的情况。这是正常的,因为 joplin server 会校验访问源的网址,必需和 .env 文件中 APP_BASE_URL 一致才行
Invalid origin: http://192.168.1.20:22300
-
此时配置反向代理,将外部访问的流量转发到内部。然后访问 https://fn.example.com:23333 就能出现这样的界面了。至此 server 的部署结束

初始配置
这里简单提两句初始化配置,感觉这部分的教程在网上也挺零散的。
-
首先以管理员身份登陆,默认的用户名为 admin@localhost,密码是 admin
-
进去后点击管理配置,先改个管理员密码,然后点 Users → Add User,创建标准用户

-
这里的操作会有点非常规,主要是因为我们没有对邮件收发相关的服务进行配置。但我们也没必要进行配置,一是个人用的话邮件服务有没有无所谓,二是一般家用的 ip 运营商也不会给你开相关的端口。但是呢,joplin server 新建用户后会给新用户的邮箱发激活邮件,不过也不用担心收不到,因为在管理员账户下是能直接查看到的

-
点进去之后,复制(不要直接点)那个激活链接,点右上角退出管理员账户。新建标签页,粘贴后转到该链接,登陆后就会提示账户激活成功了。
-
最后在客户端的同步设置中,选择同步目标为 Joplin Server (beta) 即可

-
个人觉得最爽的还是这个发布笔记功能,其他同步方式没有,Joplin Server 独占

注意事项
- yml 文件中,db 服务映射到外部的端口默认为 5432,会冲突,导致数据库容器启动不了,需要修改。但是 joplin-app-1 与 joplin-db-1 这两个容器通信时是通过新创建的 docker 内部网络通信的,所以不能把 yml 文件中 app 服务下的 POSTGRES_PORT 给改了,改了反而通信不了
- 我是用 iStoreOS 下安装 nginx 的方式进行反代配置,刚配置完后同步时出现了 ssl 证书错误,排查下来发现是 joplin 对证书链的完整性要求比较严格,反代时 ssl 证书要加载 fullchain 才行
# 加载单证书不够
# ssl_certificate /etc/acme/fn.example.com_ecc/fn.example.com.cer;
# 加载单证书,且添加 ssl_trusted_certificate 也不行
# ssl_certificate /etc/acme/fn.example.com_ecc/fn.example.com.cer;
# ssl_trusted_certificate /etc/acme/fn.example.com_ecc/ca.cer;
# 得要加载 fullchain 才行
ssl_certificate /etc/acme/fn.example.com_ecc/fullchain.cer;
- 另外 nginx 反代时,若改写了 header,不要把 port 丢了
# 这样的配置同样会出现 Invalid origin
# proxy_set_header Host $host;
# 这样才行
proxy_set_header Host $host:$server_port;
- 为了保证 fnos 开机后能自动启动 joplin server,需要把容器的重启策略改成 restart: always,unless-stopped 目前没用
- joplin server 支持的可同步附件大小不能超过 250 MB,似乎是 postgres 的限制,我没细研究了,相关讨论在这