Bring up a minimal working environment first, then move database, cache, storage, and file-processing services to the level required by real usage. For the first deployment, start with the lightweight profile; for long-term multi-user usage, prefer PostgreSQL + Redis.
Before You Start#
DEEIX Chat deployment starts by clarifying three things: where the service runs, which public URLs browsers should use, and where data and files are persisted. Avoid maintaining the same value in multiple places. If environment variables override config.yaml, record the override source so later debugging stays clear.
| Item | Requirement | Notes |
|---|---|---|
| Runtime | Docker and Docker Compose | Recommended for first deployment, lightweight install, standard deployment, and full deployment |
| Config file | Root-level config.yaml | Mounted to /app/config.yaml inside Docker deployments |
| Public URLs | API, Web, and CORS must align | Especially important for separated frontend/backend deployments |
| Security secrets | Must be replaced in production | Do not use example values for jwt_secret or data_encryption_key |
| Persistence | Database, cache, and file volumes | SQLite and local storage still need persistent mounts |
terminal
Choose a Deployment Path#
The five paths cover trials, production-like single-node deployment, full local dependencies, separated frontend/backend hosting, and source development. Choose the path first, then copy the matching template. Mixing fields from different templates is not recommended.
| Path | Best for | Config template | Startup method | Dependency model |
|---|---|---|---|---|
| Lightweight install | Trials, demos, personal deployments, small single-node setups | config.sqlite.example.yaml | docker-compose.sqlite.yml | App + SQLite + sqlite-vec + memory cache |
| Standard deployment | Existing PostgreSQL and Redis | config.example.yaml | docker-compose.yml | App only, database and cache external |
| Full deployment | One machine running app, database, and cache | config.full.example.yaml | docker-compose.full.yml | App + PostgreSQL + Redis |
| Separated deployment | Frontend and API use different public domains | Target environment config | Custom build and static hosting | Static frontend assets and backend API hosted separately |
| Local development | Source changes and frontend/backend debugging | config.example.yaml + frontend/.env.local | Backend make run, frontend pnpm dev | Local PostgreSQL, Redis, and dev servers |
1. Lightweight Install#
The lightweight install starts only the app container. Data is stored in SQLite, vector indexes use sqlite-vec, and cache uses in-process memory. This is the fastest way to evaluate the product, run demos, or host a small single-node setup. For long-term multi-user usage, migrate to PostgreSQL + Redis.
Prepare Configuration#
terminal
Before any public deployment, replace at least security.jwt_secret, security.data_encryption_key, server.public_api_base_url, server.public_web_base_url, and server.cors_allow_origin. You can generate secrets in the configuration guide.
Start the App#
terminal
The default image is ghcr.io/deeix-ai/deeix-chat:latest. To use a local image or test a source build, override the image name.
terminal
Open the Service#
| Service | URL | Purpose |
|---|---|---|
| Web app | http://localhost:8080 | User chat and admin entry point |
| Health check | http://localhost:8080/healthz | Verify that the service started |
| Swagger | http://localhost:8080/swagger/index.html | Inspect backend APIs |
2. Standard Deployment#
The standard deployment starts only the application container. Use it when PostgreSQL, Redis, object storage, or platform infrastructure already exists. Database and Redis addresses must be resolvable and reachable from inside the container. If they run on the Docker host, host.docker.internal is usually the right hostname.
Prepare Configuration#
terminal
Check Connection Settings#
| Setting | Description |
|---|---|
database.postgres.dsn | PostgreSQL connection string; verify container-network reachability |
cache.redis.addr | Redis address; production should prefer Redis over memory cache |
cache.redis.password | Redis password; if empty, verify the network boundary is trusted |
server.public_api_base_url | Public API URL used by browsers, callbacks, and external systems |
server.public_web_base_url | Web URL used for shares, redirects, and notifications |
server.cors_allow_origin | Frontend origin allowed for separated or cross-origin deployments |
Start the App#
terminal
The default docker-compose.yml does not start PostgreSQL or Redis. Keep matching Compose environment variables empty unless you intentionally want them to override config.yaml; otherwise the effective config source becomes hard to audit.
3. Full Deployment#
The full deployment starts App, PostgreSQL, and Redis on one machine. It is closer to the production dependency model than the lightweight profile, works better for long-running single-node usage, and is easier to migrate toward external database, Redis, or managed cloud services later.
Prepare Configuration#
terminal
Before public deployment, replace security secrets, public URLs, CORS, trusted proxies, PostgreSQL password, Redis password, and storage settings.
Start the Full Stack#
terminal
docker-compose.full.yml injects POSTGRES_DSN, REDIS_ADDR, and REDIS_PASSWORD through environment variables. Environment variables have higher priority than config.yaml, so these values override database and Redis settings in the config file. This is intentional so the app container connects to the Compose-managed services.
Check Dependencies#
terminal
If the app fails to start, check whether PostgreSQL finished initialization, whether the Redis password matches, whether config.yaml is mounted, and whether Compose environment variables override the expected fields.
4. Separated Deployment#
Use separated deployment when frontend and backend are exposed through different public origins. For example, the web app runs at https://chat.example.com and the API runs at https://api.example.com. This path requires build variables, CORS, public URLs, and CDN route fallback to align. Read the configuration guide before production release.
Align Public URLs#
| Setting | Example | Description |
|---|---|---|
NEXT_PUBLIC_API_BASE_URL | https://api.example.com | Injected at frontend build time; browsers use it for API requests |
server.public_api_base_url | https://api.example.com | Public backend API URL for callbacks, links, and external systems |
server.public_web_base_url | https://chat.example.com | Public web URL used when the backend generates web links |
server.cors_allow_origin | https://chat.example.com | Frontend origin allowed to call the API cross-origin |
Build the Frontend#
terminal
When publishing frontend/out, the CDN or static server must support route fallback, for example /chat to /chat/index.html. API, health check, and Swagger paths should bypass CDN cache and forward complete headers, request bodies, and response statuses.
Verify After Deployment#
terminal
If the page loads but API calls fail, the usual causes are NEXT_PUBLIC_API_BASE_URL, cors_allow_origin, or reverse-proxy routes not matching. Frontend build variables are embedded into static assets, so changes require rebuilding the frontend.
5. Local Development#
Local development is for source changes, frontend/backend debugging, and UI interaction checks. It is not the shortest trial path. The default config connects to local PostgreSQL and Redis, so make sure those dependencies are running first.
Backend#
terminal
The backend listens on http://localhost:8080 by default, and Swagger is available at http://localhost:8080/swagger/index.html.
Frontend#
terminal
The local frontend usually points to the backend development service.
.env.local
Startup Checks#
After startup, verify health, container status, config mount, and logs. The commands below use the lightweight profile. For the standard profile, omit -f docker-compose.sqlite.yml; for the full profile, replace it with -f docker-compose.full.yml.
terminal
| Check | Expected result | Inspect first when abnormal |
|---|---|---|
| Health check | Service health response | Config parsing, database connection, port conflicts |
| Container status | app is running | Image pull, startup command, dependency status |
| Config mount | /app/config.yaml exists | Startup directory, volume path, file permissions |
| Startup logs | No migration or initialization errors | Database version, secret length, environment overrides |
First Login#
If the database does not contain a superadmin account, the backend creates the initial administrator on first startup and prints the initial password only once. Do not store the initial password in the config file, and do not keep using initial credentials for real operation.
| Item | Description |
|---|---|
| Initial username | admin |
| Initial password | Inspect startup logs, search for bootstrap superadmin created, and read the password field |
| First login | The system requires changing the username and password |
| Later changes | Use the account flow or admin console; credentials are not changed through config.yaml |
Optional File Processing Services#
The base deployment does not require document parsing or OCR services. Start these optional services only when the matching capability is enabled in the admin console or configuration. They are usually related to file extraction, OCR, and RAG indexing, so bring up the base application first and add them gradually.
terminal
These services join deeix-chat-network. Start one root deployment first, or create the network manually.
terminal
| Service | Default URL | Purpose |
|---|---|---|
| Tika | http://127.0.0.1:9998 | Document text extraction |
| Tesseract OCR | http://127.0.0.1:8004/ocr | OCR service |
| Docling | http://127.0.0.1:8005/ocr | Document and OCR extraction |
Next Steps#
After login, finish runtime business configuration before opening the service to real users. Models, upstreams, routes, pricing, file policies, RAG, and MCP tools belong in the admin console rather than hard-coded deployment config.
| Area | Suggested action |
|---|---|
| Upstreams and models | Add upstream channels, platform models, and route bindings |
| Files and RAG | Confirm storage, extraction, OCR, embedding, and retrieval strategy |
| Auth and security | Replace secrets, check CORS, trusted proxies, signup policy, and 2FA |
| Billing and usage | Configure model pricing, subscriptions, top-ups, payments, and webhooks |
| Operations and audit | Check logs, audit events, backups, GeoIP, and OpenTelemetry |