Commit 6b1191d6 authored by Artem Baranovskyi's avatar Artem Baranovskyi
Browse files

Partial solution with Nginx user access separation (to be finished).

Summarising.
parent 5c4d4470
...@@ -2,8 +2,9 @@ HF_TOKEN= ...@@ -2,8 +2,9 @@ HF_TOKEN=
LANGCHAIN_API_KEY= LANGCHAIN_API_KEY=
PORT=3000 PORT=3000
FLOWISE_USERNAME= # Flowise student's access creds on http://localhost:3000/
FLOWISE_PASSWORD= FLOWISE_USERNAME=student
FLOWISE_PASSWORD=student
APIKEY_PATH=/root/.flowise APIKEY_PATH=/root/.flowise
SECRETKEY_PATH=/root/.flowise SECRETKEY_PATH=/root/.flowise
...@@ -14,7 +15,21 @@ DATABASE_TYPE=postgres ...@@ -14,7 +15,21 @@ DATABASE_TYPE=postgres
DATABASE_PORT=5432 DATABASE_PORT=5432
DATABASE_HOST=localhost DATABASE_HOST=localhost
DATABASE_NAME=flowise DATABASE_NAME=flowise
DATABASE_USER= DATABASE_USER=user
DATABASE_PASSWORD= DATABASE_PASSWORD=pass
PGSSLMODE=require PGSSLMODE=require
OLLAMA_CPU=1
OLLAMA_KEEP_ALIVE=5m
OLLAMA_NUM_PARALLEL=1
OLLAMA_HOST=http://localhost:11435
#MODEL_NAME=llama3.2:1b
MODEL_NAME=bartowski/DeepSeek-R1-Distill-Qwen-14B-GGUF
OLLAMA_MODEL=llama3.2:1b
MODEL=llama3.2:1b
# Nginx
NGINX_PORT=8080
# Nginx admin access creds on http://localhost:8080/
ADMIN_USER=admin
ADMIN_PASSWORD=admin
\ No newline at end of file
...@@ -23,14 +23,16 @@ services: ...@@ -23,14 +23,16 @@ services:
container_name: flowiseai container_name: flowiseai
hostname: flowise hostname: flowise
healthcheck: healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:${PORT} test: ["CMD", "curl", "-f", "http://localhost:3000/api/v1/health"]
interval: 5s interval: 60s
timeout: 5s timeout: 20s
retries: 5 retries: 10
start_period: 120s
ports: ports:
- ${PORT}:${PORT} - ${PORT}:${PORT}
volumes: volumes:
- ./flowiseai:/root/.flowise - ./flowiseai:/root/.flowise
env_file: .env
environment: environment:
DEBUG: 'false' DEBUG: 'false'
PORT: ${PORT} PORT: ${PORT}
...@@ -46,9 +48,12 @@ services: ...@@ -46,9 +48,12 @@ services:
DATABASE_NAME: ${DATABASE_NAME} DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USER: ${DATABASE_USER} DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD} DATABASE_PASSWORD: ${DATABASE_PASSWORD}
# DATABASE_URL: postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@flowise-db:${DATABASE_PORT}/${DATABASE_NAME}?sslmode=disable
depends_on: depends_on:
- ollama flowise-db:
- flowise-db condition: service_healthy
ollama:
condition: service_started
entrypoint: /bin/sh -c "sleep 3; flowise start" entrypoint: /bin/sh -c "sleep 3; flowise start"
networks: networks:
- flowise_network - flowise_network
...@@ -62,16 +67,54 @@ services: ...@@ -62,16 +67,54 @@ services:
volumes: volumes:
- ollama_data:/root/.ollama - ollama_data:/root/.ollama
ports: ports:
- "11434:11434" - "11435:11434"
env_file: .env
environment: environment:
HF_TOKEN: ${HF_TOKEN} HF_TOKEN: ${HF_TOKEN}
GIN_MODE: ${GIN_MODE} GIN_MODE: ${GIN_MODE}
OLLAMA_CPU: "1"
OLLAMA_HOST: ${OLLAMA_HOST}
OLLAMA_MODEL: ${OLLAMA_MODEL}
MODEL_NAME: ${MODEL_NAME}
networks:
- flowise_network
nginx:
image: nginx:alpine
ports:
- "${NGINX_PORT}:80"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/.htpasswd:/etc/nginx/.htpasswd
depends_on:
- flowise
- htpasswd-generator
# flowise:
# condition: service_healthy
# htpasswd-generator:
# condition: service_completed_successfully
networks:
- flowise_network
htpasswd-generator:
image: httpd:alpine
command: sh -c "htpasswd -Bbn $${ADMIN_USER} $${ADMIN_PASSWORD} > /etc/nginx/.htpasswd"
env_file: .env
environment:
ADMIN_USER: ${ADMIN_USER}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
volumes:
- ./nginx:/etc/nginx
networks: networks:
- flowise_network - flowise_network
restart: on-failure
volumes: volumes:
flowise-db-data: flowise-db-data:
ollama_data: ollama_data:
networks: networks:
flowise_network: flowise_network:
\ No newline at end of file driver: bridge
name: flowise_network
attachable: true
\ No newline at end of file
events {}
http {
server {
listen 80;
# Public chat interface
location / {
proxy_pass http://flowise:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Admin API (protected)
location /api/v1/ {
#allow 192.168.1.0/24; # Access only from internal network
#deny all;
# Basic Auth for admins
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# Flowise auth headers
proxy_set_header Authorization $http_authorization;
proxy_pass_header Authorization;
proxy_pass http://flowise:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Exclude login endpoint from basic auth
location /api/v1/login {
proxy_pass http://flowise:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
\ No newline at end of file
...@@ -20,6 +20,9 @@ COPY load_model.py /app/load_model.py ...@@ -20,6 +20,9 @@ COPY load_model.py /app/load_model.py
ARG HF_TOKEN ARG HF_TOKEN
ENV HF_TOKEN=${HF_TOKEN} ENV HF_TOKEN=${HF_TOKEN}
ARG MODEL_NAME
ENV MODEL_NAME=${MODEL_NAME}
COPY start.sh /app/start.sh COPY start.sh /app/start.sh
RUN chmod +x /app/start.sh RUN chmod +x /app/start.sh
......
# load_model.py
import os import os
from transformers import AutoModelForCausalLM, AutoTokenizer from transformers import AutoModelForCausalLM, AutoTokenizer
...@@ -6,8 +7,7 @@ hf_token = os.environ.get("HF_TOKEN") ...@@ -6,8 +7,7 @@ hf_token = os.environ.get("HF_TOKEN")
if hf_token is None: if hf_token is None:
raise ValueError("Hugging Face token is not set") raise ValueError("Hugging Face token is not set")
model_name = "meta-llama/Llama-3.2-1B" model_name = os.environ.get("MODEL_NAME")
model = AutoModelForCausalLM.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name) tokenizer = AutoTokenizer.from_pretrained(model_name)
......
#!/bin/bash #!/bin/bash
# start.sh
MODEL_NAME="llama3.2:1b"
if ! ollama list | grep -q "$MODEL_NAME"; then if ! ollama list | grep -q "$MODEL_NAME"; then
echo "Model is not found. Loading..." echo "Model is not found. Loading..."
ollama pull "$MODEL_NAME" HUGGING_FACE_HUB_TOKEN=${HF_TOKEN} ollama pull "$MODEL_NAME"
else else
echo "Model is already loaded." echo "Model is already loaded."
fi fi
ollama run "$MODEL_NAME" & ollama serve &
ollama serve sleep 10
\ No newline at end of file ollama run "$MODEL_NAME"
tail -f /dev/null
\ No newline at end of file
### IMPETUS Educational Chatbot Project
The **IMPETUS** project focuses on developing specialized chatbots for educational purposes, analyzing student-bot interactions to optimize learning experiences. The initiative leverages **LangChain** for chatbot prototyping and **Flowise** for workflow management, with emphasis on secure deployment, database integration, and access control.
---
### Project Overview
**Primary Goal**: Investigate optimization strategies for educational chatbots and identify effective prompting techniques to maximize student engagement.
**Focus Areas**:
- Interaction analytics via custom database logging
- Secure deployment architecture for chatbot interfaces
- Migration from SQLite to PostgreSQL for long-term scalability
- Access control separation between admin/student interfaces
**Core Technologies**:
- **LangChain**: Python-based framework for LLM pipeline construction ([Documentation](https://python.langchain.com/docs/tutorials/))
- **Flowise**: Drag-and-drop UI for chatbot workflows ([GitHub Integration Example](https://github.com/AXRoux/Flowise-LangChain))
- **Docker**: Containerization for service isolation and deployment reproducibility
**Project Repositories**:
[https://transfer.hft-stuttgart.de/gitlab/22baar1mst/flowise-ollama](https://transfer.hft-stuttgart.de/gitlab/22baar1mst/flowise-ollama)
[https://github.com/ArtemBaranovsky/flowise-ollama](https://github.com/ArtemBaranovsky/flowise-ollama) (mirror)
### Key Objectives
1. **Global Service Installation**:
- Dockerize Flowise/LangChain for system-wide availability
- Separate student-facing chat interface (port 3000) from admin panel
2. **Database Migration**:
- Replace SQLite with PostgreSQL for production-grade reliability
- Implement volume persistence for critical data
3. **Security Hardening**:
- Isolate administrative endpoints via Nginx routing
- Implement Basic Auth with fallback to JWT/OAuth2
4. **LLM Infrastructure**:
- Integrate Ollama for local model management
- Configure RAG (Retrieval-Augmented Generation) workflows
---
### Implementation Highlights
#### 1. Dockerized Architecture
```yaml
# docker-compose.yml (simplified)
services:
flowise:
image: flowiseai/flowise:latest
ports: ["3000:3000"]
depends_on: [postgres, ollama]
postgres:
image: postgres:16-alpine
volumes: ["./pgdata:/var/lib/postgresql/data"]
ollama:
build: ./ollama-models
ports: ["11435:11434"]
nginx:
image: nginx:alpine
ports: ["8080:80"]
configs: ["./nginx/:/etc/nginx/"]
```
#### 2. Access Control Implementation
```nginx
# nginx.conf (security routing)
location /admin/ {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://flowise:3000/api/v1/;
}
location /chat/ {
proxy_pass http://flowise:3000/;
}
```
#### 3. Ollama Model Integration
```Dockerfile
# Custom Ollama Dockerfile
FROM ollama/ollama
RUN ollama pull ${MODEL_NAME}
CMD ["ollama", "serve"]
```
---
### Challenges & Solutions
| Challenge | Resolution |
|-----------|------------|
| **Flowise Admin/Chat Interface Collision** | Implemented Nginx path-based routing with Basic Auth |
| **SQLite Scalability Limitations** | Migrated to PostgreSQL with automated schema migration |
| **Model Loading Failures** | Created pre-loading script for Ollama containers |
| **Student Access Exploits** | Added IP filtering + rate limiting in Nginx |
Stable implemented version of this simple solution is at https://transfer.hft-stuttgart.de/gitlab/22baar1mst/flowise-ollama/-/commit/5c4d44705f550546423afcd06bc7e69a54e4276a
**Unresolved Issues**:
- Basic Auth bypass vulnerabilities in shared port configuration
- LangChain migration incomplete due to time constraints
---
### Deployment Workflow
1. **Infrastructure Setup**:
```bash
ssh impetus@193.196.53.83 -i <key.pem>
docker-compose up -d --build
```
2. **Environment Configuration**:
```.env
DATABASE_URL=postgresql://user:pass@postgres:5432/db
OLLAMA_MODEL=llama2-uncensored
NGINX_PORT=8080
```
3. **Security Hardening**:
```bash
# Generate admin credentials
htpasswd -c ./nginx/.htpasswd admin
```
---
### Future Development Plan
1. **LangChain Migration**:
- Port Flowise workflows to LangChain agents
- Implement dual interface system:
- `/chat` – student-facing endpoint
- `/admin` – JWT-protected management UI
2. **Enhanced Security**:
- Implement OAuth2 via Keycloak/Linkding
- Add audit logging for all admin actions
3. **CI/CD Pipeline**:
- Automated Docker builds on GitLab
- Canary deployment strategy
4. **Analytics Integration**:
- ClickHouse for interaction telemetry
- Grafana dashboard for usage metrics
---
### Conclusion
The IMPETUS project demonstrates a viable architecture for educational chatbots using Dockerized LLM components. While Flowise provided rapid prototyping capabilities, future work will focus on transitioning to LangChain for greater flexibility. The current implementation achieves:
- Isolated PostgreSQL database with persistent storage
- Basic access control through Nginx
- Local LLM management via Ollama
**Next Steps**: Address security vulnerabilities in access control and complete LangChain migration using [Flowise-LangChain integration templates](https://volcano-ice-cd6.notion.site/Introduction-to-Practical-Building-LLM-Applications-with-Flowise-LangChain-03d6d75bfd20495d96dfdae964bea5a5).
---
(Due to technical issues, the search service is temporarily unavailable.)
### Deployment Guide: Flowise-Ollama Chatbot System
#### Prerequisites
1. **Docker** and **Docker Compose** installed
2. **Hugging Face Account** (for accessing LLM models)
3. Minimum **8GB RAM** and **20GB Disk Space**
---
### Step-by-Step Deployment
#### 1. Clone Repository
```bash
git clone https://transfer.hft-stuttgart.de/gitlab/22baar1mst/flowise-ollama.git
cd flowise-ollama
```
#### 2. Configure Environment
Create `.env` file or copy from .env.Example:
```ini
# Database
DATABASE_NAME=flowise
DATABASE_USER=admin
DATABASE_PASSWORD=SecurePass123!
DATABASE_TYPE=postgres
DATABASE_PORT=5432
# Flowise
PORT=3000
FLOWISE_USERNAME=admin
FLOWISE_PASSWORD=AdminSecure456!
# Ollama
HF_TOKEN=your_huggingface_token
GIN_MODE=release
```
Don't forget to register and use credentials for
HF_TOKEN=
LANGCHAIN_API_KEY=
#### 3. Start Services
```bash
docker-compose up -d --build
```
*This will:*
- Launch PostgreSQL database with persistent storage
- Start Flowise with Ollama integration
- Automatically load specified LLM models
#### 4. Verify Services
```bash
docker ps -a
```
Expected output:
```
CONTAINER ID IMAGE STATUS PORTS
a1b2c3d4e5f6 flowiseai/flowise:latest Up 5 minutes (healthy) 0.0.0.0:3000->3000/tcp
g7h8i9j0k1l2 postgres:16-alpine Up 5 minutes (healthy) 5432/tcp
m3n4o5p6q7r8 ollama Up 5 minutes 0.0.0.0:11434->11434/tcp
```
#### 5. Access Flowise UI
1. Open `http://localhost:3000` in browser
2. Log in using credentials from `.env`:
- **Username**: `admin`
- **Password**: `AdminSecure456!`
#### 6. Import Chatflow
1. Navigate to **Chatflows****Add New**
2. Import `Ollama_RAG_Chatflow.json` (drag-and-drop or use file picker)
3. Configure RAG parameters:
```json
{
"model": "llama2-uncensored",
"temperature": 0.7,
"max_tokens": 500
}
```
#### 7. Test Ollama Integration
```bash
curl http://localhost:11434/api/tags
```
Expected response:
```json
{"models":[{"name":"llama2-uncensored","modified_at":"2024-03-15T12:34:56.789Z"}]}
```
---
### Key Endpoints
| Service | URL | Port |
|---------|-----|------|
| Flowise UI | `http://<server-ip>:3000` | 3000 |
| Ollama API | `http://<server-ip>:11434` | 11434 |
| PostgreSQL | `postgres://admin:SecurePass123!@localhost:5432/flowise` | 5432 |
---
### Troubleshooting
1. **Healthcheck Failures**:
```bash
docker logs flowiseai --tail 50
docker exec -it flowise-db psql -U admin -d flowise
```
2. **Model Loading Issues**:
```bash
docker exec ollama ollama list
docker exec ollama ollama pull llama2-uncensored
```
3. **Port Conflicts**:
Update `PORT` in `.env` and restart:
```bash
docker-compose down && docker-compose up -d
```
---
### Security Recommendations
1. Add Nginx reverse proxy with SSL
2. Implement IP whitelisting for `/api/v1` endpoints
3. Rotate database credentials monthly
4. Monitor Ollama GPU utilization:
```bash
docker stats ollama
```
This deployment provides a fully functional educational chatbot system with RAG capabilities. For advanced configuration, refer to [Flowise-Ollama Integration Guide](https://github.com/ArtemBaranovsky/flowise-ollama).
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment