Nitejar Docs
Start Here

Configuration

Environment variables, model config, database options, and encryption.

Nitejar has two config paths depending on how you run it:

  • CLI install path (npx --yes @nitejar/cli@latest up): ~/.nitejar/config/env
  • Source/dev path (pnpm dev from this repo): apps/web/.env

Copy the example and edit it:

cp .env.example apps/web/.env

Which command path are you using?

Use the command path that matches your context:

  1. Published npm CLI (normal users):
npx --yes @nitejar/cli@latest up
# or, if 3000 is occupied
npx --yes @nitejar/cli@latest up --port auto
  1. Local repo test (before publish):
pnpm nitejar:local:up -- --data-dir /tmp/nitejar-local --port auto

Use --full-runtime if you want the real built web runtime instead of the fixture smoke runtime:

pnpm nitejar:local:up -- --full-runtime --data-dir /tmp/nitejar-local --port auto
  1. Pre-publish packaged artifact validation:
pnpm --filter @nitejar/cli build
cd packages/nitejar-cli
PKG_TGZ="$(npm pack --silent)"
cd ../..
npx --yes --package "./packages/nitejar-cli/${PKG_TGZ}" nitejar up --data-dir /tmp/nitejar-pack --port 3002

Most variables are optional.

  • CLI path: ENCRYPTION_KEY and BETTER_AUTH_SECRET are generated automatically on first boot.
  • Source/dev path: set ENCRYPTION_KEY yourself in apps/web/.env; everything else is optional unless that feature is enabled.

Environment variables

VariableRequiredDefaultDescription
NODE_ENVNodevelopmentdevelopment, production, or test. Controls logging verbosity and security warnings.
APP_BASE_URLNoCLI: inferred from selected portPublic URL where Nitejar is reachable. Used to construct webhook callback URLs. Can be overridden by the runtime setting in Settings > Runtime. See Public app URL.
DATABASE_URLNoCLI: ~/.nitejar/data/nitejar.dbSQLite file path or Postgres connection string. Leave unset for source/dev defaults under packages/database/data/.
ENCRYPTION_KEYYes (production)None64-character hex string for AES-256-GCM encryption. Protects API keys, tokens, and secrets stored in the database. See Encryption.
BETTER_AUTH_SECRETYes (production)CLI: auto-generated on first bootStable auth signing secret. Must remain stable across restarts for valid sessions.
OPENROUTER_API_KEYNoNoneOpenRouter API key. The default model routes through OpenRouter, but the free tier requires no key. Set this if you use paid models.
OPENAI_API_KEYNoNoneOpenAI API key. Used as a fallback if no OpenRouter key is set. Also required for embeddings if you don't have an OpenRouter key.
GITHUB_WEBHOOK_SECRETNoNoneSecret for verifying GitHub webhook signatures. Required for GitHub integration.
AGENT_MODELNoarcee-ai/trinity-large-preview:freeDefault model for newly created agents. Existing agents keep their configured model.
POSTGRES_URLNoNoneLegacy Postgres connection string. Deprecated -- use DATABASE_URL instead. Will be removed.

Where to verify

After starting Nitejar, open Settings > Gateway for model provider keys and Settings > Capabilities > Tool Execution for the Sprites key. Runtime settings stored in the app are the source of truth.

Runtime requirements

Nitejar runs as a single web application process. There is no separate worker service, Redis, or queue daemon required for normal operation.

What is required

  • The web app (apps/web)
  • A database -- SQLite by default, Postgres optional

What is optional

  • Sprites -- required only for bash, filesystem, and other sandbox-backed tool execution
  • A public app URL -- required only for inbound webhooks from Telegram, GitHub, Slack, Discord, or external webhook senders
  • Channel-specific credentials -- only for the plugins you enable

SQLite vs Postgres

SQLite is enough for local development and single-node deployments. Postgres is only needed when you want multiple application instances sharing one database or when your hosting environment already standardizes on Postgres.

Database

Nitejar uses Kysely as its query builder with support for two backends.

SQLite (default)

CLI-managed installs set DATABASE_URL to ~/.nitejar/data/nitejar.db.

Source/dev installs can leave DATABASE_URL unset and use the workspace default under packages/database/data/.

SQLite is the right choice for local development, single-node deployments, and "I just want to see this thing run." It handles more traffic than you think.

Postgres

Set DATABASE_URL to a Postgres connection string:

DATABASE_URL=postgres://user:password@host:5432/nitejar

Use Postgres when you need multiple application instances hitting the same database, or when you're deploying to infrastructure that already has a managed Postgres instance.

Migrations

For the CLI path (npx --yes @nitejar/cli@latest up), migrations run automatically before the server starts.

For source/dev workflows, run migrations manually:

pnpm --filter @nitejar/database db:migrate

This detects the database type from DATABASE_URL and applies any pending migrations. The same migration files work for both SQLite and Postgres.

Encryption

Nitejar encrypts sensitive fields in the database using AES-256-GCM. This covers:

  • Gateway API keys (OpenRouter, OpenAI)
  • Plugin instance configuration marked as sensitive (bot tokens, API keys, secrets)
  • Credential store values

Generating a key

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

This produces a 64-character hex string. Put it in your .env:

ENCRYPTION_KEY=a1b2c3d4e5f6...your-64-char-hex-key-here

The key must be exactly 32 bytes. Nitejar accepts it as:

  • 64-character hex string (recommended)
  • 44-character base64 string
  • 32-character raw UTF-8 string

What happens without a key

In development, Nitejar stores values in plaintext and logs a security warning on first write. This is fine for local hacking. It is not fine for anything else.

What happens if you lose the key

Encrypted values become unrecoverable. There is no backdoor, no recovery mechanism, no "contact support." You will need to re-enter every API key and secret through the app. Treat the encryption key like a database password -- back it up somewhere safe.

Rotating the key

There is no built-in key rotation command yet. If you need to rotate: export your config, change the key, re-enter secrets through the app.

Model configuration

Default model

New agents are created with arcee-ai/trinity-large-preview:free via OpenRouter. This is a free model. It works. It costs nothing. Do not change it unless you have a specific reason and an API key that can handle the traffic.

You can override the default for new agents with the AGENT_MODEL environment variable:

AGENT_MODEL=anthropic/claude-sonnet-4

This only affects newly created agents. Existing agents keep whatever model they were configured with.

Per-agent model

Each agent stores its own model setting. Change it in the app:

  1. Go to Agents.
  2. Click the agent.
  3. Under model settings, pick a model from the catalog or type a model identifier.
  4. Save.

The model catalog is populated from the gateway settings. If you're using OpenRouter, any model available on OpenRouter works.

Gateway settings

The gateway controls how Nitejar reaches model providers. Configure it at Settings > Gateway:

  • API Key -- Your OpenRouter or OpenAI key. Stored encrypted in the database.
  • Base URL -- Defaults to https://openrouter.ai/api/v1. Change this if you're running a local proxy, a custom OpenAI-compatible endpoint, or a different provider.

Keys set in the app take priority over environment variables. The resolution order is: gateway database settings, then OPENROUTER_API_KEY env var, then OPENAI_API_KEY env var.

Network and webhooks

Public app URL

This is the URL external services use to reach Nitejar. It must be correct for webhooks to work.

Nitejar resolves the public URL using the first value it finds in this order:

  1. Settings > Runtime > Public app URL -- set in the app, stored in the database. Takes highest precedence.
  2. APP_URL env var
  3. APP_BASE_URL env var
  4. NEXTAUTH_URL env var
  5. NEXT_PUBLIC_APP_URL env var
  6. http://localhost:3000 (fallback)

The runtime setting is the recommended approach for production. It persists across restarts and does not require redeploying or editing environment files. Set it at Settings > Runtime.

Environment variables still work and are fine for local development or CI. If neither the runtime setting nor any env var is set, Nitejar falls back to http://localhost:3000.

Typical setups:

  • Local development: Leave everything unset. http://localhost:3000 is the default.
  • With ngrok: Set APP_BASE_URL=https://your-subdomain.ngrok-free.app in your .env, or set the runtime URL in the app.
  • Production: Set the public URL in Settings > Runtime, or set APP_BASE_URL in your environment. The runtime setting takes priority if both are set.

Webhook URLs

Plugin instances receive webhooks at:

{BASE_URL}/api/webhooks/plugins/{plugin-type}/{instance-id}

For example, a Telegram plugin instance with ID abc123:

https://nitejar.yourdomain.com/api/webhooks/plugins/telegram/abc123

Each plugin instance page shows the full webhook URL. Copy it from there rather than constructing it by hand.

Local development with ngrok

If you need external services to reach your local dev server:

ngrok http 3000 --domain=your-subdomain.ngrok-free.app

Set APP_BASE_URL in your .env to your ngrok URL:

APP_BASE_URL=https://your-subdomain.ngrok-free.app

Or set the URL in Settings > Runtime > Public app URL. The runtime setting takes priority over environment variables.

Nitejar uses this to construct webhook URLs and register them with external services. Without it, Telegram and GitHub have no way to deliver events to your laptop.

Outbound network

Nitejar makes outbound HTTP requests to:

  • Model providers -- OpenRouter (openrouter.ai) or OpenAI (api.openai.com), depending on your gateway config.
  • Sprites -- sprites.dev API, if you have a token configured.
  • Channel APIs -- Telegram Bot API (api.telegram.org), GitHub API (api.github.com), or whatever your plugins talk to.

If you're running behind a corporate firewall, make sure these domains are reachable. Per-agent network policies can further restrict which domains an agent is allowed to contact during runs -- configure those in the agent settings.