Rensaiō is a modern fork of the original Kaizoku and Kaizoku Next Gen by OAE, built to fill the void and bring a streamlined series manager back to life.
What does it do?
When you subscribe to a series, it will automatically download it. Whenever the series is updated in any of your configured providers, new chapters will be downloaded automatically, in a "drop and forget" fashion.
Important
⬆️ You can upgrade directly from Kaizoku.Net to Rensaiō. No changes are required on your side: simply run the new executable or update your Docker image, and everything will be upgraded automatically.
Nevertheless, before upgrading, make sure to back up your config directory, including your database. Since the devil never rests.
- Quick Start
- What It Does
- Key Features
- Under the Hood
- Issues
- Running Android libraries on .NET, is that possible?
- Docker Support
- Single Sign-On (OpenID Connect)
- Desktop App
- Build It Yourself
- Resource Usage
- Contributing
- License
docker run -d \
--name rensaio \
--network host \
-e PUID=99 -e PGID=100 -e UMASK=022 \
-v /path/to/config:/config \
-v /path/to/series:/series \
maxpiva/rensaio:latestOpen http://<host-ip>:9833 and follow the setup wizard.
For Docker Compose, Unraid, or Kubernetes (Helm), see Docker Support.
Rensaiō is a series manager that prioritizes simplicity, speed, and reliability.
It uses the power of MIHON extensions to connect with multiple sources.
-
🧙♂️ Startup Wizard
Automatically imports your existing library. -
🔁 Temporary vs Permanent Sources
- Chapters are only downloaded from temporary sources when there is no permanent sources
- Auto-deleted if a permanent source later provides them.
-
🔎 Multi-Search & Multi-Linking
Search and link one series to multiple sources/providers. -
📥 Automatic Downloads
Everything is automatic, Retries, Reschedules. With a dedicated download Page.
-
🔄 Auto-Updates
Extensions are kept up to date. -
👥 Multi-User System Create separate accounts with different permission levels. Invite people, and control who has access to what. Optionally enable authentication to restrict access to authorized users only, with password login or Single Sign-On through any OpenID Connect provider.
-
🩺 Status & Health Dashboard A dedicated page that shows which series and providers need attention. Color-coded alerts (green/yellow/red) help you spot issues at a glance like broken providers, stale series with no new chapters, and more.
-
📡 OPDS Server Read your library from any OPDS-compatible reader app. Browse by all series, what's new, what you're currently reading, categories, and tags. Reading progress syncs back automatically. Each user gets their own unique random OPDS path (e.g.
door-pebble) for private access. Example:https://rensaio.example.com/door-pebble -
🤖 MCP Server (AI Integration) Expose your library to AI tools through the Model Context Protocol. Let LLMs search your series, check status, and more, all respecting user permissions. Just add /mcp to your OPDS path. Example:
https://rensaio.example.com/door-pebble/mcp -
📖 Read State Tracking Remembers where you left off reading each chapter, across all your devices, backed in your series, not the database.
-
🔗 External Scrobbler Sync Sync your reading progress with external trackers. Supported providers: AniList, MyAnimeList, Kitsu, MangaDex. Each user controls their own connections and sync settings.
-
🧹 Filename Normalization
Rebuild your library easily with consistent naming, that will help you reimport it back when needed. -
🧾 ComicInfo.xml Injection
Chapters include rich metadata from the original source. -
🖼️ Extras
- Stores
cover.jpgper series - Stores
rensaio.jsonfor full metadata mapping, and read-state stored with you series. - External Domain Support for reverse proxy scenarios.
- Support for jxl, jp2, avif image formats, with real-time transcoding for clients not supporting them.
- And much more...
- Stores
Rensaiō is composed of:
- Frontend: A beautiful UI forked from Kaizoku Next by OAE (Next.js).
- Backend: A custom .NET engine that manages schedules, downloads, metadata, OPDS/MCP servers, and scrobbler sync, with a Mihon Bridge that enables the use of Mihon Android extensions.
- If you encounter any issues, check the
logsfolder. You can review the logs there or upload them to share feedback.
Only the MIHON extensions are actively maintained, and they are distributed as Android APKs. So we need to hack around that!
By leveraging the Java/Android bridge originally created by the Suwayomi team, and adapting parts of it to fit our use case, including replacing KCEF with JCEF Maven we can generate a Java 8 Android compatibility layer with all required Java dependencies included.
Then use IKVM to run this on .NET.
- Available for both
amd64andarm64.
| Container Path | Description |
|---|---|
/config |
Stores application configuration |
/series |
Stores series |
| Port | Service | Required | Notes |
|---|---|---|---|
| 9833 | Rensaiō UI | ✅ | Web interface |
| Variable | Value | Description |
|---|---|---|
PUID |
99 | Host user ID |
PGID |
100 | Host group ID |
UMASK |
022 | File permission mask (default) |
Ensure the specified PUID and PGID have write access to your mounted
/configand/seriesdirectories.
It is recommended to use host networking for optimal performance when downloading a lot and querying multiple providers in parallel. This applies to the Docker one-liner and Unraid template below; the Compose and Helm examples use bridged/ClusterIP networking instead since host networking isn't practical (or needed) in those environments.
docker run -d \
--name Rensaio \
--network host \
-p 9833:9833 \
-e PUID=99 \
-e PGID=100 \
-e UMASK=022 \
-v /path/to/your/config:/config \
-v /path/to/your/series:/series \
maxpiva/rensaio:latestReplace /path/to/your/config and /path/to/your/series with real paths on your host.
Runnable file: examples/docker-compose.yml
services:
rensaio:
container_name: rensaio
image: 'maxpiva/rensaio:latest'
volumes:
- '/path/to/your/series:/series'
- '/path/to/your/config:/config'
environment:
- UMASK=022
- PGID=100
- PUID=99
ports:
- '9833:9833'Template file: examples/unraid.xml
<Container>
<Name>Rensaiō</Name>
<Repository>maxpiva/rensaio:latest</Repository>
<Registry>https://hub.docker.com/r/maxpiva/rensaio</Registry>
<Network>host</Network>
<MyID>rensaio</MyID>
<Shell>sh</Shell>
<Privileged>false</Privileged>
<Support>https://github.com/maxpiva/rensaio/issues</Support>
<Project>https://github.com/maxpiva/rensaio</Project>
<Overview>Rensaiō – a feature-complete series manager powered by Mihon extensions. </Overview>
<Category>MediaManager:Comics</Category>
<Config Name="Config Folder" Target="/config" Default="/mnt/user/appdata/rensaio" Mode="rw" Description="Path to store configuration, database, and settings." Type="Path" />
<Config Name="Series Folder" Target="/series" Default="/mnt/user/media/series" Mode="rw" Description="Path where series and chapters will be downloaded." Type="Path" />
<Config Name="PUID" Target="PUID" Default="99" Mode="rw" Description="User ID to run the container as." Type="Variable" />
<Config Name="PGID" Target="PGID" Default="100" Mode="rw" Description="Group ID to run the container as." Type="Variable" />
<Config Name="UMASK" Target="UMASK" Default="022" Mode="rw" Description="UMASK for file permissions." Type="Variable" />
<WebUI>http://[IP]:9833</WebUI>
<TemplateURL>https://raw.githubusercontent.com/maxpiva/rensaio/main/examples/unraid.xml</TemplateURL>
<Icon>https://raw.githubusercontent.com/maxpiva/rensaio/refs/heads/main/RensaioFrontend/public/rensaio.png</Icon>
</Container>A Helm chart is available at charts/rensaio for running Rensaiō on Kubernetes. It deploys a single container, a Service on port 9833, and PVCs for /config and /series.
helm dependency update ./charts/rensaio
helm install rensaio ./charts/rensaio -n rensaio --create-namespaceConfigure PUID/PGID/UMASK, image tag, PVC sizes/storage classes, and ingress via values.yaml. A sample override — existing PVC claims, a dedicated storage class, and ingress with TLS — is at examples/helm-values.yaml:
helm install rensaio ./charts/rensaio -n rensaio --create-namespace \
-f examples/helm-values.yamlRensaiō can log users in through any OpenID Connect provider (Authentik, Keycloak, Pocket ID, Authelia, Zitadel, ...). Password login keeps working alongside it, and OPDS / MCP access is unchanged because those use the per-user path, not the login.
- Enable Authentication in Settings → Security and set the External Domain (e.g.
https://rensaio.example.com). - At your identity provider, create an OIDC client:
- Type: confidential (with a client secret) or public (PKCE only, no secret). PKCE is always used.
- Redirect / callback URL:
https://rensaio.example.com/api/auth/oidc/callback - Scopes:
openid profile email(addgroupsif you want group mapping)
- Back in Settings → Security, turn on Single Sign-On, fill in the Issuer URL (the provider's base URL, without
/.well-known/openid-configuration), the Client ID and, for a confidential client, the Client Secret. Save. - The login page now shows a Single Sign-On button.
On first sign-in a user is matched to an existing Rensaiō account with the same username (exact match first, then case-insensitive if unambiguous) and linked to it. Later sign-ins use the link, so renaming the account is safe. If no account matches, sign-in is refused unless auto-register is on (see below). The Owner account is never linked and always logs in with its password.
The client secret is write-only: the Settings page never displays it, and saving with the field empty keeps the stored value.
Everything beyond the four basics lives in the Oidc section of appsettings.json. Each key can also be set as an environment variable using the Oidc__Key form, which is convenient for Docker; environment variables override the file, and both override what is stored from the Settings page.
| Key | Default | Description |
|---|---|---|
Enabled, Issuer, ClientId, ClientSecret, ButtonLabel |
(from Settings) | Set here to manage them outside the UI; the Settings fields become read-only |
Scopes |
openid profile email groups |
Scopes requested from the provider |
UsernameClaim |
preferred_username |
Claim used as the Rensaiō username (falls back to name, then email) |
GroupsClaim |
groups |
Claim holding the user's groups |
AdminGroup |
(empty) | Members get the Admin level on every login |
ManagerGroup |
(empty) | Members get the Manager level on every login |
DefaultLevel |
User |
Level for auto-registered users, and for mapped users in neither group |
AutoRegister |
false |
Create a Rensaiō account on first sign-in when none matches |
HidePasswordLogin |
false |
Hide the username/password form and show only the SSO button |
AutoRedirect |
false |
Skip the login page and go straight to the provider |
SyncAvatar |
true |
Copy the provider's profile picture (picture claim) to the user's avatar on each login |
RedirectUri |
(derived) | Override the callback URL when the External Domain is not what the provider sees |
When AdminGroup or ManagerGroup is set, the user's level is re-evaluated on every login that carries the groups claim: in the admin group → Admin, in the manager group → Manager, otherwise DefaultLevel. A login without the groups claim leaves the level untouched. The Owner level is never granted by SSO.
Docker example:
environment:
- Oidc__Enabled=true
- Oidc__Issuer=https://id.example.com
- Oidc__ClientId=rensaio
- Oidc__ClientSecret=xxxxxxxx
- Oidc__AdminGroup=rensaio-admins
- Oidc__AutoRegister=true
- Oidc__HidePasswordLogin=true- A tray application based on Avalonia is available in the Releases.
- Currently tested only on Windows. Testers for Linux and macOS are welcome, as I'm unable to verify it myself.
Build scripts are provided for convenience:
.\build_frontend.ps1Builds the Next.js frontend and packages it as wwwroot.zip for the backend to serve.
.\build_docker.ps1Restores and publishes the backend for linux-x64 and linux-arm64, then builds and pushes a multi-arch Docker image.
.\build_apps.ps1Publishes the backend and tray app for win-x64, win-arm64, linux-x64, linux-arm64, and osx-arm64, then zips the tray binaries.
Be aware: Rensaiō can be memory-intensive, especially when managing large libraries or doing parallel searches and downloads.
Extensions that need a browser context (anti-bot / Cloudflare bypass via the WebViewFetchInterceptor) spawn Chromium renderer processes (jcef_helper --type=renderer), each consuming roughly 80–200 MB. To keep long-running instances from accumulating orphaned helpers and exhausting memory, Rensaiō bounds and reaps them automatically:
| Knob | Default | Meaning |
|---|---|---|
cefMaxRenderers |
4 |
Hard cap on concurrently alive renderer processes across all extensions. Requests beyond the cap degrade to the direct network chain instead of spawning another helper. Also passed to CEF as --max-render-processes. |
cefIdleTimeoutMs |
300000 |
Idle time (ms) before an unused pooled WebView's browser is destroyed by the watchdog sweep (5 minutes). |
cefWebViewPoolEnabled |
true |
Enables host-keyed WebView reuse (same host reuses the same browser/cookie context) instead of a fresh WebView per request. |
These are configurable from Settings → Server (cefMaxRenderers, cefIdleTimeoutMs, cefWebViewPoolEnabled).
How it stays bounded:
- The authoritative renderer budget (
RendererGate) is enforced inside the CEF WebView provider itself, at browser creation — so the cap covers every WebView in the process, including extension-owned ones (e.g. Keiyoushi-stylerunWebView/WebViewSessionhelpers), not just the interceptor path. When the cap is reached the provider refuses to spawn another renderer; the interceptor pre-checks the budget and falls back to the direct network/FlareSolverr chain. - WebViews are pooled per host (
WebViewPool) instead of created per request, and are deterministically destroyed in afinallyblock on success/timeout/error — the old racypostDelayed(destroy)is gone. - A time-gated watchdog sweep runs on the existing safe CEF pump path (the IKVM-attached daemon on Docker, the Avalonia UI thread on desktop) and evicts idle browsers, posting destruction to the main looper. It never calls JCEF from a raw thread.
Validation checklist (long-running instances):
- Run with several WebView-requiring sources active for 24–48 h.
- Monitor with your platform's process tooling (
ps aux --sort=-%memon Linux/macOS, Task Manager on Windows); the number ofjcef_helper --type=rendererprocesses should stay at or belowcefMaxRenderers(plus a short transition window), not accumulate. - Watch the log for
Renderer budget exhausted/WebView pool saturated— these indicate you may want to raisecefMaxRendererson a memory-rich host, or lower it on a constrained one. - No manual process killing is needed on any platform: renderer processes are bounded by the budget and reaped automatically by the watchdog. If the process list ever looks wrong, the fix is to restart Rensaiō (a clean restart tears down CEF entirely), not to kill individual helper processes.
Help clean up the mess left behind by our overenthusiastic friends, Copilot, Claude and Fable (banned).
PRs are welcome to improve stability and architecture.
Licensed under the GNU General Public License v3.0.
This app just works™ until it doesn't. But it's here. Start managing your series with the style it deserves.
