
阿里云服务器快到期了。上面跑着一个 FreshRSS,地址是:
https://rss.seis-jun.xyz/
怎么办?继续续费当然可以,但我又觉得有点亏。RSS 阅读器这种东西,本质上就是给自己用的,不需要一台公网 VPS 常年挂着。
于是这次试了一下:把 FreshRSS 搬到办公室 Fedora 电脑上,用 Podman 跑容器,再用 Cloudflare Tunnel 暴露到公网。
最后访问地址不变:
https://rss.seis-jun.xyz/
大概结构是这样:
浏览器 / RSS 客户端
↓
Cloudflare DNS / Tunnel
↓
办公室 Fedora 上的 cloudflared
↓
http://127.0.0.1:8080
↓
FreshRSS Podman 容器
这样有几个好处:
- 不需要阿里云 VPS。
- 办公室电脑不需要公网 IP。
- 不用在办公室路由器上开 80/443/8080。
- FreshRSS 还是完整自托管,不是静态 OPML 页面。
先把域名接到 Cloudflare
域名是:
seis-jun.xyz
在 Cloudflare 里添加站点,选择 Free plan。
原来博客是 GitHub Pages,所以 Cloudflare 扫出来的这两条记录先保留:
CNAME seis-jun.xyz junxie01.github.io
CNAME www junxie01.github.io
这里我把它们设成 DNS only。先不要让 Cloudflare 代理博客,不然 HTTPS、缓存、GitHub Pages 这些东西混在一起,容易把自己绕进去。
Cloudflare 给了两个 nameserver,然后去阿里云域名控制台把 DNS 服务器改过去。
检查一下:
dig NS seis-jun.xyz +short
dig @1.1.1.1 NS seis-jun.xyz +short
能看到 Cloudflare 的 nameserver,就说明 DNS 接管差不多好了。
Fedora 上跑 FreshRSS
办公室机器是 Fedora,用 Podman。
先装:
sudo dnf install -y podman
podman --version
然后建两个 volume:
sudo podman volume create freshrss_data
sudo podman volume create freshrss_extensions
一开始我想拉 Docker Hub 的镜像:
docker.io/freshrss/freshrss:latest
结果办公室网络访问 Docker Hub 超时。好吧,熟悉的味道。
于是换成 GHCR:
sudo podman pull ghcr.io/freshrss/freshrss:latest
启动容器:
sudo podman run -d --replace \
--name freshrss \
-p 127.0.0.1:8080:80 \
-e TZ=Asia/Tokyo \
-e CRON_MIN='1,31' \
-v freshrss_data:/var/www/FreshRSS/data \
-v freshrss_extensions:/var/www/FreshRSS/extensions \
ghcr.io/freshrss/freshrss:latest
这里比较关键的是:
-p 127.0.0.1:8080:80
也就是说 FreshRSS 只监听本机 127.0.0.1:8080,不会直接暴露给局域网或公网。外面访问全部交给 Cloudflare Tunnel。
检查:
sudo podman ps --filter name=freshrss
curl -I http://127.0.0.1:8080/
如果返回类似:
HTTP/1.1 302 Found
Location: /i/?rid=...
就说明 FreshRSS 活着。302 不是坏事,是它在跳转到初始化或入口页面。
创建 Cloudflare Tunnel
安装 cloudflared:
curl -fsSL https://pkg.cloudflare.com/cloudflared.repo | sudo tee /etc/yum.repos.d/cloudflared.repo
sudo dnf install -y cloudflared
cloudflared --version
我本来想在 Cloudflare Zero Trust 网页后台创建 Tunnel,但 Free 激活时要绑定付款方式,中国卡不太顺利。
于是改走命令行 locally-managed tunnel。
登录:
sudo cloudflared tunnel login
它会给一个 URL,浏览器打开后选择 seis-jun.xyz。授权完成后会在 root 的 cloudflared 目录下生成证书。
注意:这个证书不要公开。
创建 Tunnel:
sudo cloudflared tunnel create freshrss-office
然后写配置:
sudo tee /root/.cloudflared/config.yml >/dev/null <<'EOF'
tunnel: <TUNNEL_ID>
credentials-file: /root/.cloudflared/<TUNNEL_ID>.json
ingress:
- hostname: rss.seis-jun.xyz
service: http://127.0.0.1:8080
- service: http_status:404
EOF
再把域名路由到 Tunnel:
sudo cloudflared tunnel route dns freshrss-office rss.seis-jun.xyz
如果看到类似:
Added CNAME rss.seis-jun.xyz which will route to this tunnel
就差不多了。
前台测试一下
先前台跑:
sudo cloudflared tunnel --config /root/.cloudflared/config.yml run freshrss-office
看到:
Registered tunnel connection
protocol=quic
说明连上了。
另开一个终端:
curl -I https://rss.seis-jun.xyz/
成功的话应该是:
HTTP/2 302
server: cloudflare
location: /i/?rid=...
如果本地 DNS 抽风,可以查公共 DNS:
dig @1.1.1.1 rss.seis-jun.xyz +short
dig @8.8.8.8 rss.seis-jun.xyz +short
Fedora 本地缓存没刷新时,也可以:
sudo resolvectl flush-caches
resolvectl query rss.seis-jun.xyz
初始化 FreshRSS
等 https://rss.seis-jun.xyz/ 能打开后,就用正式域名初始化 FreshRSS。
我这里选:
数据库:SQLite
Base URL:https://rss.seis-jun.xyz/
然后导入旧 FreshRSS 导出的 OPML。
OPML 一般能恢复:
订阅源
分类
Feed 地址
但不要指望它完整恢复历史文章、已读状态、收藏、插件配置和用户偏好。RSS 搬家嘛,能把订阅源搬回来就已经很不错了。
让它开机自动跑
Tunnel 做一个 systemd 服务:
sudo tee /etc/systemd/system/cloudflared-freshrss.service >/dev/null <<'EOF'
[Unit]
Description=Cloudflare Tunnel for FreshRSS
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/bin/cloudflared tunnel --config /root/.cloudflared/config.yml run freshrss-office
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now cloudflared-freshrss.service
FreshRSS 容器也交给 systemd:
sudo tee /etc/systemd/system/freshrss-container.service >/dev/null <<'EOF'
[Unit]
Description=FreshRSS Podman Container
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=/usr/bin/podman start -a freshrss
ExecStop=/usr/bin/podman stop -t 10 freshrss
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo podman stop freshrss
sudo systemctl enable --now freshrss-container.service
检查:
sudo systemctl status freshrss-container.service --no-pager
sudo systemctl status cloudflared-freshrss.service --no-pager
curl -I http://127.0.0.1:8080/
curl -I https://rss.seis-jun.xyz/
期望是:
FreshRSS: active
cloudflared: active
本地访问: HTTP/1.1 302
公网访问: HTTP/2 302
这就可以了。
日常维护
以后主要就这几个命令:
sudo systemctl status freshrss-container.service --no-pager
sudo systemctl status cloudflared-freshrss.service --no-pager
sudo systemctl restart freshrss-container.service
sudo systemctl restart cloudflared-freshrss.service
sudo journalctl -u freshrss-container.service -n 100 --no-pager
sudo journalctl -u cloudflared-freshrss.service -n 100 --no-pager
更新 FreshRSS 镜像时,因为 Docker Hub 访问不稳,继续用 GHCR:
sudo systemctl stop freshrss-container.service
sudo podman pull ghcr.io/freshrss/freshrss:latest
sudo podman rm freshrss
sudo podman run -d --replace \
--name freshrss \
-p 127.0.0.1:8080:80 \
-e TZ=Asia/Tokyo \
-e CRON_MIN='1,31' \
-v freshrss_data:/var/www/FreshRSS/data \
-v freshrss_extensions:/var/www/FreshRSS/extensions \
ghcr.io/freshrss/freshrss:latest
sudo systemctl start freshrss-container.service
再检查:
curl -I http://127.0.0.1:8080/
curl -I https://rss.seis-jun.xyz/
安全上别偷懒
下面这些东西不要公开:
/root/.cloudflared/cert.pem
/root/.cloudflared/<TUNNEL_ID>.json
/root/.cloudflared/config.yml
特别是 .json 凭据文件,泄露后别人可能冒用这个 Tunnel。
FreshRSS 管理员密码也要设置强一点。毕竟现在 rss.seis-jun.xyz 是公网可访问的,不是自己电脑上随便玩的小服务。
如果以后 Cloudflare Zero Trust 的付款方式问题解决,也可以再加一层 Cloudflare Access。不过目前先跑起来,比什么都强。
最后
现在的状态是:
seis-jun.xyz 已接入 Cloudflare
GitHub Pages 博客记录保留为 DNS only
rss.seis-jun.xyz 通过 Tunnel 指向办公室 Fedora
FreshRSS 用 Podman 跑在 127.0.0.1:8080
OPML 已导入
公网访问返回 HTTP/2 302
等回办公室后,再做一次完整自检:
sudo systemctl is-enabled freshrss-container.service
sudo systemctl is-active freshrss-container.service
sudo systemctl is-enabled cloudflared-freshrss.service
sudo systemctl is-active cloudflared-freshrss.service
curl -I http://127.0.0.1:8080/
curl -I https://rss.seis-jun.xyz/
如果都正常,阿里云上的旧 FreshRSS 就可以不用续费了。
省下一台 VPS,RSS 继续活着。挺好。
对了,要是你想用的话给我说一下,我来给你建一个账户。
Comments