README.md

August 6, 2026 · View on GitHub

DEEIX Chat

An integrated AI platform for enterprise model routing, chat, files, tools, billing, identity, and operations.

English | 简体中文

Website Guide Telegram X License Next.js React Go

Overview

DEEIX Chat is an open-source, deployable AI platform for individuals, teams, and enterprises that need long-term, stable, and unified access to multiple model providers. It provides one clear entry point for multiple upstream models and providers, integrating multimodal chat, model routing, files and RAG, MCP tools, usage billing, identity, audit logs, and operational controls into one product.

The system is designed around simple deployment, efficient static delivery, and a low runtime resource footprint: lightweight without feeling limited, restrained without losing capability, and open without becoming disorderly.

DEEIX Chat workspace

Features

AreaCapabilities
ConversationsA multimodal chat interface for daily use, with streaming, branches, retries, edits, feedback, sharing, rich rendering, and traceable model execution metadata.
Models and routingA platform-model layer for upstream channels, real models, route bindings, priority, weights, circuit breaking, vendor mapping, and capability configuration, reducing the cost of multi-provider operations.
Protocols and adaptationUnified support for OpenAI, Anthropic, Google/Gemini, xAI, OpenRouter, and OpenAI-compatible protocols across text, image, tools, and provider-native capability differences.
Files and retrievalFile upload, preview, extraction, OCR, storage quota, full-context injection, chunking, embeddings, and semantic retrieval so file content can naturally enter the conversation context.
Tool ecosystemMCP servers and provider-native official tools with discovery, enablement, user selection, execution limits, result rendering, and tool-call traceability.
Context and memoryMessage windows, token budgets, summary compression, conversation memory, long-term memory, and RAG evidence records for controlled-cost continuity.
Billing and paymentsModel pricing, per-call tool pricing, subscriptions, top-ups, balances, usage ledgers, billing snapshots, Stripe Checkout, EPay, and webhook validation.
Identity and securityLocal accounts, session management, HttpOnly refresh cookies, 2FA/TOTP, trusted devices, SSO/OIDC/OAuth, contact verification, and encrypted sensitive data.
Administration and auditCentralized management for users, roles, upstreams, models, routes, pricing, subscriptions, balances, usage logs, audit logs, auth events, and system events.
Deployment and operationsSingle-runtime frontend/API serving, Docker deployment, SQLite or PostgreSQL, in-memory cache or Redis, S3-compatible storage, Swagger, structured logs, version endpoint, GeoIP, and OpenTelemetry.

DEEIX Chat image generation DEEIX Chat dark mode

DEEIX Chat usage and billing DEEIX Chat artifacts DEEIX Chat HTML rendering

Architecture and Tech Stack

DEEIX Chat uses a split frontend/backend development model with a single-runtime deployment path. The frontend is built into static assets and served by the Go service, while APIs, authorization, model routing, files, billing, and audit capabilities run in the same backend runtime. Heavy document extraction and OCR capabilities are optional services, keeping the base deployment lightweight.

flowchart TB
  Browser["User / Admin Browser"]

  subgraph Frontend["Frontend Build"]
    Web["Next.js 16 / React 19<br/>Chat UI / Admin Console"]
  end

  subgraph Backend["Go Single Runtime"]
    Static["Static Asset Serving"]
    HTTP["Gin HTTP API"]
    App["Application<br/>Auth / Routing / Files / Billing / Audit"]
    Infra["Infra Adapters<br/>Protocols / Data / Cache / Storage"]
  end

  subgraph External["External Capabilities"]
    Providers["Model Providers<br/>OpenAI / Anthropic / Google / xAI / OpenRouter"]
    Tools["Tool Services<br/>MCP / Provider Native Tools"]
    Extractors["Optional File Processing<br/>Tika / Docling / OCR"]
  end

  subgraph Data["Data and Storage"]
    DB["PostgreSQL + pgvector<br/>or SQLite + sqlite-vec"]
    Cache["Redis<br/>or In-Memory Cache"]
    Storage["Local Filesystem<br/>or S3-Compatible Storage"]
  end

  Web --> Static
  Browser --> Static
  Browser --> HTTP
  HTTP --> App
  App --> Infra
  Infra --> Providers
  Infra --> Tools
  Infra --> Extractors
  Infra --> DB
  Infra --> Cache
  Infra --> Storage
LayerResponsibilityTechnologies
FrontendChat UI, admin console, and static buildsNext.js 16, React 19, TypeScript, Tailwind CSS, Shadcn/UI, Streamdown, KaTeX, Mermaid, Recharts, Motion
Backend runtimeAPIs, authentication, authorization, orchestration, protocol adaptation, and static servingGo 1.26, Gin, Gorm, Swagger, OpenTelemetry, Zap
Data and cacheDomain data, vector retrieval, session state, and runtime cachePostgreSQL, pgvector, SQLite, sqlite-vec, Redis, in-memory cache
Files and storageUploaded files, generated files, object storage, and local persistenceLocal filesystem, S3-compatible object storage
File processingText extraction, OCR, document parsing, and LLM OCR fallbackBuilt-in extractors, Apache Tika, Docling, RapidOCR, Tesseract OCR, Paddle OCR, cloud OCR adapters, MinerU
Tool protocolMCP tool integration and provider-native official toolsMCP Streamable HTTP JSON-RPC, provider-native tools
Deployment runtimeLightweight single-node deployment or multi-node production deploymentDocker, Docker Compose, SQLite/in-memory cache, PostgreSQL/Redis

The backend keeps clear internal boundaries: cmd/internal/cli handles entrypoints, internal/app assembles the application, transport/http owns the HTTP boundary, application coordinates use cases and transactions, domain expresses business semantics, and infra contains database, cache, storage, and external protocol implementations. The data layer uses domain-prefixed tables, while financial records, audit trails, system events, and high-growth vector data remain separate sources of truth.

Quick Start

Quick installation guide: Quick Start.

Local Development

Local development is intended for editing source code and running the frontend and backend separately. The default config connects to local PostgreSQL and Redis. If you only want a low-dependency trial, use the lightweight Docker installation below.

  1. Prepare backend configuration:
cp config.example.yaml config.yaml

Adjust database.postgres.dsn, database.redis.*, and public URLs in config.yaml for your local environment.

  1. Install workspace dependencies and prepare the frontend environment:
pnpm install
cp frontend/.env.example frontend/.env.local
  1. Start the frontend and backend together:
pnpm dev

Use pnpm dev:web or pnpm dev:api to start only one workspace.

The frontend uses NEXT_PUBLIC_API_BASE_URL for API requests. For local development, confirm that frontend/.env.local contains:

NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8080

URLs:

ServiceURL
Frontendhttp://localhost:3000
APIhttp://localhost:8080
Swaggerhttp://localhost:8080/swagger/index.html

If NEXT_PUBLIC_API_BASE_URL is omitted, local development defaults to localhost:8080; same-origin deployments use the current origin.

Docker Deployment

Choose one installation profile first, then copy the matching config file. All root compose profiles expose the app at http://localhost:8080 by default and mount the repository-level config.yaml to /app/config.yaml inside the container.

ProfileUse caseConfig fileCompose fileBuilt-in dependencies
LightweightLocal evaluation, personal use, small single-node deploymentsconfig.sqlite.example.yamldocker-compose.sqlite.ymlApp only, SQLite + sqlite-vec + in-memory cache
DefaultExternal PostgreSQL and Redis already existconfig.example.yamldocker-compose.ymlApp only
FullSingle-machine stack with app, PostgreSQL, and Redisconfig.full.example.yamldocker-compose.full.ymlApp, PostgreSQL, Redis

1. Lightweight Installation: SQLite

This is the lowest-dependency deployment. It starts only the app container, stores data and local vector indexes in SQLite, and uses the in-process memory cache. Use it for local evaluation, personal deployments, and small single-node setups.

cp config.sqlite.example.yaml config.yaml
docker compose -f docker-compose.sqlite.yml up -d

SQLite + memory cache is single-process only. It is good for local use, evaluation, and small single-node deployments. Use PostgreSQL + Redis for multi-node or high-concurrency production deployments.

2. Default Installation: External PostgreSQL + Redis

Use this when PostgreSQL and Redis are already managed outside this compose stack. Before starting, set database and Redis addresses to values reachable from inside the container; if the services run on the Docker host, host.docker.internal is usually the right hostname.

cp config.example.yaml config.yaml
# Edit database.postgres.dsn, database.redis.*, and public URLs.
docker compose up -d

The default docker-compose.yml starts only the application container. Keep compose environment empty unless you intentionally want environment variables to override config.yaml.

3. Full Installation: PostgreSQL + Redis Containers

Use this when you want compose to start the app, PostgreSQL, and Redis together.

cp config.full.example.yaml config.yaml
docker compose -f docker-compose.full.yml up -d

docker-compose.full.yml sets POSTGRES_DSN, REDIS_ADDR, REDIS_USERNAME, and REDIS_PASSWORD in compose environment, so those values override the database and Redis values in config.yaml.

Configuration, Persistence, and Image

Configuration priority is environment variables > config.yaml > built-in defaults. config.yaml is for static infrastructure and security configuration such as server URLs, database, cache, storage, GeoIP, tracing, JWT, and encryption keys. Runtime business settings are stored in the database and managed in the admin console.

The default compose files persist application data:

DataContainer path
SQLite database/app/data/deeix.db
Uploaded and generated files/app/storage
PostgreSQL data/var/lib/postgresql/data, full installation only
Redis data/data, full installation only

The default application image is ghcr.io/deeix-ai/deeix-chat:latest. Override it with DEEIX_CHAT_IMAGE when testing a custom build:

DEEIX_CHAT_IMAGE=deeix-chat:local docker compose up -d --build

APP_ENV accepts dev/development and prod/production, normalizes them to dev or prod, and defaults to prod when omitted. Use dev only for local development. Public production deployments should keep APP_ENV=prod or APP_ENV=production and use production secrets.

Optional Installation Services

These services are optional. Start only the ones you enable in the admin console or config.yaml. They attach to deeix-chat-network; start one root compose profile first, or create the network manually with docker network create deeix-chat-network.

docker compose -f docker/tika/docker-compose.yml up -d
docker compose -f docker/tesseract/docker-compose.yml up -d --build
docker compose -f docker/docling/docker-compose.yml up -d --build

Default local endpoints:

ServiceURLPurpose
Tikahttp://127.0.0.1:9998Document text extraction
Tesseract OCRhttp://127.0.0.1:8004/ocrOCR service
Doclinghttp://127.0.0.1:8005/ocrDocument/OCR extraction

docker/rapidocr currently provides a Dockerfile and app entrypoint, but no compose file. Add a compose file or run it manually if you choose RapidOCR.

Separated Deployment

Use this mode when the frontend and backend are served from different public origins, for example https://chat.example.com and https://api.example.com.

  1. Configure public URLs.

    • Frontend build variable: NEXT_PUBLIC_API_BASE_URL=https://api.example.com
    • Backend config: server.public_api_base_url=https://api.example.com
    • Backend config: server.public_web_base_url=https://chat.example.com
    • Backend config: server.cors_allow_origin=https://chat.example.com

    For Docker image builds, pass the frontend API URL at build time:

    docker build --build-arg NEXT_PUBLIC_API_BASE_URL=https://api.example.com -t deeix-chat .
    
  2. Build and publish the frontend.

    pnpm install
    NEXT_PUBLIC_API_BASE_URL=https://api.example.com pnpm --filter @deeix/web build
    

    The static output is frontend/out. Serve it with Nginx, CDN, object storage, or any static web server. To let the Go backend serve the frontend, place frontend/out under server.frontend_dist_dir; the Docker image defaults to /app/frontend/out.

  3. Apply CDN rules.

    PathRule
    /_next/static/*Cache for 1 year with immutable assets enabled.
    /logo*.svg, /*.ico, /*.png, /*.jpg, /*.webp, /*.woff2Cache for 1 day to 30 days.
    /, /*.html, /chat*, /recent*, /files*, /setting*, /admin*, /share*Do not long-cache. Use no-cache or a short TTL.
    /api/*, /healthz, /readyz, /swagger/*Bypass CDN cache and forward all request headers, methods, query strings, and request bodies.

    If the CDN serves frontend/out from object storage, enable route fallback so clean URLs resolve to their exported index.html files, for example /chat -> /chat/index.html.

Startup Check and First Login

After the application starts, verify the health endpoint, config file, and startup logs. For Docker deployments:

curl http://localhost:8080/healthz
docker compose exec app ls -l /app/config.yaml
docker compose logs app

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.

ItemDescription
Initial usernameadmin
Initial passwordInspect backend startup logs, search for bootstrap superadmin created, and read the password field.
First loginThe system requires changing the username and password.
Later changesUse the account flow or admin console; credentials are not managed through config.yaml.

If a superadmin already exists, the service does not regenerate or print the initial password again.

Configuration

Full configuration guide: Configuration.

Backend configuration is split into static runtime configuration and runtime business settings. Static runtime configuration describes branding and the infrastructure, security, and storage parameters required to start the service, and is provided through config.yaml and environment variables. Runtime business settings cover product capabilities such as authentication, conversations, models, files, and billing; they are stored in system_settings and maintained from the admin console. Environment variables override matching config-file values, which is useful for containerized deployments, separated deployments, and secret injection.

At startup, the backend resolves the default config file from the working directory: starting from the repository root reads config.yaml, while starting from backend/ reads ../config.yaml. Docker deployments usually mount host ./config.yaml as read-only /app/config.yaml inside the container. If the config file is stored elsewhere, set CONFIG_FILE to a path accessible from the running process or container.

Frontend branding is also runtime configuration. Set the branding section in config.yaml, then restart the application; rebuilding the frontend or Docker image is not required. See Custom branding.

Static configuration environment variables:

AreaEnvironment variablePurpose
Frontend buildNEXT_PUBLIC_API_BASE_URLBrowser API base URL; set in frontend/.env.local for local dev or at build time for separated deployment.
Config fileCONFIG_FILEOptional config file path; Docker values should use the container path.
ApplicationAPP_NAMEApplication name.
ApplicationAPP_ENVRuntime environment: dev/development or prod/production; omitted values default to prod.
HTTP serviceHTTP_PORTAPI/runtime port.
HTTP serviceCORS_ALLOW_ORIGINAllowed CORS origins, comma-separated.
HTTP serviceTRUSTED_PROXIESTrusted proxy CIDR list.
HTTP servicePUBLIC_API_BASE_URLPublic API URL for links, callbacks, and public URL generation.
HTTP servicePUBLIC_WEB_BASE_URLPublic Web URL for links, callbacks, and public URL generation.
HTTP serviceFRONTEND_DIST_DIRFrontend static output directory.
HTTP serviceHTTP_READ_HEADER_TIMEOUT_SECONDSHTTP read-header timeout.
HTTP serviceHTTP_READ_TIMEOUT_SECONDSHTTP request read timeout.
HTTP serviceHTTP_IDLE_TIMEOUT_SECONDSHTTP keep-alive idle timeout.
HTTP serviceHTTP_MAX_HEADER_BYTESMaximum HTTP request header size.
SecurityJWT_SECRETJWT signing secret.
SecurityDATA_ENCRYPTION_KEYKey material for upstream API keys, SSO secrets, MCP tokens, sensitive settings, and TOTP secrets.
SecuritySSRF_PROTECTION_ENABLEDEnables outbound SSRF protection.
SecuritySSRF_ALLOWED_HOSTSExact hostnames for deployment-level integrations or trusted private redirect targets, comma-separated.
SecuritySSRF_ALLOWED_CIDRSTrusted deployment-level integration or private redirect CIDRs, comma-separated.
SecurityTURNSTILE_SITEVERIFY_URLCloudflare Turnstile siteverify endpoint.
DatabaseDATABASE_DRIVERpostgres or sqlite.
PostgreSQLPOSTGRES_DSNPostgreSQL DSN.
PostgreSQLPOSTGRES_MAX_OPEN_CONNSMaximum open connections.
PostgreSQLPOSTGRES_MAX_IDLE_CONNSMaximum idle connections.
PostgreSQLPOSTGRES_CONN_MAX_LIFETIME_MINUTESMaximum connection lifetime.
PostgreSQLPOSTGRES_CONN_MAX_IDLE_TIME_MINUTESMaximum idle connection time.
SQLiteSQLITE_PATHDatabase file path.
SQLiteSQLITE_DSNFull DSN; takes priority over path-based DSN construction.
SQLiteSQLITE_MAX_OPEN_CONNSMaximum open connections, default 1.
SQLiteSQLITE_BUSY_TIMEOUT_MSBusy timeout.
SQLiteSQLITE_CACHE_SIZE_KBPage cache size.
SQLiteSQLITE_MMAP_SIZE_BYTESMmap size.
SQLiteSQLITE_SYNCHRONOUSSynchronous mode: OFF, NORMAL, FULL, or EXTRA.
SQLiteSQLITE_TEMP_STORETemporary storage: DEFAULT, FILE, or MEMORY.
CacheCACHE_DRIVERredis or memory; memory is single-process only.
RedisREDIS_ADDRRedis address.
RedisREDIS_USERNAMERedis ACL username; leave empty for password-only/default-user Redis.
RedisREDIS_PASSWORDRedis password.
RedisREDIS_DBRedis DB number.
RedisREDIS_TLS_ENABLEDEnable TLS for Redis connections, for example Upstash Redis.
RedisREDIS_TLS_INSECURE_SKIP_VERIFYSkip Redis TLS certificate verification; keep false unless required by a nonstandard endpoint.
StorageSTORAGE_BACKENDlocal or s3.
Local storageSTORAGE_ROOT_DIRLocal file storage directory.
S3 storageSTORAGE_S3_ENDPOINTS3-compatible endpoint.
S3 storageSTORAGE_S3_REGIONS3 region; required when S3 storage is enabled.
S3 storageSTORAGE_S3_BUCKETS3 bucket; required when S3 storage is enabled.
S3 storageSTORAGE_S3_PREFIXS3 object prefix.
S3 storageSTORAGE_S3_ACCESS_KEY_IDS3 Access Key ID.
S3 storageSTORAGE_S3_SECRET_ACCESS_KEYS3 Secret Access Key.
S3 storageSTORAGE_S3_FORCE_PATH_STYLEWhether to use path-style access.
GeoIPGEOIP_PROVIDERnone, ipwhois, ipinfo, or mmdb.
GeoIPGEOIP_BASE_URLGeoIP HTTP service URL, default https://ipwho.is.
GeoIPGEOIP_TOKENGeoIP service token.
GeoIPGEOIP_TIMEOUT_MSGeoIP request timeout.
GeoIPGEOIP_DATABASE_URLMMDB download URL.
GeoIPGEOIP_DATABASE_PATHLocal MMDB path.
GeoIPGEOIP_DATABASE_MAX_BYTESMaximum MMDB download size.
GeoIPGEOIP_REFRESH_INTERVAL_HOURSMMDB refresh interval.
OpenTelemetryOTEL_ENABLEDEnables tracing; when omitted, a configured endpoint enables tracing automatically.
OpenTelemetryOTEL_EXPORTER_OTLP_ENDPOINTOTLP collector endpoint.
OpenTelemetryOTEL_EXPORTER_OTLP_HEADERSOTLP headers in key=value,key2=value2 format.
OpenTelemetryOTEL_EXPORTER_OTLP_INSECUREWhether to use plaintext transport.
OpenTelemetryOTEL_EXPORTER_OTLP_PROTOCOLOTLP exporter protocol: grpc, http, or http/protobuf; defaults to grpc.
OpenTelemetryOTEL_TRACES_SAMPLER_ARG / OTEL_SAMPLING_RATETrace sampling rate from 0 to 1; OTEL_TRACES_SAMPLER_ARG takes priority.

Authentication, registration, conversation settings, model option policies, file processing, RAG, embedding, MCP, billing, payments, and announcements are runtime business settings, not static YAML configuration. Their defaults are seeded by the backend and maintained in the admin console.

When SSRF protection is enabled in production, administrator-saved model, MCP, Embedding, OIDC/OAuth2, and custom Turnstile endpoints are authorized locally by exact origin (scheme + host + port) and do not require entries in the global allowlist. Model, MCP, and Embedding redirects retain standard compatibility: public cross-origin targets are allowed, while private cross-origin targets must match SSRF_ALLOWED_HOSTS or SSRF_ALLOWED_CIDRS; OIDC/OAuth2 and Turnstile keep their stricter identity boundary. Generated media is downloaded, validated, and stored by the backend: a private artifact URL inherits trust only when it has the same origin as the selected model endpoint; public cross-origin artifact URLs remain subject to the strict public-network policy, and private cross-origin artifact URLs are blocked. The global allowlist also remains available for deployment-level integrations that cannot be tied to an administrator-saved endpoint, such as selected GeoIP or extraction deployments. Link-local, multicast, unspecified, and known metadata targets always remain blocked. Invalid allowlist entries stop backend startup, and global allowlist changes require a restart.

OAuth callbacks for Web, App, and Desktop (multi-platform clients not yet released)

Set PUBLIC_API_BASE_URL to the externally reachable API origin before enabling the provider auth bridge. For every OIDC/OAuth2 provider, register the server callback shown in the admin provider dialog:

<PUBLIC_API_BASE_URL>/api/v1/auth/providers/<provider-slug>/callback

Web, App, and Desktop clients then reuse that instance callback automatically. The external provider authorization code and client secret remain on the self-hosted server; public clients receive only a short-lived, one-time DEEIX grant bound to their PKCE verifier. Keep the legacy Web callback shown by the admin dialog registered when account identity binding or older Web clients are still in use.

Feature Guides

Security Notes

  • User passwords are hashed with bcrypt.
  • Production mode rejects unsafe default secrets, weak encryption keys, wildcard CORS, and non-HTTPS public URLs.
  • Refresh tokens and recovery-style secrets are stored as hashes.
  • Upstream API keys, SSO client secrets, MCP auth tokens, sensitive settings, and TOTP secrets are encrypted with AES-GCM using DATA_ENCRYPTION_KEY.
  • Access tokens are short-lived and held client-side in memory; refresh tokens are issued through HttpOnly cookies.
  • User-supplied model options are filtered before provider requests. System-generated fields such as model, messages, tools, system prompts, headers, and previous-response identifiers are not user-overridable.

Documentation

Acknowledgements

DEEIX Chat is built on the open-source ecosystem. Thanks to all maintainers and communities in the AI tooling ecosystem.

Contact & Community

License

DEEIX Chat is licensed under the Apache License 2.0.