Self-hosting TenderCheck AI gives you complete control over your data, lets you run the platform under a custom domain, and ensures that tender documents and proposal PDFs never leave your own infrastructure. All you need is a machine capable of running Docker, a Turso database (the free tier is sufficient), and a Google AI Studio API key for Gemini 2.5 Flash.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/elecodes/TenderCheck-AI/llms.txt
Use this file to discover all available pages before exploring further.
Prerequisites
- Docker 24+ — docs.docker.com/get-docker
- Docker Compose v2 — bundled with Docker Desktop; standalone install at docs.docker.com/compose
- Turso account — turso.tech
- Google AI Studio API key — aistudio.google.com
Docker Compose Configuration
The repository ships with adocker-compose.yml that defines the backend service and wires it to your local source tree for development use:
backend service builds from backend/Dockerfile using a multi-stage Node.js 20 Alpine image. The volume mount (./backend:/app) enables live code reload during development. For a production deployment, remove the volume mount and set NODE_ENV=production — the container will run the compiled dist/ output instead.
The backend/Dockerfile itself uses a two-stage build pattern:
- Builder stage (
node:20-alpine): installs all dependencies, compiles TypeScript, then prunes to production-only packages. - Runner stage (
node:20-alpine): copies only the compileddist/,node_modules, andpackage.jsonfrom the builder and runs as the non-rootnodeuser.
Environment Variables
Create abackend/.env file with the following variables before running docker-compose up:
| Variable | Required | Description | Example |
|---|---|---|---|
TURSO_DB_URL | Yes | Turso database connection URL | libsql://tendercheck-ai.turso.io |
TURSO_AUTH_TOKEN | Yes | Turso auth token from turso db tokens create | eyJh... |
GOOGLE_GENAI_API_KEY | Yes | Primary Gemini API key from Google AI Studio | AIzaSy... |
GOOGLE_API_KEY | Yes | Standard Google AI key (required by Genkit 1.28.0+) | AIzaSy... |
JWT_SECRET | Yes | Secret used to sign and verify JWT session tokens | a-long-random-string-32-chars+ |
ALLOWED_ORIGINS | Yes | Comma-separated list of allowed CORS origins | http://localhost:3000,https://yourdomain.com |
LANGCHAIN_API_KEY | No | LangSmith API key for AI observability and tracing | ls__... |
LANGCHAIN_TRACING_V2 | No | Enable LangSmith tracing (true / false) | true |
LANGCHAIN_PROJECT | No | LangSmith project name | TenderCheckAI |
SENTRY_DSN | No | Sentry DSN for error monitoring | https://...@sentry.io/... |
Build and Run
Create the Backend Environment File
backend/.env in your editor and fill in all required values (see the table above). At minimum you need TURSO_DB_URL, TURSO_AUTH_TOKEN, GOOGLE_GENAI_API_KEY, GOOGLE_API_KEY, JWT_SECRET, and ALLOWED_ORIGINS.Build and Start the Containers
- Build the backend image using
backend/Dockerfile. - Mount your local
backend/directory into the container. - Start the Express server with
npm run dev. - The backend becomes available at http://localhost:3000 (the compose file maps container port 3000 → host port 3000 and sets
PORT=3000for the Docker development environment).
Start the Frontend
The Docker Compose file covers the backend only. Run the frontend separately:For a fully containerised production setup, build the frontend static assets (
When running the backend via Docker Compose (port 3000), Vite’s default port 3000 will already be occupied. Set
VITE_PORT=3001 or configure server.port in vite.config.ts to use a free port for the frontend, and update ALLOWED_ORIGINS in backend/.env to match.npm run build) and serve the frontend/dist/ directory via Nginx or any static file server alongside the backend container.Production Hardening
Before exposing TenderCheck AI to the internet, apply the following hardening measures:- Set
NODE_ENV=productioninbackend/.envand in the Docker Compose environment block to enable production-mode Express optimisations and stricter error handling. - Use a strong
JWT_SECRETof at least 32 random characters. Generate one withopenssl rand -hex 32. - Set
ALLOWED_ORIGINSprecisely — list only the exact frontend domain (e.g.,https://tenders.yourdomain.com). Wildcard or localhost entries must be removed from production configuration. - Enable HTTPS via a reverse proxy. Place Nginx or Caddy in front of the backend container and terminate TLS there. Neither the backend nor the frontend serves HTTPS natively.
- Consider adding a
SENTRY_DSNfor real-time error monitoring and alerting. The backend integrates@sentry/nodewith profiling — simply set the DSN environment variable to activate it. - Do not commit
backend/.envto version control. Use Docker secrets, a secrets manager (e.g., AWS Secrets Manager, HashiCorp Vault), or your CI/CD platform’s environment variable injection for production credentials.
Health Check
The backend exposes a/health endpoint that returns a JSON status object and the current server timestamp. Use it to verify the container started correctly and to configure uptime monitors or load-balancer health probes:
The repository also includes a root-level
Dockerfile for GPU/Ollama on-premise deployments (NVIDIA CUDA + Ubuntu 22.04). That image bundles the full frontend and backend, pre-pulls the Mistral and nomic-embed-text models via Ollama, and uses start.sh as the container entrypoint. It is separate from the backend/Dockerfile used by docker-compose.yml.Cloud Deployment Alternatives
If you prefer a fully managed cloud deployment instead of self-hosting:- Deploy to Vercel → — the recommended path for the frontend and backend as serverless functions, with automatic CI/CD from GitHub.
- Deploy with Docker on Render → — deploy the backend as a Docker Web Service on Render with Turso as the persistent database layer.