# suwayomi-rss A small Node.js 24 and Koa service that turns recent chapter updates from a [Suwayomi](https://github.com/Suwayomi/Suwayomi-Server) library into an RSS 2.0 feed. It queries Suwayomi's GraphQL API for library chapters ordered by the time they were fetched. Each RSS item uses the Suwayomi chapter ID as a stable GUID, so a feed reader will notify only when a chapter first appears in the feed. ## Run with Docker ```sh docker build -t suwayomi-rss . docker run --rm -p 3000:3000 \ -e SUWAYOMI_URL=http://suwayomi:4567 \ suwayomi-rss ``` In Compose, place this service on the same network as Suwayomi: ```yaml services: suwayomi-rss: build: . environment: SUWAYOMI_URL: http://suwayomi:4567 SUWAYOMI_AUTH_MODE: ui_login SUWAYOMI_USERNAME: ${SUWAYOMI_USERNAME} SUWAYOMI_PASSWORD: ${SUWAYOMI_PASSWORD} FEED_PUBLIC_URL: https://rss.example.com/rss.xml RSS_USERNAME: ${RSS_USERNAME} RSS_PASSWORD: ${RSS_PASSWORD} ports: - "127.0.0.1:3000:3000" restart: unless-stopped ``` The feed is available at `/rss.xml` and `/feed.xml`. A liveness endpoint is available at `/healthz`; it deliberately does not contact Suwayomi. ## Configuration | Variable | Default | Description | | --- | --- | --- | | `SUWAYOMI_URL` | `http://suwayomi:4567` | Suwayomi server root URL | | `SUWAYOMI_GRAPHQL_URL` | `$SUWAYOMI_URL/api/graphql` | Override the GraphQL endpoint | | `SUWAYOMI_AUTH_MODE` | `none` | `none`, `basic`, `ui_login`, or `bearer` | | `SUWAYOMI_USERNAME` | | Required for `basic` and `ui_login` | | `SUWAYOMI_PASSWORD` | | Required for `basic` and `ui_login` | | `SUWAYOMI_TOKEN` | | Required for `bearer` | | `SUWAYOMI_TIMEOUT_MS` | `10000` | Upstream request timeout | | `FEED_TITLE` | `Suwayomi releases` | RSS channel title | | `FEED_DESCRIPTION` | `New chapters in my Suwayomi library` | RSS channel description | | `FEED_LINK` | `SUWAYOMI_URL` | RSS channel link and fallback item link | | `FEED_PUBLIC_URL` | | Public feed URL, emitted as the Atom self link | | `FEED_ITEM_LIMIT` | `50` | Number of recent chapters, from 1 to 200 | | `FEED_CACHE_SECONDS` | `300` | In-memory upstream response cache duration | | `RSS_USERNAME` / `RSS_PASSWORD` | | Optional HTTP Basic protection for the feed | | `HOST` | `0.0.0.0` | Listening address | | `PORT` | `3000` | Listening port | `simple_login` is not supported for the upstream connection because it is an interactive, cookie-based mode. Prefer Suwayomi's `ui_login`, Basic Auth over a trusted private network, or a bearer token. The application never persists credentials or chapter data. Its cache is held in memory and is discarded on restart. ## Local development ```sh npm install npm test SUWAYOMI_URL=http://localhost:4567 npm start ``` This project uses Node's built-in `node:test` runner and has no test framework dependency. ## Security This feed reveals the contents of your Suwayomi library and chapter source URLs. Keep it on a private network, protect it with `RSS_USERNAME` and `RSS_PASSWORD`, or put it behind your existing authenticated reverse proxy. Do not send Suwayomi or RSS credentials over unencrypted public HTTP. ## License MIT