Browse docs

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

  1. Launch Alex. Its local server binds to 127.0.0.1:3210.
  2. Choose Local Folder or S3 / R2 Bucket.
  3. For a local library, select a folder. For S3, enter the bucket, access key, secret key, and any provider-specific endpoint/region.
  4. 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

VariableRequiredDefaultDescription
NEXTAUTH_SECRETYesSigns/encrypts NextAuth session material.
NEXTAUTH_URLRecommendedhttp://localhost:3000 in the supplied Compose fileCanonical app origin; https:// enables secure cookie names.
DATABASE_PATHNo./data/library.dbSQLite path. Docker image sets /app/data/library.db.
LIBRARY_PATHLocal mode./data/libraryRecursively watched folder.
COVERS_PATHNo./data/coversLocal JPEG cover directory.
WATCHER_RS_BINNoAuto-resolvedOverride the Rust binary location.
S3_BUCKETS3 modeEnables S3 mode and names the bucket.
S3_ACCESS_KEY_IDS3 modeS3 access key.
S3_SECRET_ACCESS_KEYS3 modeS3 secret key.
S3_ENDPOINTNon-AWS S3AWS default resolutionR2/MinIO/provider endpoint.
S3_REGIONNoauto in watcher-rsRegion (auto is appropriate for R2).
S3_PREFIXNoEmptyRestrict ingestion to an object-key prefix.
S3_POLL_INTERVALNo60Poll 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.

Next steps