Files
Visigine/docker
Ihor_Zhekov 070e1e6e09 fix(nginx): serve .txt as UTF-8 and make AI-discovery files reachable
llms.txt and robots.txt were served without a charset, so browsers
decoded the valid UTF-8 as Windows-1252 and showed mojibake (â€", für).

- Add `charset utf-8;` (+ charset_types) so text responses carry
  `; charset=utf-8`.
- Add an explicit `location ~* \.txt$` that serves the file as plain
  text, returns 404 instead of falling back to the SPA index.html, and
  sets `Access-Control-Allow-Origin: *` so any AI crawler/tool can fetch
  llms.txt / llms-full.txt cross-origin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 12:46:57 +02:00
..

Visigine — Docker

Single-stack compose: nginx serves the built React app on port 8080 and reverse-proxies /api/* to the backend container over the internal docker network. The browser sees one origin — no CORS dance.

Prerequisites

  • Docker Desktop / Docker Engine
  • docker compose v2 plugin (bundled with current Docker Desktop)

First run

# 1. Make sure server/.env exists with MISTRAL_KEY and ADMIN_TOKEN.
#    If you only used the dev flow so far, server/.env is already populated.
cat server/.env

# 2. Build + start (from repo root)
docker compose -f docker/docker-compose.yml up -d --build

# 3. Open
#    UI:     http://localhost:8080
#    Admin:  http://localhost:8080/admin
#    Health: http://localhost:8080/health

Daily ops

# Logs (follow)
docker compose -f docker/docker-compose.yml logs -f

# Restart after backend code change
docker compose -f docker/docker-compose.yml up -d --build backend

# Restart after frontend code change
docker compose -f docker/docker-compose.yml up -d --build frontend

# Stop everything
docker compose -f docker/docker-compose.yml down

# Stop + remove built images
docker compose -f docker/docker-compose.yml down --rmi local

What runs where

Container Image Port Role
visigine-frontend nginx:alpine 8080 Serves dist/ + proxies /api/*
visigine-backend node:20 3001* Express API, Mistral, checks

*Backend port is internal-only. It is expose:d, not ports:d — nothing on your host can hit :3001 directly. The frontend reaches it via the docker network DNS name backend:3001.

Configuration

  • Secrets (MISTRAL_KEY, ADMIN_TOKEN): loaded from ../server/.env.
  • Deployment vars: hard-set in docker-compose.yml. To run on a different host port or domain:
    • Change ports: "8080:80" to whatever you want on the host side.
    • Update ALLOWED_ORIGINS to match the public URL the browser uses.

Notes

  • NODE_ENV=production?debug=1 is unconditionally stripped from responses. The admin dashboard still gets full debug data through /api/admin/analyze (gated by ADMIN_TOKEN).
  • ALLOW_PRIVATE_HOSTS=0 → SSRF guard is fully on. Don't flip this in prod.
  • Nginx strips the browser Origin header before forwarding, so the backend's CORS allow-list only governs cross-origin browsers hitting :3001 directly — which can only happen if you manually -p 3001:3001.