Nanahoshi configuration is managed through environment variables and the admin UI.
Environment-based configuration
All core settings are defined via environment variables. See Environment variables for the complete reference.
For production deployment:
- Copy
.env.example to .env
- Generate secure secrets:
# Generate UUIDs
uuidgen # for NAMESPACE_UUID
uuidgen # for DOWNLOAD_SECRET
# Generate auth secret (32+ chars)
openssl rand -hex 32 # for BETTER_AUTH_SECRET
- Configure database, SMTP, and service URLs
- Set Redis and Postgres passwords
Application settings
Runtime settings are stored in the app_settings database table with a key-value structure:
{
id: serial,
key: text,
value: jsonb,
createdAt: timestamp,
updatedAt: timestamp
}
Settings are managed through the admin UI and can include:
- Default library visibility
- Metadata provider preferences
- Scan intervals for cron-watched libraries
- UI customization options
Library configuration
Libraries are the top-level organizational units for your books. Each library:
- Has one or more filesystem paths (
library_path table)
- Belongs to an organization
- Can be public or private
- Optionally supports cron-based automatic scanning
Creating a library
- Navigate to the admin UI
- Create a new library with a name (e.g., “Manga”, “Novels”)
- Add one or more paths pointing to mounted directories
- Enable/disable automatic scanning
- Set visibility (public or organization-only)
Library paths
Each library can have multiple paths:
{
id: bigint,
libraryId: bigint,
path: text, // e.g., "/books/manga"
isEnabled: boolean, // allow toggling without deletion
createdAt: timestamp
}
Paths must match container paths (for Docker) or filesystem paths (for bare-metal). Do not use host machine paths when running in Docker.
User and organization settings
Nanahoshi uses better-auth with the organizations plugin for multi-tenancy:
Organizations
- Each library belongs to an organization
- Users are members of one or more organizations
- Members have roles:
owner, admin, or member
- Organization-scoped libraries are only visible to members
User roles
Global roles:
- admin — Full system access, can view Bull Board queue dashboard
- user — Standard user (default)
Organization roles (per membership):
- owner — Full organization control
- admin — Manage libraries, members, invitations
- member — Read access to organization libraries
CORS configuration
The server enforces CORS via the CORS_ORIGIN environment variable:
CORS_ORIGIN=http://localhost:3001
For multiple origins (not recommended for production), modify apps/server/src/index.ts:
cors({
origin: [env.CORS_ORIGIN, 'https://example.com'],
allowMethods: ['GET', 'POST', 'OPTIONS'],
allowHeaders: ['Content-Type', 'Authorization'],
credentials: true,
})
File scanning behavior
The library scanner:
- Walks all enabled
library_path entries
- Finds supported file types (
.epub, .pdf, .cbz, .zip, etc.)
- Hashes each file to generate a stable
filehash
- Creates
book records with a deterministic UUID (using NAMESPACE_UUID)
- Queues file events for metadata extraction
- Tracks scanned files in
scanned_file table
Deduplication
Books are deduplicated within each library using a composite unique index:
CREATE UNIQUE INDEX books_filehash_per_library_idx
ON book (library_id, filehash);
The same file in different libraries will create separate book records.
Search configuration
Elasticsearch settings:
- Index name:
${ELASTICSEARCH_INDEX_PREFIX}_books (default: nanahoshi_books)
- Analyzer: Sudachi tokenizer for Japanese, standard for other languages
- Indexed fields: title, subtitle, description, author names
The index is automatically created and maintained by the book-index BullMQ worker.
Queue configuration
BullMQ queues use Redis for job storage:
- file-events — Processes file add/delete/update events
- book-index — Indexes books into Elasticsearch
- cover-color — Extracts dominant colors from book covers
Worker concurrency auto-scales based on CPU count. To override, edit worker initialization in packages/api/src/infrastructure/queue/workers/.
SMTP configuration
Email is used for:
- Email verification during registration
- Password reset links
- Organization invitations
Required environment variables:
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=[email protected]
SMTP_PASS=your-app-password # Generate via Google account settings
For Gmail, use an App Password instead of your account password.
Data directory
The server stores generated files in NANAHOSHI_DATA_PATH (default: ./data):
- covers/ — Downloaded/extracted book covers
- thumbnails/ — Resized cover thumbnails
- cache/ — Temporary metadata cache
In Docker, this is mounted as the server_data volume at /app/apps/server/data.
API reference
The OpenAPI reference is auto-generated and served at:
http://localhost:3000/api-reference/
This is built from oRPC procedure definitions in packages/api/src/routers/.