Tiny Tiny RSS 安装及填坑之路

@Wen's  April 13, 2021

之前一直在使用 Inoreader,最近实在是受不了它的速度所以考虑更换 RSS 服务,参考了很多最终选择自己搭建一个 Tiny Tiny RSS (TT-RSS) 服务,本以为十分成熟的配置流程结果处处是坑,所以还是单独记录一下方便查阅。

大部分网上关于 TT-RSS 的配置教程都是基于 Docker,对于我这种不喜欢使用 Docker 的百无一用,而少数自己在服务器上手动配置的也是年代久远,配置过程中的各种错误也没有什么很好的解释。尤其是像 Mercury 这种官方关闭服务的,我也是折腾好久才搭好了一个 API。

本文主要内容包括:

  • TT-RSS 在个人 Server 上的搭建方法

  • TT-RSS 后台自动更新 Feeds

  • Fever API 配置

  • 搭建个人 Mercury-Parser API

  • 还会稍微介绍一下常见的 TT-RSS 设置(如主题、客户端等)

准备工作和安装

服务器配置

Vultr 服务器,公网 IP,有解析域名,希望能够通过子域名访问 Web 端 RSS 服务。

因为不是直接在 Docker 上部署,所以在正式安装前,需要进行一些服务器端的操作,以下操作都能通过 Google 解决,有搭建网站经验的应该很快就能搞定。

  1. 子域名解析

  2. LNMP 环境配置(已安装的可以跳过,注意后面会用到 LNMP 的安装包)

  3. Nginx 网站配置(根目录,SSL,重定向等)

  4. 申请 SSL 证书

下面是我使用的 nginx.conf,可以参考添加到自己的配置文件中:

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server
   {
       server_name rss.phower.me;  # 你的子域名
       index index.html index.htm index.php default.html default.htm default.php;
       root $ROOT_DIR;  # 子域名网站根目录,将 $ROOT_DIR 改为自己的目录
       error_page   404   /404.html;
       include enable-php.conf;

       listen 443 ssl; # managed by Certbot
       ssl_certificate /etc/letsencrypt/live/phower.me/fullchain.pem; # managed by Certbot
       ssl_certificate_key /etc/letsencrypt/live/phower.me/privkey.pem; # managed by Certbot
       include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
       ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server
   {
   if ($host = rss.phower.me) {
       return 301 https://$host$request_uri;
   } # managed by Certbot

   listen 80;
   listen [::]:80;
   server_name rss.phower.me;
   return 404; # managed by Certbot
}

到此当你访问自己设置的域名时应该会出现 nginx 已安装的界面。

安装 TT-RSS

接下来就是正式安装 TT-RSS,这个环节没有太大问题,只是有些小 Bug 需要注意。

首先,我选择的数据库是 MYSQL,官方推荐采用 PostgreSQL,不过两者大同小异。在正式安装前,我们需要手动在 MYSQL 中创建用户 ttrss 和名为 ttrss 的数据库(用户名和数据库名也可以自行设置)

使用 Git 拉取安装包(TT-RSS 是在其作者自建的 Gogs 上),以下涉及 $ROOT_DIR 的更换为自己的网站根目录。

Bash

1
2
3
cd $ROOT_DIR  # 进入网站根目录
git clone https://tt-rss.org/git/tt-rss.git ttrss
cp -R ttrss/* $ROOT_DIR  # 将文件复制到网站根目录下

实际安装中会出现以下权限问题,所以我们先设置好文件权限:

TT-RSS 权限错误TT-RSS 权限错误

Bash

1
chmod -R 777 $ROOT_DIR

刷新我们的网站,此时应该能够正常进入安装界面了,我们在表中填入之前创建好的数据库名及数据库用户名,Tiny Tiny RSS URL 处填写我们的域名,点击 test configuration 就能完成安装了。

TT-RSS installTT-RSS install

在这个环节容易遇到以下错误:PHP function mime_content_type() is missing, try enabling fileinfo module.

原因是 PHP 缺少 fileinfo 模块,这时我们需要用到 LNMP 安装包,重新对 fileinfo 这个模块进行编译安装,具体操作可参考:《手动为已编译的PHP加入fileinfo扩展模块》

TT-RSS 安装步骤并不复杂,如果没有报错一切进行顺利,最后点击按钮 Return to Tiny Tiny RSS 即算正式完成安装。

进入登录界面,初始用户名和密码分别为 admin 和 password,记得登录成功后第一时间修改密码。(盗用一张 Web 主界面)

TT-RSS 主界面TT-RSS 主界面

TT-RSS 的后台配置十分简洁,说明也很清晰,配合汉化根据自己需求进行选择即可。

TT-RSS 后台自动更新 feeds

官方文档:《UpdatingFeeds - Tiny Tiny RSS》

官方文档写的比较简略,主要介绍了三种办法:1)手动;2)后台自动,使用 crontab;3)前台自动。本来使用 crontab 是个执行定时更新的好办法,但是网上找到的教程乱七八糟,大多教程配置出来根本就不能正常更新,有的甚至是把后台更新跟前台更新混淆在一起,事实上 crontab 根本没有运作。

crontab 定时更新

TT-RSS 更新脚本文件 update.php 或 update_daemon2.php 不能由 root 用户来执行,比较合适的是通过 nginx 的运行用户 www 来执行。

crontab 命令被用来提交和管理用户的需要周期性执行的任务,与 windows 下的计划任务类似,当安装完成操作系统后,默认会安装此服务工具,并且会自动启动 crond 进程,crond 进程每分钟会定期检查是否有要执行的任务,如果有要执行的任务,则自动执行该任务。

crontab 的基本语法如下:

Bash

1
2
3
4
5
6
7
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
*  *  *  *  * user-name  command to be executed

简单来说,设定好执行时间周期以及需要执行命令就可以了,但是由于 TT-RSS 的更新脚本不能用 root 执行,所以网上教程很多不规范的代码实际并不能运行。下面代码是我参考官方文档,使用 www 用户执行,并且测试成功的:

Bash

1
2
3
4
5
# 以下内容均在 root 用户下执行
vi /etc/cron.allow   # 该文件中所列用户允许使用crontab命令,在编辑界面写入 www 表示允许该用户使用 crontab
crontab -u www -e
# 编辑界面添加以下内容
*/30 * * * * /usr/local/php/bin/php /安装TT-RSS的目录/update.php --feeds --quiet

需要注意:

  • 定时时间可以自行修改

  • 为了保证 crontab 正常运行,一定先在 cron.allow 中写入执行用户

  • /usr/local/php/bin/php 要修改为你的 PHP 执行文件的地址,也可能是 /usr/bin/php,以个人系统为准

  • update.php 的绝对路径不能出错

另外,如果你不是在 root 用户下执行以上命令,比如也可以直接在 www 用户下执行:

Bash

1
2
3
4
5
vi /etc/cron.allow   # 该语句执行仍需要 root 权限
# 以下可直接在 www 下执行
crontab -e
# 编辑界面添加以下内容
*/30 * * * * /usr/local/php/bin/php /安装TT-RSS的目录/update.php --feeds --quiet

crontab 语句不能写成 */30 * * * * www /usr/local/php/bin/php /安装TT-RSS的目录/update.php --feeds --quiet

Each cron command followed by a username, only if it is the system crontab file

crontab 接用户名的语法只能是用在系统调度的 crond 文件中,而我们使用的只是单个用户下的 crond 进程。

在此之后,可以通过以下几个方法查看 crontab 是否配置成功以及是否执行:

  1. 在 root 用户下查看 /var/spool/cron/,每个用户 crond 命令文件存放的目录,以用户名命名。
    crontab 配置成功1crontab 配置成功1

  2. 切换到 www 用户,执行 crontab -l,出现之前所设置的命令:
    crontab 配置成功2crontab 配置成功2

  3. 查看 crontab 的 log 文件 /var/log/cron,里面出现所配置的定时任务:
    crontab 配置成功3crontab 配置成功3

为了检验 crontab 的命令是否正常运行,可以将上图中 command 语句复制出来手动执行一次(需要在 www 用户下执行),这时可以把 --quiet 去掉,如果能够正常运行,并且网页上显示 feeds 最新的更新时间,那说明定时任务配置成功。

手动更新时可能会出现警告:Warning: exec() has been disabled for security reasons in /update.php

原因是 exec() 函数因为安全原因被禁止。
我们需要找到 php.ini,其中 disable_function 选项中为禁用的函数,删掉 exec,重启 php 服务即可。

前台自动更新

在官方文档中,还介绍了一种更新方法:Simple background updates,我称之为”前台更新“。也就是只要在浏览器中开着 TT-RSS 的网页,它也可以按照你设置的更新时间定时更新 feeds。

If all else fails and you can’t use any of the above methods, you can enable simple update mode where tt-rss will try to periodically update feeds while it is open in your web browser. Obviously, no updates will happen when tt-rss is not open or your computer is not running.

配置方法为:将 config.php 中的 SIMPLE_UPDATE_MODE 设置为 true 即可。不过这种办法只适合于浏览器打开的场景,其他使用 TT-RSS API 的程序并不支持这种更新方法。

在网页端设置的定时更新时间与 crontab 的更新时间是有关的,如网页端设置 4 小时更新,crontab 设置 30 分钟更新,实际上后台 feeds 更新的频率是 4 小时。这应该是一个优先级的问题,具体程序怎么调整的就没有深究了。

Fever API 配置

GitHub: DigitalDJ/tinytinyrss-fever-plugin: Tiny Tiny RSS Fever API Plugin

Fever API 主要是为 TT-RSS 提供一个多端同步的功能,配置方法相对简单:

Bash

1
2
cd $ROOT_DIR/plugins.local
git clone https://github.com/DigitalDJ/tinytinyrss-fever-plugin fever

在 TT-RSS 后台开启 允许外部客户端通过 API 来访问账户 以及在插件中勾选 Fever 并保存,此时就能看到 Fever Emulation 设置界面。

Fever API 设置界面Fever API 设置界面

设置 Fever API 的独立密码,可以看到图中的 Warning,建议设置独立密码。设置好后,在支持 Fever API 的客户端上,使用 API URL 和用户名密码登录即可,注意 API URL 要使用上图红框中由插件给出的地址。下图为 Reeder4 的登录界面:

Reeder4 登录界面Reeder4 登录界面

好在 Fever API 还在缓慢更新,所以为了解决一些 Bug,以后可以手动更新插件:

Bash

1
2
cd $ROOT_DIR/plugins.local
git pull origin master

相关问题:Fever API 无法保存密码

Fever 插件配置界面点击保存没有任何反应,而且下次打开配置界面,显示的密码还是为空。那么密码到底是否设置成功呢,答案是”成功了“。

在插件配置界面 F12,切换到 Network 选项,然后输入密码点击设置,当我们看到名为 backend.php 出现并且状态码为 200 时说明密码设置是成功的。

Fever backendFever backend

如果还不放心,进入数据库后台 phpadmin,找到 ttrss 数据库下的表单 ttrss_plugin_storage,可以看到下面 Fever 那一行的数据相比未设置时是发生了改变的,并且你可以重复操作几次,确定表单中密码相关的内容具有一致性。(当然,最好的方法还是直接用客户端试一试)

这个问题在 Docker 版的多合一安装包中貌似也存在,所以只能等待未来插件的作者修复这个 Bug 了。

TT-RSS 全文输出

RSS 可以方便人们更高效的获取信息,但是对于网站来说其实是损失了部分网络流量,一些论坛或者门户网站会将 RSS 链接隐藏起来或者是只输出部分文章内容,所以在阅读 RSS 时你需要再跳转到原始网址才能完整阅读。

当然,对于我而言,全文输出的功能只是”锦上添花“,并非”必不可少“。我主要是用 RSS 订阅论坛更新和一些博主,有感兴趣的内容我会更倾向于去原网站阅读,因为原网站自身的排版和样式无疑还是比 RSS 单一的图片和文字输出要生动许多。

在配置这个功能之初稍稍做了一下工作,目前 TT-RSS 常用有两个方法来实现全文输出:

  1. 采用自带的 af_readability 插件

  2. 使用 Mercury Parser API

可能因为早期的 af_readability 效果不好,大多数教程上来就直接配置 Mercury,结果我也花了大量时间在填这个坑。而事实上 af_readability 是 TT-RSS 作者在维护,不说实用性,至少兼容性是完全没问题的,而且在持续更新,就个人测试而言目前的 af_readability 更加实用。

搭建 Mercury-Parser API

可以认为 Mercury 就是一个爬虫 API,你将需要爬取的网址发送给 Mercury 服务器,然后它返回全文的内容。遗憾的是 2019 年 Mercury 就开源代码然后彻底关停官方服务了。因此网上几乎所有 Mercury 相关的教程都失效了。

February 2019, Postlight announced they were discontinuing the hosted service and open-sourcing the code.

Postlight 也给出了一个自建 API 的方法:《postlight/mercury-parser-api》。不过这个方法并不太适用自己在服务器上搭建,反而像是为 Docker 和 AWS 量身定做。另外,官方的搭建方法输出端口为 3000,不知道去哪里修改,这直接跟我服务器在跑的有些服务冲突,于是干脆放弃。想着用 Mercury Parser 的源代码搭一个类似的 Web API,Google 了好久还真让我发现了一篇自建 Mercury Parser 的文章:

Replacing Postlight’s Mercury scraping service with your self-hosted copy – Babak Fakhamzadeh

Mercury Parser 本身就是依靠 node 搭建的,那就方便了,用 expressjs 包装一下,一个 web API 就诞生了。

首先,我们需要创建一个文件夹来安装 mercury parser,需要保证的是这个文件夹能简单的通过域名访问到,如我在 TT-RSS 目录下新建文件夹 mercury,然后可以通过 rss.phower.me/mercury 来访问。接下来就是 API 的搭建。

Bash

1
2
3
4
5
cd $ROOT_DIR/mercury
npm init    # 需要 nodejs 环境
# 中间会弹出几个选项,entry point 填写 app.js,其余直接 enter 跳过
npm install express --save
npm install @postlight/mercury-parser --save    # 直接拉取 mercury 源代码,非 API 版

在 /mercury/ 中创建 app.js 文件,填入以下内容:

Javascript

1
2
3
4
5
6
7
8
const express = require('express');
const app = express();
const port = 1234;    // API 运行端口号,自定义
app.get('/mercury/', function (req, res){    // /mercury 为 app.js 所在文件夹名称
const Mercury = require('@postlight/mercury-parser');
const url = req.query.url;
Mercury.parse(url).then(result => {res.send(result);} );})
app.listen(port)

执行此文件:

Bash

1
node app.js

此时访问 rss.phower.me:1234/mercury/?url=https://www.baidu.com 可以看到 parser 抓取的全文内容,说明服务搭建成功。

mercury 抓取百度全文mercury 抓取百度全文

接下来我们需要该 web API 能在后台运行:

Bash

1
2
3
npm install forever -g
forever start app.js
# 之后可以通过 forever 的相关命令来查看和终止服务

此时 Mercury Parser API 就算是完整搭建起来了,以后只需要通过访问 rss.phower.me:1234/mercury/?url=网址 就可以获得全文抓取的内容。值得提醒,因为这个 API 没有提供任何用户认证和防爆措施,所以部署的端口号以及文件夹名按照个人喜好来设置,以防滥用。当然也可以配置一下 nginx 的反代来隐藏端口号等信息,这就是后话了。

TT-RSS Mercury 插件

上一节其实都算是为使用 mercury 插件的准备工作,这里才是正式的插件配置方法。目前 TT-RSS 中使用的 mercury 插件是 mercury_fulltext,其作者也是 TT-RSS Docker 版的开发者。

由于原插件适配的是 Docker 版本和早期 postlight 的 API,所以我进行了一些小改动,可以支持自己配置的 mercury API。

使用 git 获取插件:

Bash

1
2
cd $ROOT_DIR/plugins
git clone https://github.com/PhosphorW/mercury_fulltext.git mercury_fulltext

进入后台先在插件列表启动 mercury_fulltext,此时在信息源页面出现相关的设置界面,填入上一节中配置好的 mercury API URL,如 rss.phower.me:1234/mercury/,注意不要包括后面的网址等链接。

mercury 后台设置mercury 后台设置

对需要全文输出的信息源,我们还需要手动启动 mercury 全文输出支持,等待下一次该信息源有更新时就能够看到全文输出的内容了。如果需要调试,也可以使用 调试信息源 功能,勾选 force refresh 和 force rehash,看到 mercury_fulltext 有对应的运行时间时说明 API 已经正常工作,返回主界面可以看到原有节选内容已经变成了全文输出。

重新抓取信息源重新抓取信息源

如果是使用的 HenryQW 的插件,请自行修改 init.php

Php

1
2
3
4
// 找到下面这一行代码,第 200 行附近
curl_setopt($ch, CURLOPT_URL, rtrim($api_endpoint, '/') . '/parser?url=' . rawurlencode($url));
// 修改为
curl_setopt($ch, CURLOPT_URL, rtrim($api_endpoint, '/') . '/?url=' . rawurlencode($url));

af_readability 插件

相比 mercury 我其实更加推荐 af_readability,即官方的全文输出插件。测试了几个我常用的信息源均能正常抓取,抓取质量跟 mercury 相比几乎没有什么区别。而且 af_readability 还有一个吸引我的地方就是它有一个 toggle 按钮,即使你没有为这个信息源配置全文输出,也可以通过这个按钮进行二次抓取并且实时显示在页面中。

使用方法跟 mercury_fulltext 类似,不需要额外安装,难度系数极低。启动插件后在后台全局设置中勾选为 核心代码和其他插件提供全文服务,然后对于需要全文输出的信息源勾选 inline 文章内容。没有勾选该功能的信息源也可以使用 手动切换 全文输出,如果需要在移动端直接查看全文的必须勾选 ”inline 文章内容“。

readability 后台配置readability 后台配置

下面是 ”Chiphell 新闻“ 的全文输出对比,目标网站是论坛形式,可以看出 af_readability 更美观一些,不过总体来说大同小异。mercury 是采用的自建 API,官方也有一些扩展功能的配置方法,而 af_readability 是原生插件稳定性肯定更好。

两种全文抓取结果对比两种全文抓取结果对比


添加新评论