- TypeScript 98.5%
- Python 1.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| .vscode | ||
| docker | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .npmrc | ||
| AGENTS.md | ||
| biome.json | ||
| bun.lock | ||
| package.json | ||
| prisma.config.ts | ||
| pyproject.toml | ||
| README.md | ||
| tsconfig.json | ||
| uv.lock | ||
nmanga-list
To install dependencies:
bun install
To run:
bun run index.ts
This project was created using bun init in bun v1.3.12. Bun is a fast all-in-one JavaScript runtime.
Resource limits for large manga
Large manga can use a lot of RAM/CPU because image conversion + embedding run in worker threads.
Docker limits
docker/docker-compose.yml now includes an app service with hard caps:
cpus: 2mem_limit: 2g
Tune those values based on your machine. Example:
app:
cpus: 1.5
mem_limit: 1536m
App-level throttles
Use these environment variables to reduce workload:
IMAGE_QUEUE_WORKERS(default:1)
Number of manga processed at same time.IMAGE_PAGE_CONCURRENCY(default:2)
Number of pages fetched/converted at same time per worker.MANGA_REFRESH_INTERVAL_HOURS(default:2)
Minimum hours before/api/scrapere-fetches manga metadata/tags again. Within this interval, scrape request returns fresh and skips re-fetch.
Safe low-memory profile:
IMAGE_QUEUE_WORKERS=1
IMAGE_PAGE_CONCURRENCY=1
nhentai 429 handling with temporary proxies
When nhentai responds with HTTP 429, the app now:
- Reads
Retry-Afterwhen available (falls back to 60s, capped at 10m) - Shares one cooldown across all concurrent workers in the same app process
- Uses rotating proxies only while that cooldown is active
Proxy list is loaded once on app startup from ProxyScrape by default.
Optional env vars:
NMANGA_NHENTAI_PROXY_ENABLED(default:true)
Set tofalseto disable proxy usage entirely.NMANGA_NHENTAI_PROXY_LIST_URL(default: ProxyScrape elite list URL)
Override with your own provider URL that returns one proxy per line inprotocol://ip:portformat.NMANGA_NHENTAI_FETCH_TIMEOUT_MS(default:15000)
Per-request timeout for nhentai direct/proxy fetches. Increase if your network/proxy path is slow; decrease to fail over faster.
Remote worker via CLI
You can run additional queue workers on another machine using the same database and S3/MinIO bucket:
bun run cli remote-worker
By default this command starts a worker subprocess with:
- env file:
.env.remote - concurrency:
1 - poll interval:
1000ms
Examples:
# 2 worker loops
bun run cli remote-worker --concurrency 2
# custom env file
bun run cli remote-worker --env-file /etc/nmanga/worker.env --concurrency 2
.env.remote must contain the server connection settings — not just the API
URLs — because the Python embedding worker on the same machine connects to the
database and bucket directly:
API_URL=http://10.0.0.11:3006
API_WS_URL=ws://10.0.0.11:3008/trpc
DATABASE_URL=postgresql://nmanga:CHANGE_ME@10.0.0.11:5432/nmanga?schema=public
MINIO_ENDPOINT=10.0.0.11
MINIO_PORT=9000
MINIO_USE_SSL=false
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_BUCKET=nmanga
Real environment variables take precedence; with bun --env-file the root
.env is not loaded, and the Python workers read .env.remote themselves
(falling back to .env for keys missing there).
All normal scraper/proxy env vars are supported, including:
NMANGA_NHENTAI_PROXY_ENABLEDNMANGA_NHENTAI_PROXY_LIST_URLNMANGA_NHENTAI_FETCH_TIMEOUT_MS
AMD GPU (ROCm) embedding worker
On Windows, uv sync installs ROCm-enabled PyTorch from AMD's index
(torch 2.12.0+rocm10.1.0 for the Radeon RX 9070/XT, target device-gfx1201)
instead of the CPU wheel. Other platforms (Docker/Linux) keep resolving
regular PyPI wheels. The first sync downloads roughly 1.4 GB (ROCm runtime).
Requirements:
- Latest AMD Adrenalin driver
- Python 3.13 / 3.14 (managed by uv)
Verify the GPU is visible:
uv run python -c "import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0), torch.version.hip)"
Embedding workers use the GPU by default (--device cuda); rocm and hip
are accepted as aliases:
uv run scripts/embed_worker.py --once # continuous DB embedding worker
uv run scripts/reembed_images_gpu.py # re-embed stored pages
For a different AMD GPU, change the device-gfx1201 extras on the
torch/torchvision dependencies in pyproject.toml to the matching target
(e.g. device-gfx1100 for the RX 7900 XTX), then run uv lock && uv sync.
If inference crashes or resets the GPU on RX 9070 series, run with
TORCH_BLAS_PREFER_HIPBLASLT=0 to disable hipBLASLt.
Nginx Proxy Manager setup
This app serves HTTP API on port 3000 and tRPC WebSocket on port 3001.
In Nginx Proxy Manager, create a Proxy Host:
- Domain Names:
nmanga.domain.dev - Scheme:
http - Forward Hostname / IP: your app container or host (example:
app) - Forward Port:
3000 - Websockets Support: enabled
Then add this in Advanced:
location /trpc {
set $nmanga_upstream http://app:3000;
if ($http_upgrade = "websocket") {
set $nmanga_upstream http://app:3001;
}
proxy_pass $nmanga_upstream;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
}
Replace app with your actual upstream hostname/IP used by NPM.