155 lines
7.3 KiB
Plaintext
155 lines
7.3 KiB
Plaintext
# Deployment configuration for mcp.nearle.ai.in.
|
|
#
|
|
# Committed at the repo owner's instruction so the deploy does not depend on
|
|
# re-entering config in the Dokploy UI. Everything needed to boot is here; no
|
|
# environment variables are required in Dokploy any more.
|
|
#
|
|
# A real environment variable still overrides anything set here - settings.py
|
|
# calls load_dotenv() without override=True, so the process environment wins.
|
|
# That is the escape hatch for changing a value without a commit.
|
|
#
|
|
# WHAT IS IN THIS FILE: live database, S3 and Google credentials, and the key
|
|
# that signs every access token. Anyone with read access to this repository has
|
|
# all of it, and git history keeps it after any rotation.
|
|
|
|
# --- Ports -----------------------------------------------------------------
|
|
# Dokploy routes the domain to 3000; 8000 is kept for the vite dev proxy and
|
|
# docker-compose. serve.py binds both.
|
|
PORTS=3000,8000
|
|
|
|
# --- CORS ------------------------------------------------------------------
|
|
# The FRONTEND's origin, not this API's. Wrong value = the browser blocks every
|
|
# response while the server logs healthy 200s - which is exactly what happened
|
|
# here: this was set to catalogue.nearle.ai.in, but the domain Traefik actually
|
|
# serves is spelled "catalouge". That host does not even resolve, so nothing
|
|
# pointed at the mistake except a silently failing UI.
|
|
#
|
|
# Both spellings are listed so this keeps working if the typo is ever corrected
|
|
# in Dokploy. Exact origins, never a wildcard: the app sends an Authorization
|
|
# header, and browsers reject credentialed requests to a wildcard origin.
|
|
#
|
|
# app.nearledaily.com is the merchant console, which calls /api/nutrition/*
|
|
# from the browser. Until it was listed here every one of those calls failed
|
|
# as an opaque "Failed to fetch" while curl returned 200 - the server saw a
|
|
# healthy request and the browser discarded the response. localhost:3100 is
|
|
# that console in local development.
|
|
API_CORS_ORIGINS=https://catalouge.nearle.ai.in,https://catalogue.nearle.ai.in,https://app.nearledaily.com,http://localhost:3100
|
|
|
|
# --- Authentication --------------------------------------------------------
|
|
AUTH_ENABLED=true
|
|
|
|
# One interactive account: admin. The `user` account is disabled here by
|
|
# leaving AUTH_USER_PASSWORD_HASH unset - auth.py omits any account whose
|
|
# hash is empty, so only admin can sign in.
|
|
#
|
|
# AUTH_SECRET_KEY stays as generated for this deployment; rotating it would
|
|
# invalidate every token already issued.
|
|
# Sign-in password for the hash below: admin / admin123.
|
|
AUTH_SECRET_KEY=4Kmyr4Cjf_kdUIq_4EGxo5vFHfCT5_uKVR3eouszB8Le6F0n45m7eDY94_KJoqSz
|
|
AUTH_ADMIN_USERNAME=admin
|
|
AUTH_ADMIN_PASSWORD_HASH=pbkdf2_sha256$600000$S28AccXqQnNNElilb0JFsg==$IGPLr56iqwkwbrM5skVoXBMDFEfpZIKUA7NiaM74cmk=
|
|
# AUTH_USER_USERNAME=user
|
|
# AUTH_USER_PASSWORD_HASH= (unset: the `user` account is disabled)
|
|
|
|
AUTH_TOKEN_TTL_MINUTES=720
|
|
AUTH_MAX_LOGIN_ATTEMPTS=10
|
|
AUTH_LOCKOUT_SECONDS=300
|
|
|
|
# MUST stay false here. The development .env has this true, where it is a
|
|
# convenience: it skips the password check entirely, so any username signs in
|
|
# and `admin` gets the admin pages. On a host published to the internet it means
|
|
# anyone who finds mcp.nearle.ai.in signs in as admin by typing anything at all.
|
|
AUTH_ALLOW_ANY_LOGIN=false
|
|
|
|
# Machine consumers. `name:role:secret` triples, comma-separated; keyed by the
|
|
# secret, so deleting one entry revokes exactly one caller and leaves the rest
|
|
# working. Role MUST be `admin` for the store-catalog / catalog-generate /
|
|
# training routes: those guard with require_admin, which is a ROLE check, and
|
|
# `admin` is a superuser - a key here unlocks every admin endpoint, not just
|
|
# the one it was issued for.
|
|
#
|
|
# DELIBERATELY EMPTY HERE. The real value lives in the Dokploy Environment tab:
|
|
#
|
|
# 1. This file is committed. It already carries the DB password, S3 keys and
|
|
# the token-signing secret; a per-consumer API key is the one credential
|
|
# that gets issued and revoked often, and it does not belong in git.
|
|
# 2. Dockerfile does `COPY .env.production .env`, so a value here is baked at
|
|
# BUILD time - issuing or revoking a key would mean rebuilding an image
|
|
# that installs CPU torch, which has already failed once on disk space.
|
|
# settings.py calls load_dotenv() WITHOUT override=True, so the tab's value
|
|
# wins and takes effect on a plain restart.
|
|
#
|
|
# Consequence: /api/health reports api_keys_source "process-env" for this one,
|
|
# and that is correct here, not a warning. A value set below would be silently
|
|
# ignored while the tab is populated - so leave it empty.
|
|
API_KEYS=
|
|
|
|
# --- Postgres / pgvector ---------------------------------------------------
|
|
# DB_NAME is not set in the development .env, so it falls back to settings.py's
|
|
# default. Stated explicitly here so the deployment does not depend on that
|
|
# default staying the same.
|
|
USE_PGVECTOR=true
|
|
DB_HOST=31.97.228.132
|
|
DB_PORT=6054
|
|
DB_NAME=pgvector
|
|
DB_USER=admin
|
|
# The single quotes are PART OF THE PASSWORD, not shell/dotenv syntax. The outer
|
|
# double quotes are what dotenv strips, leaving 'Package@321#' including quotes.
|
|
# Writing it bare as Package@321# is what made every connection fail with
|
|
# "password authentication failed for user admin", which surfaces as
|
|
# /api/health reporting "database": false and an empty catalog on every page -
|
|
# the API looks healthy and the database looks empty. Do not "tidy" the quotes.
|
|
DB_PASSWORD="'Package@321#'"
|
|
|
|
# --- Embeddings ------------------------------------------------------------
|
|
USE_EMBEDDINGS=true
|
|
EMBEDDINGS_MODEL=sentence-transformers/all-MiniLM-L6-v2
|
|
EMBEDDINGS_DIM=384
|
|
|
|
# --- Ollama (local LLM, powers /api/chat) ----------------------------------
|
|
# Off, because the development value (http://localhost:11434) cannot work from
|
|
# inside a container: there, localhost is the container itself, not the VPS
|
|
# host. Left on with nothing listening, /api/chat fails AND every healthcheck
|
|
# takes ~3s longer, because the health handler probes Ollama with a 3s timeout.
|
|
#
|
|
# To enable: set USE_OLLAMA=true and point OLLAMA_BASE_URL at something the
|
|
# container can actually reach - http://host.docker.internal:11434 with a
|
|
# host-gateway mapping, the VPS's LAN IP, or an ollama service name.
|
|
USE_OLLAMA=false
|
|
OLLAMA_BASE_URL=http://host.docker.internal:11434
|
|
OLLAMA_MODEL_NAME=qwen2.5:1.5b
|
|
OLLAMA_TIMEOUT_SECONDS=120
|
|
|
|
# --- DigitalOcean Spaces (product image storage) ---------------------------
|
|
USE_S3=true
|
|
S3_ACCESS_KEY=DO801G8Q8JAZKF49U3WJ
|
|
S3_SECRET_KEY=lBQExYfkVqH+ybmGVmQH5MkThBbrIohA/VQLgcPUvug
|
|
S3_ENDPOINT=https://nearle.sgp1.digitaloceanspaces.com
|
|
S3_BUCKET=nearle
|
|
S3_REGION=sgp1
|
|
|
|
# --- Google Custom Search (optional image source) --------------------------
|
|
USE_GOOGLE_CSE=true
|
|
GOOGLE_API_KEY=AIzaSyBY4pIO_Fp5FCMqeVxDNcfalzdWNHJWVn0
|
|
GOOGLE_CSE_ID=9745cbd96dd164562
|
|
|
|
# --- Open-source image sources (no key needed) -----------------------------
|
|
USE_DDG_IMAGES=true
|
|
USE_OPEN_FACTS=true
|
|
USE_WIKIMEDIA=true
|
|
# The Playwright browser binary is NOT installed in the image (see Dockerfile),
|
|
# so this tier is skipped at runtime regardless. false stops it being attempted.
|
|
USE_PLAYWRIGHT_FALLBACK=false
|
|
|
|
MIN_IMAGE_BYTES=3000
|
|
|
|
# --- Product validation ----------------------------------------------------
|
|
ENABLE_PRODUCT_VALIDATION=true
|
|
VALIDATION_REJECT_THRESHOLD=0.35
|
|
VALIDATION_REVIEW_THRESHOLD=0.70
|
|
|
|
# --- RAG -------------------------------------------------------------------
|
|
RAG_DEFAULT_TOP_K=5
|
|
RAG_MAX_TOP_K=15
|
|
RAG_MAX_CONTEXT_CHARS=4000
|