Installation
Install the desktop app or run Alex with Docker or Node.js
Alex can run as a desktop app, a Docker service, or a standalone Next.js/Rust application. All three support a local library folder or an S3-compatible bucket.
Desktop app
The desktop app manages its embedded Next.js server, SQLite database, ingestion watcher, and optional public-access tunnel for you.
Downloads
The current release workflow publishes a signed and notarized macOS arm64 DMG/ZIP plus Linux x64/arm64 AppImage and deb packages. Windows NSIS packaging exists in the source configuration, but Windows artifacts are not published by the current release workflow.
Alex does not currently auto-update; install a newer package when you want to upgrade.
First run
- Launch Alex. Its local server binds to
127.0.0.1:3210. - Choose Local Folder or S3 / R2 Bucket.
- For a local library, select a folder. For S3, enter the bucket, access key, secret key, and any provider-specific endpoint/region.
- Choose Get Started and let the initial scan finish.
Packaged database, cover, and config.json files live in Electron's platform user-data directory. Original books remain in the folder or bucket you selected.
Public access
Under Admin → Users, Public Access (Relay) can assign a stable https://<three-words>.alexreader.app URL and open an outbound WebSocket tunnel. You do not need port forwarding or local TLS configuration.
The public hostname exposes the app but does not log remote visitors in. They need an Alex account for private pages; tokenized shared-collection URLs remain public.
Docker
Docker is the simplest always-on server installation. Published images target Linux amd64 and arm64.
Prerequisites
- Docker with Compose support
- A long random NextAuth secret
Generate a secret with:
openssl rand -base64 32
Local-folder mode
services:
alex:
image: jamesacklin/alex:latest
ports:
- "3000:3000"
environment:
DATABASE_PATH: /app/data/library.db
LIBRARY_PATH: /app/data/library
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:?Set NEXTAUTH_SECRET in .env}
NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000}
volumes:
- alex-data:/app/data
- /path/to/your/books:/app/data/library
restart: unless-stopped
volumes:
alex-data:
Create .env beside the Compose file:
NEXTAUTH_SECRET=paste-the-generated-value-here
NEXTAUTH_URL=http://your-server:3000
Use the real externally reachable HTTPS URL for NEXTAUTH_URL when Alex is behind an HTTPS reverse proxy.
S3 mode
Remove the local books bind mount and add S3 settings:
services:
alex:
image: jamesacklin/alex:latest
ports:
- "3000:3000"
environment:
DATABASE_PATH: /app/data/library.db
COVERS_PATH: /app/data/covers
NEXTAUTH_SECRET: ${NEXTAUTH_SECRET:?Set NEXTAUTH_SECRET in .env}
NEXTAUTH_URL: ${NEXTAUTH_URL:-http://localhost:3000}
S3_BUCKET: my-books
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY}
S3_ENDPOINT: https://<account-id>.r2.cloudflarestorage.com
S3_REGION: auto
S3_PREFIX: books/
S3_POLL_INTERVAL: 60
volumes:
- alex-data:/app/data
restart: unless-stopped
volumes:
alex-data:
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
NEXTAUTH_SECRET | Yes | — | Signs/encrypts NextAuth session material. |
NEXTAUTH_URL | Recommended | http://localhost:3000 in the supplied Compose file | Canonical app origin; https:// enables secure cookie names. |
DATABASE_PATH | No | ./data/library.db | SQLite path. Docker image sets /app/data/library.db. |
LIBRARY_PATH | Local mode | ./data/library | Recursively watched folder. |
COVERS_PATH | No | ./data/covers | Local JPEG cover directory. |
WATCHER_RS_BIN | No | Auto-resolved | Override the Rust binary location. |
S3_BUCKET | S3 mode | — | Enables S3 mode and names the bucket. |
S3_ACCESS_KEY_ID | S3 mode | — | S3 access key. |
S3_SECRET_ACCESS_KEY | S3 mode | — | S3 secret key. |
S3_ENDPOINT | Non-AWS S3 | AWS default resolution | R2/MinIO/provider endpoint. |
S3_REGION | No | auto in watcher-rs | Region (auto is appropriate for R2). |
S3_PREFIX | No | Empty | Restrict ingestion to an object-key prefix. |
S3_POLL_INTERVAL | No | 60 | Poll interval in seconds. |
First login and seed behavior
Open http://your-server:3000 and sign in with:
- Email:
admin@localhost - Password:
admin123
Change this immediately.
The current Docker entrypoint runs pnpm db:seed on every container start. That command upserts the default admin and resets its seeded password, display name, and role. Be aware of this behavior when changing that account in a Docker deployment.
Standalone Node.js
Use this option for development or when you want to manage the Next.js and Rust processes yourself.
Prerequisites
- Node.js 20.9 or later (the Docker image uses Node 22)
- Corepack and the repository-pinned pnpm 10.33.2
- A stable Rust toolchain
Setup
git clone https://github.com/jamesacklin/alex.git
cd alex
pnpm setup
pnpm setup installs dependencies, creates .env with a random NextAuth secret, builds/resolves the Rust bridge, creates the database, and seeds the default admin.
For manual setup:
pnpm install
cp .env.example .env
# Replace NEXTAUTH_SECRET in .env
pnpm db:push
pnpm db:seed
Development
Run two terminals:
pnpm dev
pnpm watcher
pnpm watcher uses local mode unless S3_BUCKET is set. The dev server listens on port 3000 by default.
Production
Build and start the standalone server, and keep the watcher running as a separately supervised process:
pnpm build
node .next/standalone/server.js
pnpm watcher
Persist the database, covers, and local library paths across deployments. Place Alex behind HTTPS before exposing a server to the internet, and set NEXTAUTH_URL to that public origin.