很多人把 FreshRSS + RSSHub 跑起来很快,但跑稳很难:容器重启后订阅丢失、RSSHub 频繁 403、反代后回调地址异常、升级时服务中断。

这篇给一套可直接复制的 Linux 部署方案,目标是:可长期运行、可观测、可升级回滚

架构与稳定性目标

  • FreshRSS:负责订阅聚合、阅读和规则过滤
  • RSSHub:负责生成动态源(社交平台、开发平台等)
  • Redis:给 RSSHub 做缓存,减少上游请求压力
  • Nginx/Caddy:反向代理 + HTTPS

稳定性目标:

  • 容器异常可自动拉起
  • 数据目录持久化
  • 关键参数环境变量化
  • 有健康检查与日志定位路径

1) 目录规划与基础环境

sudo mkdir -p /opt/rss-stack/{freshrss-data,rsshub-cache,logs}
cd /opt/rss-stack

# 推荐先确保 Docker + Compose 可用
docker --version
docker compose version

2) docker-compose.yml(生产可用基线)

services:
  freshrss:
    image: freshrss/freshrss:latest
    container_name: freshrss
    restart: unless-stopped
    environment:
      TZ: Asia/Shanghai
      CRON_MIN: '3,33'
      TRUSTED_PROXY: 172.16.0.0/12 192.168.0.0/16
    volumes:
      - ./freshrss-data:/var/www/FreshRSS/data
      - ./freshrss-data/extensions:/var/www/FreshRSS/extensions
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:80/"]
      interval: 30s
      timeout: 5s
      retries: 5
    networks:
      - rss_net

  redis:
    image: redis:7-alpine
    container_name: rsshub-redis
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - ./rsshub-cache:/data
    networks:
      - rss_net

  rsshub:
    image: diygod/rsshub:chromium-bundled
    container_name: rsshub
    restart: unless-stopped
    depends_on:
      - redis
    environment:
      NODE_ENV: production
      CACHE_TYPE: redis
      REDIS_URL: redis://redis:6379/
      PUPPETEER_WS_ENDPOINT: ''
      REQUEST_RETRY: 2
      REQUEST_TIMEOUT: 10000
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://127.0.0.1:1200/healthz"]
      interval: 30s
      timeout: 5s
      retries: 5
    networks:
      - rss_net

networks:
  rss_net:
    driver: bridge

启动:

docker compose up -d
docker compose ps

3) 反向代理与 HTTPS(Nginx 示例)

server {
  listen 443 ssl http2;
  server_name rss.example.com;

  location / {
    proxy_pass http://127.0.0.1:1200;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }
}

server {
  listen 443 ssl http2;
  server_name reader.example.com;

  location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
  }
}

如果你的 FreshRSS 容器并未映射到宿主 8080,请改为 docker inspect 得到的端口或改用同网络反代。

4) 常见翻车点与修复

RSSHub 频繁 403 或超时

  • 降低抓取频率,优先开启缓存(Redis)
  • 为高风控源配置代理/IP 轮换
  • 调整 REQUEST_TIMEOUT(10s→15s)并观察日志
docker logs --tail=200 rsshub

FreshRSS 定时更新不执行

  • 检查 CRON_MIN 是否生效
  • 容器时区是否与预期一致
  • 在管理面板手动触发更新验证

升级后白屏或插件异常

先备份数据目录再升级:

tar czf backup-freshrss-$(date +%F).tgz /opt/rss-stack/freshrss-data
docker compose pull
docker compose up -d

5) 运营建议(保守增长)

  • 新增订阅源时,先小批量验证 24 小时
  • 每周固定一次 docker compose pull && docker compose up -d
  • 给 RSSHub 路由做“价值分层”:高价值源优先稳定,低价值源可降频

总结

这套方案的核心不是“能跑”,而是“出故障时可快速定位并恢复”。

按上面的目录持久化、Redis 缓存、健康检查和代理配置执行后,FreshRSS + RSSHub 在 Linux 上可以长期稳定运行,并且后续扩容(如接监控、迁移到 k3s)也比较顺滑。