You're reading docs for Nextly Alpha. APIs may change between releases.

Configuration

Environment Variables

Every environment variable Nextly reads, organized by category with required vs. optional indicators.

Nextly reads environment variables for database connections, authentication, storage, email, and other runtime settings. Most live in the central env schema (packages/nextly/src/shared/lib/env.ts); storage adapter env vars are per-adapter and read by the adapter packages directly.

Copy .env.example to .env and fill in values:

cp .env.example .env

Canonical .env.example

The base template templates/base/.env.example ships the minimum required variables:

.env.example
# Nextly Configuration
# Generated by create-nextly-app

# Database Configuration
DB_DIALECT=postgresql
DATABASE_URL=postgresql://user:password@localhost:5432/nextly_dev

# Authentication (REQUIRED)
# Generate with: openssl rand -base64 32
NEXTLY_SECRET=change-me-generate-a-secure-secret

# Application URL
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Storage (per-adapter — see "Storage" section below)

The create-nextly-app scaffolder fills in DB_DIALECT, DATABASE_URL, and an auto-generated 32-byte base64 NEXTLY_SECRET for you. For a production deployment, regenerate NEXTLY_SECRET with:

openssl rand -base64 32

Database

Source: packages/nextly/src/shared/lib/env.ts.

VariableRequiredDefaultDescription
DB_DIALECTYespostgresqlDatabase dialect: postgresql, mysql, or sqlite.
DATABASE_URLYes (PostgreSQL/MySQL)Full database connection URL. Required for postgresql and mysql; optional for sqlite (paired with SQLITE_PATH). Validated as a URL.
SQLITE_PATHOptional (SQLite only)file:./data/nextly.db (factory default)SQLite file path; alternative to DATABASE_URL for the sqlite dialect.
DB_POOL_MAXNo20Max connections in the pool. Min: 1.
DB_POOL_MINNo2Min connections in the pool. Min: 0.
DB_POOL_IDLE_TIMEOUTNo30000Idle connection timeout in milliseconds. Min: 1000.
DB_QUERY_TIMEOUTNo15000Query timeout in milliseconds. Min: 1000.
DB_HEALTHCHECK_INTERVAL_MSNo30000Health-check interval in milliseconds. Min: 1000.
DB_SNAKE_CASENofalseUse snake_case for database column names instead of camelCase.

Connection-string formats

# PostgreSQL (recommended for production)
DATABASE_URL=postgresql://user:password@localhost:5432/nextly_dev

# MySQL
DATABASE_URL=mysql://root:root@localhost:3306/nextly_dev

# SQLite (development / single-instance only)
DATABASE_URL=file:./dev.db
# or
SQLITE_PATH=./dev.db

Runtime

VariableRequiredDefaultDescription
NODE_ENVNodevelopmentRuntime environment: development, production, or test. Affects production-only checks below.

Authentication

Nextly uses a custom JWT auth system (access + refresh tokens, sessions, API keys, RBAC). There is no OAuth.

VariableRequiredDefaultDescription
NEXTLY_SECRETYes (production: ≥ 32 chars)Secret used to sign JWTs and other crypto. Production startup throws if it is missing or shorter than 32 characters. Generate with openssl rand -base64 32.
NEXTLY_ALLOWED_ORIGINSNoComma-separated list of additional origins allowed for CSRF validation (e.g. https://admin.example.com,https://staging.example.com). The app's own origin is always allowed.

Application URLs

VariableRequiredDefaultDescription
NEXT_PUBLIC_APP_URLYes (production)Public-facing app URL. Used in client-side code and as the fallback for email-link baseUrl. Production startup throws if missing.
API_BASE_URLNohttp://localhost:3000/apiBase URL for API routes. Validated as a URL.

Storage (per-adapter)

The default storage backend is local disk under ./public/uploads/. No env vars are needed for default storage.

Cloud adapters are opt-in. The variables below are read by the adapter packages, not by the central env schema, so they only need to exist when you actually configure that adapter in nextly.config.ts. Nothing else (env-validation, etc.) checks for them.

S3 / S3-compatible — @nextlyhq/storage-s3

Works with AWS S3, Cloudflare R2, MinIO, and DigitalOcean Spaces. The plugin accepts these values directly; the env-var names below are the conventional ones used in our examples (and what your nextly.config.ts typically references with process.env.X).

VariableRequiredDescription
S3_BUCKETYesBucket name.
AWS_REGIONYesAWS region (e.g. us-east-1). Use auto for Cloudflare R2.
AWS_ACCESS_KEY_IDYesAccess key ID.
AWS_SECRET_ACCESS_KEYYesSecret access key.
S3_ENDPOINTSometimesCustom endpoint URL. Required for R2 and MinIO.
S3_PUBLIC_URLNoPublic URL prefix (e.g. https://pub-xxxx.r2.dev for R2 or a CDN domain).
S3_FORCE_PATH_STYLENoSet true for MinIO and other path-style providers.
nextly.config.ts
import { s3Storage } from "@nextlyhq/storage-s3";

storage: [
  s3Storage({
    bucket: process.env.S3_BUCKET!,
    region: process.env.AWS_REGION!,
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
    },
    endpoint: process.env.S3_ENDPOINT,
    forcePathStyle: process.env.S3_FORCE_PATH_STYLE === "true",
    publicUrl: process.env.S3_PUBLIC_URL,
    collections: { media: true },
  }),
];

Vercel Blob — @nextlyhq/storage-vercel-blob

Recommended for Vercel deployments.

VariableRequiredDescription
BLOB_READ_WRITE_TOKENYesVercel Blob token from the Vercel dashboard. The adapter reads this directly when the token config option is omitted.

UploadThing — @nextlyhq/storage-uploadthing

VariableRequiredDescription
UPLOADTHING_TOKENYesUploadThing API token. The adapter reads this directly when the token config option is omitted.

Email / SMTP

Source: packages/nextly/src/shared/lib/env.ts. Required only if you send emails (password resets, notifications). In production, if any SMTP variable is set, all four of SMTP_HOST, SMTP_USER, SMTP_PASS, SMTP_FROM must be set or the env validator throws.

VariableRequiredDefaultDescription
SMTP_HOSTNoSMTP server hostname (e.g. smtp.gmail.com).
SMTP_PORTNo587SMTP port. 587 for TLS, 465 for SSL. Range: 1–65535.
SMTP_USERNoSMTP authentication username.
SMTP_PASSNoSMTP authentication password.
SMTP_FROMNoFrom address for outgoing emails. Validated as an email.

For local development, the repo ships a Mailpit profile (docker compose --profile with-mailpit up -d mailpit) on host ports 1025 (SMTP) and 8025 (web UI) — see Email guide for details.


Security

These env vars are read by middleware and security helpers. None are part of the central env schema; they are read directly by the modules that use them.

VariableRequiredDefaultDescriptionRead by
TRUSTED_PROXY_IPSNoemptyComma-separated CIDR list of trusted reverse-proxy IPs. Combined with security.trustProxy: true, controls which X-Forwarded-For values are honoured for client-IP resolution (rate limiting, refresh-token binding, audit logging).packages/nextly/src/utils/get-trusted-client-ip.ts

Performance — permission cache

Nextly's RBAC layer ships a hybrid (in-memory LRU + database) permission cache. These env vars tune it; none are part of the central env schema — they are read directly by the permission service.

VariableRequiredDefaultDescriptionRead by
PERMISSION_CACHE_ENABLEDNotrueSet to false or 0 to disable the hybrid permission cache.packages/nextly/src/services/lib/permissions.ts
PERMISSION_CACHE_TTL_SECONDSNo86400Time-to-live for database cache entries (seconds).packages/nextly/src/services/lib/permissions.ts
PERMISSION_CACHE_MEMORY_SIZENo10000In-memory LRU cache size (number of entries).packages/nextly/src/services/lib/permissions.ts

The database permission cache benefits from periodic cleanup. A typical daily cron:

0 2 * * * curl -X POST http://localhost:3000/api/auth/cache/cleanup

Debug

VariableRequiredDefaultDescriptionRead by
DEBUG_RBACNoSet 1 to log detailed RBAC permission decisions.packages/nextly/src/services/lib/permissions.ts
DEBUG_CACHENoSet 1 to log permission-cache hit/miss/eviction details.packages/nextly/src/domains/auth/services/permission-cache-service.ts

Docker development (optional)

Used by the bundled docker-compose.yml for local Postgres / Redis / Adminer / Drizzle Studio / Mailpit setup. Not needed when connecting to an existing database.

VariableDefaultDescription
DB_NAMEnextly_devPostgreSQL database name.
DB_USERpostgresPostgreSQL user.
DB_PASSWORDPostgreSQL password. Override in production.
DB_PORT5432PostgreSQL host port.
ADMINER_PORT8080Adminer (database browser) UI port.
REDIS_PORT6379Redis cache port.
DRIZZLE_STUDIO_PORT4983Drizzle Studio port for the database GUI.

Example .env files

Minimal production

# Runtime
NODE_ENV=production

# Database
DB_DIALECT=postgresql
DATABASE_URL=postgresql://user:password@db.example.com:5432/nextly_prod

# Auth
NEXTLY_SECRET=your-generated-secret-at-least-32-characters-long
NEXT_PUBLIC_APP_URL=https://your-domain.com

# Storage (Vercel Blob example)
BLOB_READ_WRITE_TOKEN=vercel_blob_rw_xxxxxxxxxxxx

Development with S3-compatible storage (MinIO)

# Database
DB_DIALECT=postgresql
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/nextly_dev

# Auth
NEXTLY_SECRET=dev-secret-minimum-32-characters-long-replace-in-production
NEXT_PUBLIC_APP_URL=http://localhost:3000

# Storage (MinIO)
S3_BUCKET=nextly-dev
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=minioadmin
AWS_SECRET_ACCESS_KEY=minioadmin
S3_ENDPOINT=http://localhost:9000
S3_FORCE_PATH_STYLE=true

Next steps