Files
2026-07-19 21:28:54 +00:00

91 lines
3.1 KiB
Markdown

# 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