事情源自我和 Kevin 一起整理特性测试文档,为了减少重复劳动, Kevin 找到了一个在线合作编写 markdown 文档的网站 HackMD 。这个网站具有最长 100000 字符的文档大小限制,由于文档中有多个巨大的表格,配合自带的自动代码整理功能,轻轻松松超过了大小上限。文档编写完毕后, Kevin 发现了这个玩意还有开源版本 CodiMD,便尝试搭建。

CodiMD 本身是 HackMD 官方开源的,是 HackMD 功能的一个子集。官方提供了方便部署的 docker 镜像,但是其依赖的 nodejs 版本高达 12 。而我是属于不太喜欢使用容器部署的,所以这个 nodejs 版本就显得比较膈应人。我也不太会 node ,所以万般无奈下部署了最新的 release 2.4.2 ,其依赖 nodejs 10-12 ,用 node 10 跑基本功能都是可以正常部署运行的。但是我并不满足,毕竟其 develop 分支已经将 node 版本更新到 14 ,结果没想到整个图片上传的功能都是坏的,这就进入了紧张刺激的调试模式……明明连 javascript 都完全不会的说!

数据库

我在 Debian 12 上使用 postgresql 作为 CodiMD 的数据库,整个配置过程就直接粘贴在下面了,毕竟距离最初的部署尝试已经过去了一个月。

# 安装 pgsql
$ sudo apt-get install postgresql

# 对 pgsql 进行一个配置
$ export PATH=/usr/lib/postgresql/15/bin/:$PATH
$ sudo mkdir  /usr/local/pgsql
$ sudo chown postgres /usr/local/pgsql
$ sudo -u postgres initdb -D /usr/local/pgsql/data
$ sudo vim /usr/local/pgsql/data/postgresql.conf   # port = 50025

# 停止它并编辑 systemd daemon
$ sudo systemctl stop postgresql
$ cat /usr/lib/systemd/system/postgresql.service

[Unit]
Description=PostgreSQL RDBMS
Documentation=man:postgres(1)

[Service]
Type=notify
User=postgres
ExecStart=/usr/lib/postgresql/15/bin/postgres -D /usr/local/pgsql/data
ExecReload=/bin/kill -HUP $MAINPID
KillMode=mixed
KillSignal=SIGINT
TimeoutSec=0

[Install]
WantedBy=multi-user.target

# 重载 daemon 后启动并启用 pgsql
$ sudo systemctl daemon-reload
$ sudo systemctl start postgresql
$ sudo systemctl enable postgresql

# 建立数据库
$ sudo -u postgres psql
psql (15.3 (Debian 15.3-0+deb12u1))
Type "help" for help.

postgres=# create user codimd with password 'codimd-db.';
CREATE ROLE
postgres=# create database codimd owner codimd;
CREATE DATABASE
postgres=# grant all privileges on database codimd to codimd;
GRANT
postgres=#

# 验证使用本地端口是可以正常连接的
$ psql -U codimd -d codimd -p 50025
psql (15.3 (Debian 15.3-0+deb12u1))
Type "help" for help.

codimd=>

CodiMD 2.4.2

图片上传功能我使用的是 IBM 的免费对象存储, 25G 足够用了吧。在使用默认配置文件的情况下,可以用环境变量代替配置文件方便部署时进行参数调试,具体环境变量描述请参考文档,一个参考命令行如下。

$ CMD_HOST="127.0.0.1" CMD_PORT=50035 CMD_URL_PATH= CMD_URL_ADDPORT=false CMD_PROTOCOL_USESSL=false CMD_USECDN=true CMD_DB_URL="postgres://codimd:codimd-db.@localhost:50025/codimd" CMD_IMAGE_UPLOAD_TYPE=s3 CMD_S3_REGION=cn-east-2 CMD_S3_BUCKET=codimd CMD_S3_ENDPOINT="https://s3-cn-east-2.qiniucs.com" CMD_S3_ACCESS_KEY_ID="access-key-id" CMD_S3_SECRET_ACCESS_KEY="sec-access-key-id" CMD_SESSION_SECRET="youmu-secret" /opt/node-v10.24.1-linux-x64/bin/node app.js

这个参考命令使用的域名是七牛云的,但是告诉你由于七牛云的对象存储实现不能完全兼容 s3 ,所以压根没法用。你需要将 s3 相关配置改成你自己用的。软件源中的 nodejs 并不能满足需求,还好从官网下载的二进制 tarball 可以直接扔到 /opt 用的。

验证大致没有问题了,就可以将这些变量写入 config.json ,这个玩意在整个项目的根目录,可以看到有一个叫 config.json.example 的模板。

如果你发现有个啥功能不正常,就需要调试。由于这个项目在服务器运行,没法直接调试,只能通过 ssh 进行端口转发实现用本地浏览器对项目进行断点调试。

# 使用 --inspect 选项进行调试
$ CMD_LOGLEVEL=debug DEBUG=true NODE_ENV=production CMD_CONFIG_FILE=/srv/codimd-2.4.2/config.json /opt/node-v10.24.1-linux-x64/bin/node --inspect app.js

# 进行端口转发
$ ssh -L 9221:localhost:9229 youmu@youmu.love

# 打开 chromium 浏览器并访问
chrome://inspect/
# 理论上你可以在 9229 端口看到一个调试器

node 还会去找一个叫 libssl_conf.so 的链接库,找不到导致 crash 。寻找了一番发现一个别的仓库的 issue 描述了同样的问题,只需要配置一个环境变量即可 OPENSSL_CONF=/etc/ssl ,这可以直接配置在 systemd daemon 中。

CodiMD develop

develop 分支最大的问题就是,图像上传功能整个都是坏的,这源于 node 升到 v14 后, formidable >= 2.0.0 将变量 filepath 改为了 path 并且改变了一些逻辑,导致任何上传的文件都会被认为是不被支持的。这个变动可以在其 changelog 中看到。这意味着除了 s3 ,其他上传方式也都是坏的,而我并不太想修这么多东西,就简单修理了一下 s3 的上传代码,事实证明我修好了它,并且成功部署起来了。关于这些改动,可以在我的 fork 中查看,另外我还将 js 的 cdn 改成了国内的链接来加速加载。

最后给出一个可用的参考 codimd.service

[Unit]
Description=codimd service

[Service]
User=codimd
Group=codimd
#ExecStart=/opt/node-v10.24.1-linux-x64/bin/node /srv/codimd-2.4.2/app.js
ExecStart=/opt/node-v14.21.3-linux-x64/bin/node /srv/codimd-develop-modified/app.js
Environment=NODE_ENV=production
Environment=CMD_CONFIG_FILE=/srv/codimd-develop-modified/config.json
Environment=OPENSSL_CONF=/etc/ssl

[Install]
WantedBy=multi-user.target

by ISCAS weilinfox