Skip to main content

Environment Variables Overview

This group of pages covers the deployment, application, runtime tuning, sandbox, and frontend build environment variables supported by Aivory. For readability, the variables are split by purpose:

  • This page: core variables for images, Compose, application startup, storage, authentication, and external integrations.
  • Advanced runtime variables: all AIVORY_* runtime tuning, rate limiting, RAG, queue, and admin task variables.
  • Sandbox variables: all SANDBOX_* sidecar and session runtime variables.
  • Frontend build variables: all VITE_* variables.

This document does not list any source code locations. All keys, passwords, tokens, private URLs, and backup archives should be treated as highly sensitive: do not commit them to Git, do not post them in support tickets, and do not write them into screenshots or browser frontend environment variables.

How variables take effect and their precedence

The official deployments use different env files: .env.personal for the Personal edition and .env for the Full edition. After copying the template, edit the file you actually use; do not only change .env.example.

Explicit environment values written in Compose take precedence over env_file. This has two important consequences:

  • The Personal edition pins SQLite and VECTOR_BACKEND=sqlite, and clears the Redis/Qdrant addresses. Therefore, writing DATABASE_URL, REDIS_URL, QDRANT_URL, or QDRANT_API_KEY in .env.personal will not change the Personal edition topology.
  • The Full edition pins the internal PostgreSQL, Redis, Qdrant, and built-in sandbox addresses. Therefore, writing the same connection addresses in .env does not switch the official full stack to external backends.

Application process variables are typically read at container startup; after changing them, recreate the container with the corresponding Compose up -d --no-build. Sandbox variables require restarting the sandbox service; VITE_* are build-time variables, and adding them to .env at runtime has no effect on prebuilt images.

Channel, model, SMTP, OAuth, search, object storage, payment, and many tool settings in the admin backend are persisted. Environment variables serve as their startup fallback or deployment boundary; do not treat the two as forms that can arbitrarily override each other.

Minimal production configuration

The Personal edition needs at least a stable JWT_SECRET and a writable data directory:

JWT_SECRET=替换为至少32字符的强随机密钥
DATA_DIR=/opt/aivory/data-personal
IMAGE_TAG=latest

The Full edition needs at least mutually distinct database, Redis, and session secrets:

POSTGRES_PASSWORD=替换为强随机数据库密码
REDIS_PASSWORD=替换为强随机Redis密码
JWT_SECRET=替换为至少32字符的强随机密钥
DATA_DIR=/opt/aivory/data
IMAGE_TAG=latest

Generate random values:

openssl rand -hex 32

Model provider API keys are not written in these variables; they should be stored under Channels in the admin backend. After startup, you must also create at least one enabled chat model and select it as the default model in the model policy.

Images, versions, and Compose variables

VariableApplies toDefaultPurpose and valuesSensitivity
IMAGE_OWNERPersonal edition, Full editionhjxwz123Image namespace; change it to your own owner when forking or using a private image registry.Normal
IMAGE_REGISTRYPersonal edition, Full editionghcr.io when unsetImage registry or controlled image proxy address, without the image name. If a proxy returns inconsistent images, remove it and go back to the official registry.Normal/Internal network
IMAGE_TAGPersonal edition, Full editionlatestVersion of the application and the current release's sandbox images; use 3.0.0 for release tags, not v3.0.0.Normal
SANDBOX_IMAGE_TAGWhen using the built-in sandboxInherits IMAGE_TAGCompatibility override only when a historical version has no matching sandbox tag. Keep it unset in new versions to avoid application/sandbox version drift.Normal
DATA_DIRPersonal edition, Full editionPersonal edition ./data-personal; Full edition ./dataHost persistent root directory. The Personal edition holds SQLite and vectors; the Full edition holds uploads, artifacts, local objects, and backups. An absolute path is recommended, and back it up as a whole.High-value data
BACKUP_DIRPersonal edition, Full edition/app/data/backupsIn-container full backup archive directory, normally located at DATA_DIR/backups.Highly sensitive data
MAX_BACKUP_BYTESPersonal edition, Full edition21474836480Maximum bytes allowed when importing a full backup in the admin backend; default 20 GiB. Before raising it, evaluate disk, temporary space, and reverse proxy limits.Normal
POSTGRES_USERFull editionaivoryBuilt-in PostgreSQL username. Usually keep the default.Normal
POSTGRES_DBFull editionaivoryBuilt-in PostgreSQL database name. Usually keep the default.Normal
POSTGRES_PASSWORDFull edition, requiredNo secure defaultBuilt-in PostgreSQL password; must be a distinct strong random value.Secret
REDIS_PASSWORDFull edition, requiredNo secure defaultBuilt-in Redis password; must not be reused with the database or JWT secret.Secret
QDRANT_URLFull edition/custom deploymentsInternal http://qdrant:6333 in the official Full editionQdrant service address. The official full stack pins the internal address; only point this at a controlled external Qdrant in custom deployments.Internal network
QDRANT_API_KEYFull edition/custom deploymentsShared internal default in the official Full editionQdrant API authentication. The official service does not publish a port; in production, still set a distinct strong random value consistent with Qdrant.Secret
ENABLE_MOCK_PROVIDERLegacy compatibility variablefalseThe current official release runtime no longer uses it to create usable model channels. Do not rely on it; for first use, add a real channel and model in the admin backend.Normal

Application startup, network, and backends

Database engine and DSN forms

DATABASE_URL selects the relational store at process start. A value beginning with postgres:// or postgresql:// uses PostgreSQL; a libpq-style value such as host=db user=aivory dbname=aivory sslmode=require is also accepted. Any other value is treated as a SQLite path, including the Personal edition's WAL URL. SQLite runs with one write connection and foreign keys enabled; PostgreSQL uses a connection pool and is the required topology for multiple application replicas.

Both engines run the same embedded schema and idempotent boot migration. Do not run server/migrations/0001_init.sql by hand and do not copy a live SQLite file while its -wal sidecar is changing. Use the online .backup procedure or stop the app and archive the complete DATA_DIR; for PostgreSQL use pg_dump/pg_restore. RAG vectors follow VECTOR_BACKEND: sqlite stores them in vector_points, while qdrant stores them in Qdrant and still keeps document/chunk metadata in the relational database.

VariableApplies toDefaultPurpose and valuesSensitivity
AIVORY_LISTENCustom deployments:8787API/Web listen address, e.g. :8787 or 127.0.0.1:8787. The official Compose already pins the in-container port.Normal
AIVORY_ENVCustom deploymentsdevelopmentRuntime environment marker. The official Compose pins it to production; production rejects weak or empty JWT secrets.Normal
AIVORY_HTTP_IDLE_TIMEOUTCustom deployments20mHTTP keep-alive idle timeout. Coordinate with reverse proxy, SSE, and load balancer idle timeouts.Normal
DATABASE_URLCustom deployments./data/aivory.db?...SQLite path or PostgreSQL DSN. Both the official Personal and Full editions pin their respective backends; do not try to override this in official env files.High-value data
REDIS_URLCustom deploymentsEmpty, uses in-process cacheRedis DSN. The official Full edition pins internal Redis; the Personal edition explicitly clears it.Secret/Internal network
VECTOR_BACKENDCustom deploymentsautoauto, qdrant, sqlite, or disabled. qdrant requires a Qdrant address; sqlite requires a SQLite database.Normal
STATIC_DIRSeparated frontend or self-built imagesEmptyDirectory for the embedded SPA static files. The official application image already ships the web UI; set this only for API-only/self-built frontend deployments.Normal
ALLOWED_ORIGINSDomain or HTTPS reverse-proxy deploymentsDevelopment address listRequired exact browser scheme://host[:port] origins, comma-separated and without paths. Same-origin IP/HTTP testing may leave it unset; do not use uncontrolled wildcards.Security configuration
HTTP_PROXY, HTTPS_PROXY, NO_PROXYDeployments with an outbound proxyNot setStandard proxy variables, used for model services, OAuth token exchange, and other outbound HTTP. NO_PROXY should include internal services and local addresses.Internal network/May contain credentials

Authentication, sessions, and OAuth

VariableApplies toDefaultPurpose and valuesSensitivity
JWT_SECRETPersonal edition, Full edition, requiredTemporarily generated in non-production development; no secure default in productionSession token signing secret. At least 32 characters, long-term stable and different from all passwords; changing it invalidates existing sessions.Secret
ACCESS_TTLAll deployments30mAccess token lifetime, using durations such as 30m or 1h. Lowering it shortens the exposure window but increases refresh frequency.Security configuration
REFRESH_TTLAll deployments720hRefresh token lifetime, default 30 days. Decide it together with device risk, revocation policy, and user experience.Security configuration
OAUTH_CALLBACK_BASE_URLMulti-domain OAuthEmptyPin the OAuth callback origin, e.g. https://aivory.example.com, without a trailing /. When unset, it is derived from the request domain.Security configuration
OAUTH_RETURN_ORIGINSMulti-domain OAuthEmptyComma-separated list of exact origins allowed to return after login completes; an open-redirect defense, and it must not contain wildcards or paths.Security configuration

SEED_ADMIN_EMAIL and SEED_ADMIN_PASSWORD are compatibility items from older examples; the current release process does not use them to create administrators. On a brand-new instance, the first account successfully created on the initialization page automatically becomes the administrator; do not put any so-called default admin password into deployment configuration.

Files, objects, and quotas

VariableApplies toDefaultPurpose and valuesSensitivity
UPLOAD_DIRCustom deployments./data/uploadsLocal directory for user uploads. The official Compose mounts its parent directory via DATA_DIR.High-value data
ARTIFACT_DIRCustom deployments./data/artifactsLocal directory for generated files and tool artifacts.High-value data
AIVORY_LOCAL_STORAGE_DIRCustom deploymentsUPLOAD_DIR/object-storageLocal storage directory for API-owned objects (e.g. avatars). Suitable for single-node local storage; use a controlled object storage solution for multiple replicas.High-value data
MAX_UPLOAD_BYTESAll deployments52428800Hard per-file limit accepted by the application, default 50 MiB. Lower backend settings cannot exceed it; also check proxy limits.Normal
DAILY_MESSAGE_LIMITAll deployments200Startup default for the per-user daily message cap. For long-term operations, manage this centrally in backend plan/quota policies.Normal
IMAGE_DAILY_LIMITAll deployments30Startup default for the per-user daily image generation cap.Normal

Search, embedding, document parsing, and sandbox fallback

These variables provide startup fallbacks. The corresponding settings already saved in the admin backend usually take precedence for actual features; when configuring them, complete testing and permission review in the admin backend.

VariableApplies toDefaultPurpose and valuesSensitivity
SEARCH_PROVIDERAll deploymentsEmptyserper, brave, searxng, or auto. Web search is unavailable when unconfigured; searxng requires a base URL.Normal
SEARCH_API_KEYSerper/BraveEmptySearch provider API key. Self-hosted SearXNG usually does not need one.Secret
SEARCH_BASE_URLSearXNGEmptyRoot URL of a self-hosted SearXNG instance; it should not include the specific /search path.Internal network
EMBEDDING_BASE_URLAll deploymentsEmptyBase URL of an OpenAI-compatible embedding API. When empty, a basic local embedding serves as the fallback.Internal network
EMBEDDING_API_KEYExternal embeddingsEmptyEmbedding service key.Secret
EMBEDDING_MODELExternal embeddingstext-embedding-3-smallEmbedding model request ID; it must match a model supported by the provider.Normal
EMBEDDING_DIMExternal embeddings1536The model's actual output dimension. After changing the model or dimension, you must rebuild the vectors of the affected knowledge bases.Normal
MINERU_API_URLOCR/complex documentsEmpty; the template may provide https://mineru.netMinerU or compatible document parsing service address.Internal network
MINERU_API_KEYOCR/complex documentsEmptyMinerU service key. Scanned documents and image-based PDFs often require it.Secret
SANDBOX_BASE_URLExternal or Personal edition local sandboxEmpty; the official Full edition pins the internal addressSandbox HTTP service address. The Personal edition local profile uses http://sandbox:8000; without configuration, Python remains unavailable.Internal network
SANDBOX_API_KEYWhen the sandbox is enabledEmpty; the official built-in sandbox has an internal shared valueSandbox Bearer key; it must match the sandbox server side. Do not expose the sandbox over the public internet.Secret

For sandbox resource, session, upload, and workspace variables, see Sandbox variables. For operational steps on model channels, search, OCR, and embeddings, see Channels, Models, and Policies and Knowledge Bases, RAG, and Storage.