Lightweight Deployment (SQLite)
The back end of Aivory is automatically selected by environmental variables when launched: DATABASE_URL 以 postgres:// Start with PostgreSQL, otherwise, for example. .db File path) using built-in SQLite; REDIS_URL Leave empty is used for caching / sequencing in the process; QDRANT_URL Vector retrieval is disabled, and RAG returns to the injection of the full text. Production and development of binaries are the same, SQLite drives have been compiled in the mirror.
This means you can take. Complete production stack 5 Services Cut to 1: Running Only app Containers, data falls into a SQLite file. This page explains who this deployment is for, how compose changes, what limitations are, and how painless migration to Postgres afterwards.
When to choose SQLite model?
| The Scene | Recommended |
|---|---|
| Personal Use / Trial Assessment | SQLite, one container pulled per minute |
| Small teams (one to a dozen people), single deployment | SQLite is usually useful. |
| Small VPS with limited resources (1 core 1 GB level) | The entire stack is unmoving. |
| Requires multiple copies/level extensions | Must Postgres, SQLite is a single writer |
| Intensive writing (many simultaneous conversations, frequent knowledge base writing) | Recommended Postgres |
| Requires external tools to read and write the database directly | Recommended Postgres |
Choosing SQLite is not a hammer sale: the backup format is engine-neutral, and the entire library can be migrated to Postgres at any time (see The following)。
The Smallest Composite Document
only reserve app One of the services: remove. postgres、redis、qdrant Three services and depends_on and take DATABASE_URL Change the path to SQLite file, and ** not set up ** REDIS_URL 和 QDRANT_URL。
name: aivory
services:
app:
image: ghcr.io/${IMAGE_OWNER:-hjxwz123}/aivory-app:${IMAGE_TAG:-latest}
restart: unless-stopped
ports:
- "80:8787"
environment:
AIVORY_ENV: production
# SQLite:非 postgres:// 的值即选中内嵌 SQLite。
# 两个 pragma 分别开启 WAL 日志模式和 5 秒写锁等待。
DATABASE_URL: "/app/data/aivory.db?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000)"
# 不设置 REDIS_URL:使用进程内缓存/队列
# 不设置 QDRANT_URL:禁用向量检索,RAG 走全文注入回退
JWT_SECRET: ${JWT_SECRET:?set JWT_SECRET in .env}
# 试用时可置 true,启用内置演示模型,无需任何真实 API key
ENABLE_MOCK_PROVIDER: ${ENABLE_MOCK_PROVIDER:-false}
volumes:
# 一个目录装下所有持久化数据:aivory.db + uploads/ + artifacts/ + backups/
- ${DATA_DIR:-./data}:/app/data
Compatible with .env Only one must be filled:
# openssl rand -hex 32
JWT_SECRET=<至少 32 字符的强随机值>
Start and verify:
docker compose up -d
curl -fsS http://localhost/api/health
When the system starts for the first time, there are no users, and the first registered account after opening the site automatically becomes an administrator. First operating configuration。
Why database files are placed under /app/data
The mirror-built upload directory, product directory and backup directory are /app/data below (UPLOAD_DIR=/app/data/uploads、ARTIFACT_DIR=/app/data/artifacts、BACKUP_DIR=/app/data/backups Include SQLite documents as well. /app/data A bundle is covered. ** All of ** The Permanent Data:
./data/ # 宿主机目录(DATA_DIR)
├── aivory.db # SQLite 主库
├── aivory.db-wal # WAL 日志(运行期存在,属于数据库的一部分)
├── aivory.db-shm # WAL 共享内存文件
├── uploads/ # 用户上传的文件
├── artifacts/ # 生成的产物
└── backups/ # 管理后台导出的备份归档
If if DATABASE_URL Point to the inside of the container outside of the hanging volume, and once the container is reconstructed, the entire database is gone. DATABASE_URL The default value is ./data/aivory.db?_pragma=journal_mode(WAL)&_pragma=busy_timeout(5000) (Relative process work directory, within the container /app/data/ Below), just falling within the hanging point; explicitly written as an absolute path is to eliminate discrepancies.
Meaning of two pragma parameters
| The Parameter | 值 | Role of |
|---|---|---|
_pragma=journal_mode(WAL) | WAL | Previous PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPrevious PostPre |
_pragma=busy_timeout(5000) | 5000 ms | Wait for up to 5 seconds to report the error instead of failing immediately. |
These two parameters are the default configuration of the server side, which can be copied and is not recommended to delete.
Cut off the cost of Redis and Qdrant
| Eliminated components. | Alternative behavior | The actual impact |
|---|---|---|
postgres | Incorporated SQLite | Single writer limit (see section below); no functional differences |
redis | Caching and sequencing during the process | Single instance functionality is available; the ability to rely on Redis, such as stream recovery, is not enabled; caching and stream limit counting are cleared as the process restarts |
qdrant | The full RAG injection. | Knowledge base is still available, but does not do vector similarity retrieval, but inject the entire document within the scope into the text; the document volume consumes more tokens and retrieval accuracy decreases. |
Selection is independent: You can only replace Postgres with SQLite. redis 和 qdrant Service (reserved accordingly REDIS_URL / QDRANT_URL / QDRANT_API_KEY Environmental variables and depends_on If the knowledge base is a heavy use scenario, it is recommended to retain at least Qdrant.
What about the sandbox?
Sandbox is not related to database selection. When code is required to execute functionality, put the entire stack in sandbox The service moves into your compose file and gives app There are two environmental variables:
environment:
# ...上面的变量保持不变...
SANDBOX_BASE_URL: "http://sandbox:8000"
SANDBOX_API_KEY: ${SANDBOX_API_KEY:-aivory-bundled-sandbox}
See the full definition and security notices for the sandbox service (Docker socket hanging, not publishing ports, etc.) Deployment of Sandbox No code execution is required, and the rest of the functionality is not affected.
Limitations for writers.
SQLite is a single-file embedded database that allows multiple readers and ** A writer . ** This leads to several hard constraints:
-
- Only one
appExample** Open this database file. Do not extend the service to multiple copies, do not have two containers hanging on the same data directory, or use other tools to write the file while the application is running.
- Only one
- Database documents must be ** Local Documentation System ** Do not take up.
DATA_DIRPlaced on NFS or other network file systems, file lock is not reliable and may cause database damage. - There is a upper limit for swallowing.
busy_timeout(5000)This means that when writing at the peak, the subsequent written request ranks for a maximum of 5 seconds; continuous writing pressure buildup will show up as requests slowing down or overtime.
JWT_SECRET is also mandatory under SQLite
Don’t think that “light deployment” will save you this. AIVORY_ENV the value of non-development, 或 DATABASE_URL Is it for Postgres? The minimum compose above is set AIVORY_ENV: production So even if the database is SQLite, JWT_SECRET It must also be set and at least 32 characters, otherwise the app will refuse to start.
Not in the development environment. JWT_SECRET The application automatically generates a random temporary API key. ** Every time you restart all the login sessions are invalid. ** This is prepared for native development, not a deployment option. Any instance of external service should be explicitly set. AIVORY_ENV: production and strong random. JWT_SECRET。
backed up
A major advantage of the SQLite model is that the backup is very small: all persistent data is DATA_DIR in a catalogue.
- ** Filed to:admin console ** The full backup ZIP generated by the Backup & Migration page is engine-neutral (manifest + one JSONL + optional file per table), not affected by the "copy running database files" problem, and can be imported directly to Postgres deployments.
- ** Ready cold ** First of all
docker compose stopA full copy.DATA_DIRAttention to catalog.aivory.db-wal和aivory.db-shmpart of the database, ** No to ** Only in application operation.aivory.dbIn a single file, the unconsolidated writing in the WAL will be lost, and the copied file may also be inconsistent.
Upper limit of imported size MAX_BACKUP_BYTES Control (by default 20 GiB)
Migration with Postgres
The backup format is engine-neutral: SQLite backups can be imported into Postgres deployments, and vice versa, sequences and out keys are automatically processed by the import process. Typical "business growth, upgrade from SQLite to full stack" process:
- ** Exporting old examples **: Generate full backups in the admin console Backup & Migration (select files and vectors, if available), and download ZIP.
- ** Pick up new examples. ** according to Deployment of Docker Compose Start the full stack. After the first start, use ** The same mailbox as the old instance administrator ** Register the first account (it will become an administrator).
- ** imported ** Import ZIP on the Backup & Migration page of the new instance, enter the confirmation word
REPLACEImport is the replacement of the entire library: in one transaction, all tables are empty and reloaded, files and vectors are restored, the current session is terminated, and you need to re-log in with the account password in the backup. - ** Vector Treatment **: If the old instance does not have Qdrant (there is no smallest deployment on this page), there are no vector data in the backup. The new instance can rebuild vectors from existing chunk text in the admin console vector maintenance function without the original file, but it will consume embedded API calls.
After the import is completed, there is an anti-report mechanism: in addition to the "Administrator mailbox for the import operation", the other admin accounts carried in the backup are downgraded to ordinary users.
The reverse process (Postgres migrates to SQLite, for example, with small deployments shrinking back to single containers) is exactly the same, only with the smallest compose file on the cost page for new instances.
View full export options, asynchronous export tasks, configuration exports and imports for details Backup and Migration。
The next step.
- Rapid deployment The standard deployment path of the full stack.
- First operating configuration Register administrator, add the model channel.
- Core environmental variables:
DATABASE_URL/REDIS_URL/QDRANT_URLComplete reference of the selection mechanism. - Backup and Migration Backup formats, import semantics and security mechanisms.