MENU

【歪门邪道】在纯IPv6服务器上搭建Quassel Core

June 2, 2023 • 瞎折腾

突然想起来我在Hetzner那里还有一台闲置的纯IPv6服务器。想来想去,闲着也是闲着,不如拿来挂IRC。本文记述在这台服务器上搭建Quassel core的艰难坎坷。

太长不看:IPv4的命还长着呢。

IRC

虽然我还年轻,但我觉得IRC这个东西挺酷的。尽管IRC并不是去中心化的,也不能发送文本之外的内容,但它可以self-host啊。如果我没记错的话,能够self host并且能做到不需要购买商业许可的聊天方案里,就只有Element/Matrix和IRC了,其他像是什么Threema OnPerm这些基本都要支付授权费。而即便是现代化的Element/Matrix,我认为在用户体验上也不是很能打IRC。当然,Element/Matrix在功能上更复杂,也更注重安全,同时还能够在不同服务器间互联,但从我的体验来说,Matrix这一套使用下来还是多多少少有一些恼人的Bug,十分影响体验;而IRC赢就赢在了功能简单,虽然打不过Matrix,但用起来没有问题,而且很纯粹。

高情商:纯粹;低情商:简陋。

总之,Matrix我也有在用,但是目前为止我个人更偏向IRC一些。但是IRC有一个致命的缺点,因为他太简单了,服务器甚至不会为你存储消息。也就是说,如果别人发消息时你没在线,那你就收不到消息了。

这里我就不多费笔墨在介绍IRC协议上了。IRC协议作为一个已经发布了35年的经典协议,而且现今仍在使用,我想网络上一定有不少介绍和入门资料。

Quassel

既然IRC服务器不给我们存储消息,那我们就找一个服务器替我们挂机就是了。在众多IRC客户端中,Quassel是一个采用分离结构的IRC客户端。它分为Quassel Core和Quassel Client。其中Core的部分负责与IRC服务器交互,而Client则负责与Core交互。Core会一直在服务器上运行,与IRC服务器保持连接、接收指定频道的消息并将其存储到数据库中。而Client则运行在PC上,与Core交互,接收来自IRC的消息,也可以从数据库中调取以往的消息。

如果你更倾向于在浏览器中使用IRC,你可以尝试诸如Convos等网页客户端。Convos支持在服务端持久化保存收到的消息,同时提供了一个十分易用的网页界面。我个人更喜欢在PC上以应用程序的方式使用IRC,所以我选择Quassel。

安装

废话不多说,我们不妨切入主题,直接说安装的部分。Quassel Core可以在没有任何依赖的情况下独立运行,此时数据存入SQLite数据库。这个数据库对于少量数据还可以应付,如果是长期使用积累下来的IRC消息,在数据量很大的情况下官方也有提示,使用SQLite数据库可能会导致拉取过往消息时出现超时或失败的情况。官方推荐使用PostgreSQL作为数据库。听人劝吃饱饭,我也决定使用PostgreSQL数据库。此外,我还想使用TLS加密Quassel Client与Core之间的通讯,我原本想使用Tailscale,但我又想使用公网访问,想来想去发现Quassel Core没办法在一个端口上提供两个不同的TLS证书,最终还是以公网访问为主,通过增加DNS的A记录指向Tailscale的IP来实现tailscale访问。

具体的安装流程如下:

  1. 安装Docker
  2. 使用Docker安装PostgreSQL
  3. 安装Quassel Core
  4. (在我的电脑上)安装Quassel Client并配置Quassel Core

虽然在Docker中使用PostgreSQL数据库并不是生产环境的最佳实践,但从安全角度来说可能是最方便的。我在映射端口时可以直接把数据库端口映射到127.0.0.1上,而无需使用防火墙或修改数据库配置来实现。数据库的数据会映射到宿主机上,所以完全不需要担心数据丢失的问题。

Docker

我真是万万没想到,安装docker的环节都需要拿来说一下。我的服务器使用的是Ubuntu 2204LTS,安装Docker的过程遵照官方文档就是了,这个没什么可说的。意外发生在安装之后的验证阶段:

docker run hello-world

这一条命令本是用来验证Docker已经安装成功并且能够正常运行的。可是我一个回车按下去,却得到了一行错误:

docker: Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 44.205.64.79:443: connect: network is unreachable.

不知道为什么,Ubuntu上安装docker的默认仓库是registry-1.docker.io,而这个仓库是不支持IPv6访问的,我的服务器又没有v4地址,那肯定会网络不可达。我去网络上搜索了一圈,发现Docker hub其实早就已经支持IPv6访问了。我们只需要修改/etc/docker/daemon.json,将镜像仓库设置为registry.docker.io就好了:

{
  "registry-mirrors": ["https://registry.docker.com"]
}

千万记得前面的https://,不然Docker daemon跑不起来。保存修改后重启Docker服务,再次运行那个命令,就可以看到Docker已经能够正常拉取镜像了。

理论上也可以不进行修改,但每次拉取镜像时就需要指定仓库了:

docker run registry.docker.com/library/hello-world

会显得很麻烦

PostgreSQL

解决了Docker的问题,PostgreSQL就好办了:

docker run -d \
    --name quassel-postgres \
    --restart always \
    -p 127.0.0.1:5432:5432 \
    -e POSTGRES_PASSWORD=【密码】 \
    -e PGDATA=/var/lib/postgresql/data/pgdata \
    -v /var/lib/postgresql/quassel-data:/var/lib/postgresql/data \
    postgres:latest

容器的默认用户名和数据库名都是postgres,密码则通过POSTGRES_PASSWORD设置。这里我将数据库的端口映射到了127.0.0.1,只有本机能够访问,足够安全。

Quassel Core

这里我们需要安装两个软件包:

apt install quassel-core libqt5sql5-psql

前者是Quassel Core本体,后者则用于支持PostgreSQL的支持。如果没有第二个软件包的话,在下面使用Client配置Core时会发现只能使用SQLite数据库。

安装完成后我们还需要配置一下TLS证书。证书位于/var/lib/quassel/quasselCert.pem,其格式就是证书的key和certs拼接到一起:

-----BEGIN EC PRIVATE KEY-----
私钥。。。
-----END EC PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
证书链。。。
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
证书链。。。
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
证书链。。。
-----END CERTIFICATE-----

大概是这种样子,证书链的数量取决于你的CA,关键在于这个pem文件里要提供你的私钥、域名证书和用于整明域名证书的CA证书(ca-bundle)。

配置好之后,重启quasselcore服务即可让证书生效。如果quassel core启动失败,那多半是你的pem文件有问题。

关于证书的部分,我原本想使用两套证书,在100.64.0.0/10上提供Tailscale的证书,在其他接口上提供公网TLS证书,但后来我发现Quassel Core做不到。后来我又想,能不能让Tailscale和公网证书用一个key。我首先用tailscale生成一套证书,然后用这套证书的key生成csr,通过acme.sh等服务请求一个公网证书。但是安装acme.sh的时候我发现纯IPv6的服务器没办法访问Github。都2023年了,微软你在干什么啊。

总之这个想法就此作罢。但是我还是希望使用Tailscale访问Quassel Core,所以我只能在公网DNS上添加一条A记录来指向Tailscale里的服务器。理论上来说我这套野路子应该是可行的(取决于客户端能不能从一堆合法的证书中找到正确的证书链),甚至还可以搞一个简单的自动化。但我比较懒,这条路就暂且告一段落。

当然,最理想的情况就是Tailscale能够提供一个用于进行DNS-01验证的接口,这样我们就可以自己申请证书,在申请过程中同时验证Tailscale提供的域名我们自己的域名,这样会更舒服一些。

Quassel Client

接下来在我的PC上安装客户端,连接到运行在服务器上的Core,默认端口号4242。第一次连接会有一个向导来帮助你配置Quassel Core的账户(用于验证连接到core的客户端)、存储后端(PostgreSQL)。接下来你可以配置一些IRC的身份、服务器和频道等。关于Quassel Client的使用,这里就不多说了,可以参考官方文档。

这里说一下主题。默认情况下Quassel Client提供了一个亮色主题,但我个人更倾向于暗色主题。我搜索了一圈,发现也就Dracula主题还能用。在安装主题之后,还需要将窗口风格切换成Fusion,不然在设置窗口和其他窗口下会看起来怪怪的。

Quassel Client支持Windows和MacOS,如果想要在移动端使用的话,安卓上可以考虑Quasseldroid,iOS人士就自求多福吧,我不熟。

用量统计

为了具体测量数据库磁盘用量的增长趋势,我写了一个简单的bash脚本来查询文件大小:

#!/bin/bash

while :
do
    (du -sb /var/lib/postgresql/quassel-data && date +%s) | tee -a result.txt
    sleep 1200 # every 20 minutes
done

这个脚本每隔20分钟查询一次数据库占用的大小,并且将当时的时间戳一起追加到result.txt里。为了分析结果,我写了一段简单的kotlin程序来处理数据:

import java.io.File

object ResultCounting {
    @JvmStatic
    fun main(args: Array<String>) {
        val startTimestamp = 1685330000
        println("\n".repeat(5))
        File("result.txt").readLines()
            .chunked(2)
            .map { it[0].split("\t")[0].toLong() to it[1].toLong() }
            .forEach {
                println("${it.second - startTimestamp}\t${it.first}")
            }
        println("\n".repeat(20))
    }
}

这段程序从startTimestamp为起点输出时间T和对应的数据量。打印出来的数据刚好可以复制粘贴到excel表格里。在Excel里面做一个图标,加一个线性的趋势线,趋势线的斜率就是平均每秒增加的字节数:

微信图片_20230602222908.png

这里可以看到一个比较大的转折点。这是因为刚开始加入了几个IRC服务器,什么频道都想看,所以一下子加了差不多得有30多个频道,每个频道的在线人数从几十到几百不等,消息也很多。那个时候差不多每秒增加60到70字节。后来意识到加入了太多频道,平时也不看消息,于是就退出了一些频道,只留下了每天会看的,我感兴趣的频道。比如Libera Chat的#linuxba#opensuse之类的频道。两个阶段平均起来是每秒新增30字节的数据,但从后半段的图表来看,其实实际用量应该还会更低。

结语

这套配置我用了得有一周了,感觉下来还是挺不错的。从服务器资源占用方面来说,Quassel Core和PostgreSQL数据库加起来内存用了不到150MB(不愧是C++写的,换成Java的话1GB都不够塞牙缝的),CPU占用就更轻松一些了。我挂了三个服务器,每个服务器差不多都有10多个频道。后来退出了一些频道,CPU和内存占用就更小了。有一些服务器不支持同时登陆多个账号,而Quassel也恰巧解决了这个问题,多个Client能够同时连接到一个Core上收发消息。还是很不错的。

-全文完-


知识共享许可协议
【歪门邪道】在纯IPv6服务器上搭建Quassel Core天空 Blond 采用 知识共享 署名 - 非商业性使用 - 相同方式共享 4.0 国际 许可协议进行许可。
本许可协议授权之外的使用权限可以从 https://skyblond.info/about.html 处获得。

Archives QR Code
QR Code for this page
Tipping QR Code