反社交RSS阅读器Stringer

简介

什么是 Stringer ?

Stringer 是一个自托管的反社交 RSS 阅读器,旨在提供简单且无外部依赖的阅读体验。没有社交推荐/共享,也没有花哨的机器学习算法。

主要特点

  1. 自托管:用户可以在自己的服务器上部署 Stringer,保留对数据的完全控制。
  2. 无社交推荐:与许多现代应用不同,Stringer 不使用社交推荐或分享功能,专注于纯粹的内容阅读。
  3. 技术栈Stringer 是基于 Ruby on Rails 开发的,使用 PostgreSQL 作为数据库,前端使用 Backbone.jsGoodJob
  4. 易于部署:提供了多种部署选项,包括 HerokuDockerOpenShift
  5. 功能丰富:支持键盘快捷键、Fever API 兼容性以及多语言翻译功能。
  6. 社区驱动:项目是开源的,欢迎社区贡献和反馈。

总之,Stringer 是一个轻量级且注重隐私的 RSS 阅读器,适合喜欢自定义和控制自己阅读体验的用户。

说明

在低版本内核上运行,会遇到 libxml2: getentropy failed with error code 38

错误代码 38 通常表示 "Function not implemented",这个错误表明 libxml2 在尝试获取随机数时失败。。

这和我们之前遇到的 AH00141: Could not initialize random number generatorfailed to get urandom 是一样的,只是不同的开发语言,对同一个错误的不同表达。

这个问题除了换机器外,老苏一直没有找到其他的解决办法

安装

在群晖上以 Docker 方式安装。

采用 docker-compose 安装,将下面的内容保存为 docker-compose.yml 文件

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
27
28
29
30
31
version: '3'

services:
stringer-postgres:
image: postgres:16-alpine
container_name: stringer-postgres
restart: always
volumes:
- ./data:/var/lib/postgresql/data
environment:
POSTGRES_USER: stringer
POSTGRES_PASSWORD: myPassword
POSTGRES_DB: stringer

stringer:
image: stringerrss/stringer:latest
container_name: stringer
restart: always
ports:
- "5963:8080"
environment:
PORT: 8080
DATABASE_URL: postgres://stringer:myPassword@stringer-postgres/stringer
SECRET_KEY_BASE: Tqbt8rtBEW5CM2zPV3CH
ENCRYPTION_PRIMARY_KEY: uAPDp68hJp67TQW3fM58
ENCRYPTION_DETERMINISTIC_KEY: jYd5EcMbeVVAEZwRSUJ2
ENCRYPTION_KEY_DERIVATION_SALT: Exki7KsWyBFVmcCKm5mQ
FETCH_FEEDS_CRON: "*/5 * * * *" # optional
CLEANUP_CRON: "0 0 * * *" # optional
depends_on:
- stringer-postgres

下面是环境变量的简单说明

可变 说明
POSTGRES_USER stringer 设置 PostgreSQL 数据库的用户名,用于数据库连接。
POSTGRES_PASSWORD myPassword 设置 PostgreSQL 数据库的用户密码,确保安全的数据库访问。
POSTGRES_DB stringer 指定要创建或使用的数据库名称。Stringer 将使用这个数据库存储 RSS 数据。
PORT 8080 指定 Stringer 应用程序监听的端口。应用将在此端口上提供服务。
DATABASE_URL postgres://stringer:myPassword@stringer-postgres/stringer 用于连接数据库的完整 URL,包括用户名、密码、主机和数据库名。
SECRET_KEY_BASE Tqbt8rtBEW5CM2zPV3CH Rails 应用的安全密钥,用于加密会话和其他加密功能。确保此值是随机生成的,保持秘密。
ENCRYPTION_PRIMARY_KEY uAPDp68hJp67TQW3fM58 用于加密敏感数据的主密钥。此密钥应保持安全且不应公开。
ENCRYPTION_DETERMINISTIC_KEY jYd5EcMbeVVAEZwRSUJ2 用于确定性加密的密钥。确保相同的输入始终产生相同的输出。此密钥也应保持安全。
ENCRYPTION_KEY_DERIVATION_SALT Exki7KsWyBFVmcCKm5mQ 用于加密密钥派生的盐值,增强密钥的安全性。此值应随机生成并保持私密。
FETCH_FEEDS_CRON */5 * * * * 指定一个 cron 表达式,用于设定多久抓取一次 RSS 源。在这个例子中,每 5 分钟抓取一次。
CLEANUP_CRON 0 0 * * * 指定一个 cron 表达式,用于设定每天零点清理旧的已读故事。该任务可以手动运行或作为计划任务。

其中:

  • SECRET_KEY_BASE
  • ENCRYPTION_PRIMARY_KEY
  • ENCRYPTION_DETERMINISTIC_KEY
  • ENCRYPTION_KEY_DERIVATION_SALT

可以使用 openssl rand -hex 64 来生成

然后执行下面的命令

1
2
3
4
5
6
7
8
9
10
# 新建文件夹 stringer 和 子目录
mkdir -p /volume2/docker/stringer/data

# 进入 stringer 目录
cd /volume2/docker/stringer

# 将 docker-compose.yml 放入当前目录

# 一键启动
docker-compose up -d

反向代理

浏览器中直接访问 http://群晖IP:5963 会跳转到 https://群晖IP:5963/setup/password

虽然手动改为 http 协议能看到注册界面

但是创建用户会报错

从日志看,还是因为协议的原因

1
2
3
stringer             | 2025-01-16 02:41:32,212 DEBG 'puma' stdout output:
stringer | [b9b1b436-a0ba-4183-9400-3e55fce5eb7c] HTTP Origin header (http://192.168.0.199:5963) didn't match request.base_url (https://192.168.0.199:5963)
stringer | [b9b1b436-a0ba-4183-9400-3e55fce5eb7c] Completed 422 Unprocessable Content in 0ms (ActiveRecord: 0.0ms (0 queries, 0 cached) | GC: 0.0ms)

假设实际访问地址为: https://stringer.laosu.tech

域名 局域网地址 备注
stringer.laosu.tech http://192.168.0.199:5963 Stringer 的访问地址

npm 中的设置

SSL 都勾选了

运行

在浏览器中输入 https://stringer.laosu.tech 就能看到注册界面

注册成功后

Not now ,会跳转到一个向导界面

+ 号添加 feed

Feed URL 还是以老苏的博客为例,https://laosu.tech/atom.xml

添加成功后

点击进入

如果你有 opml 文件,可以直接导入

参考文档

stringer-rss/stringer: A self-hosted, anti-social RSS reader.
地址:https://github.com/stringer-rss/stringer

stringer/docs/Docker.md at main · stringer-rss/stringer
地址:https://github.com/stringer-rss/stringer/blob/main/docs/Docker.md