Deployment Guide - Windows Server with WSL#
This guide covers deploying EngiAI on Windows Server using WSL (Windows Subsystem for Linux) with Docker.
Prerequisites#
1. Enable WSL on Windows Server#
Open PowerShell as Administrator and run:
# Enable WSL
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
# Enable Virtual Machine Platform
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
# Restart the server
Restart-Computer
After restart, set WSL 2 as default:
wsl --set-default-version 2
2. Install Ubuntu on WSL#
# Install Ubuntu 22.04
wsl --install -d Ubuntu-22.04
# Launch Ubuntu (it will ask you to create a user)
wsl
3. Install Docker Desktop for Windows#
Download Docker Desktop from: https://www.docker.com/products/docker-desktop
Install Docker Desktop
In Docker Desktop settings:
Enable “Use the WSL 2 based engine”
Under “Resources > WSL Integration”, enable integration with your Ubuntu distribution
Deployment Steps#
Step 1: Transfer Archives to Server#
Transfer the release archives to your Windows Server:
# Example using SCP (from your local machine)
scp engiai-v1.1.0.zip user@server-ip:C:\Temp\
scp prusa-mcp-server-v1.1.0.zip user@server-ip:C:\Temp\
Or use any file transfer method (RDP, file share, etc.)
Step 2: Extract Archives in WSL#
Open WSL Ubuntu terminal:
# Create deployment directory
mkdir -p ~/deployments
cd ~/deployments
# Copy archives from Windows to WSL
cp /mnt/c/Temp/engiai-v1.1.0.zip .
cp /mnt/c/Temp/prusa-mcp-server-v1.1.0.zip .
# Extract archives
unzip engiai-v1.1.0.zip -d engiai
unzip prusa-mcp-server-v1.1.0.zip -d .
# Navigate to the application directory (match the -d target above; if the
# archive nests a top-level folder, cd into that instead)
cd engiai
Step 3: Configure Environment Variables#
Create a .env file with your configuration:
# Copy the example environment file
cp .env.example .env
# Edit the .env file with your settings
nano .env
Required environment variables:
# OpenAI API Key (required)
OPENAI_API_KEY=sk-...
# Google API Key (required)
GOOGLE_API_KEY=sk-...
# Keyless web search (default)
SEARCH_PROVIDER=duckduckgo
# Optional: SEARCH_PROVIDER=tavily and TAVILY_API_KEY=tvly-...
# LLM Configuration
LLM_MODEL=openai:gpt-4.1
# Database Configuration — set POSTGRES_PASSWORD before deploying
POSTGRES_PASSWORD=change_me
DATABASE_URL=postgresql://engiai_user:${POSTGRES_PASSWORD}@postgres:5432/engineer_assistant
# Papers Directory (optional, for bulk import)
PAPERS_SOURCE_DIR=/path/to/papers
# MCP Configuration
SKIP_MCP=false
PRUSA_TOKEN_FILE=./data/prusa_tokens.json
Step 4: Authenticate with Prusa Account#
Run the one-time OAuth2 login on the host — this opens a small native webview
window on account.prusa3d.com, you sign in, and refresh tokens are written to
./data/prusa_tokens.json (the same file the container reads).
make prusa-login
WSL / Linux note: the login opens a graphical window via
pywebview. On Linux you need system WebKit2GTK (sudo apt install gir1.2-webkit2-4.1 libgirepository1.0-dev) and a working X11/Wayland display forwarded into WSL. If the server is truly headless, runmake prusa-loginon a desktop machine (macOS, Windows, or Linux with a GUI) and copy the resulting./data/prusa_tokens.jsonfile to the server.
Step 5: Build and Start the Application#
# Build and start all services. Go through the wrapper: it creates the
# MMORE bind-mount targets that a bare `docker compose` would turn into
# directories, which kills the RAG service (and with it the chatbot).
./docker-compose-wrapper.sh up -d --build
# Check that all services are running
./docker-compose-wrapper.sh ps
Expected output:
NAME STATUS PORTS
engiai-chatbot Up (healthy) 0.0.0.0:8501->8501/tcp
engiai-postgres Up (healthy) 0.0.0.0:5432->5432/tcp
mmore-rag-service Up (healthy) 0.0.0.0:8000->8000/tcp
prusa-mcp-server Up (healthy) 0.0.0.0:8765->8765/tcp
excalidraw-mcp-server Up (healthy) 127.0.0.1:8766->8766/tcp
Step 6: Access the Application#
The application will be accessible at:
Streamlit UI: http://localhost:8501
From other machines: http://server-ip:8501
Accessing from Windows Host#
If you want to access the application from the Windows host (not just WSL):
Find your WSL IP address:
hostname -I
Access the application at:
http://<wsl-ip>:8501
Or configure port forwarding to make it accessible via Windows localhost:
# In PowerShell (as Administrator)
netsh interface portproxy add v4tov4 listenport=8501 listenaddress=0.0.0.0 connectport=8501 connectaddress=<wsl-ip>
Firewall Configuration#
If you need to access the application from external machines:
# In PowerShell (as Administrator)
# Allow inbound traffic on port 8501
New-NetFirewallRule -DisplayName "EngiAI" -Direction Inbound -LocalPort 8501 -Protocol TCP -Action Allow
Managing the Application#
View Logs#
# View all logs
./docker-compose-wrapper.sh logs
# View specific service logs
./docker-compose-wrapper.sh logs chatbot
./docker-compose-wrapper.sh logs prusa-mcp-server
# Follow logs in real-time
./docker-compose-wrapper.sh logs -f
Stop the Application#
./docker-compose-wrapper.sh down
Restart the Application#
./docker-compose-wrapper.sh restart
Update the Application#
# Stop the current version
./docker-compose-wrapper.sh down
# Pull/extract new version
cd ~/deployments
unzip engiai-vX.X.X.zip -d engiai-new
cd engiai-new
# Copy your .env file from the old version
cp ../engiai/.env .
# Rebuild and start
./docker-compose-wrapper.sh build
./docker-compose-wrapper.sh up -d
Persistence and Backups#
Data Persistence#
The application stores data in:
Database: PostgreSQL volume
postgres_data(namedengiai_postgres_data)Conversations:
./data/conversations.db(if using SQLite)Papers:
./data/directoryOutputs:
./outputs/directory
Warning
docker compose down -v deletes the engiai_postgres_data volume and with
it the whole conversation history. Use a plain docker compose down (or
make docker-down) to stop the stack; pass -v only when you intend to wipe
the database. Back up first — see below.
Backup Data#
# Backup database
docker-compose exec postgres pg_dump -U engiai_user engineer_assistant > backup.sql
# Backup data directory
tar -czf data-backup-$(date +%Y%m%d).tar.gz data/
# Backup outputs
tar -czf outputs-backup-$(date +%Y%m%d).tar.gz outputs/
Restore Data#
# Restore database
docker-compose exec -T postgres psql -U engiai_user engineer_assistant < backup.sql
# Restore data directory
tar -xzf data-backup-20250117.tar.gz
Troubleshooting#
Services Not Starting#
Check logs:
./docker-compose-wrapper.sh logs
Network Issues#
Ensure services are on the same network:
docker network ls
docker network inspect engiai_engiai
Container Cannot Resolve Prusa MCP Server#
Restart all services:
./docker-compose-wrapper.sh down
./docker-compose-wrapper.sh up -d
WSL Memory Issues#
Configure WSL memory limits in Windows:
Create C:\Users\YourUsername\.wslconfig:
[wsl2]
memory=8GB
processors=4
swap=2GB
Restart WSL:
wsl --shutdown
wsl
Port Already in Use#
Check what’s using the port:
sudo lsof -i :8501
Or change the port in docker-compose.yml:
ports:
- "8502:8501" # Use port 8502 instead
Production Recommendations#
1. Use a Reverse Proxy#
For production, use Nginx as a reverse proxy:
sudo apt update
sudo apt install nginx
# Create Nginx configuration
sudo nano /etc/nginx/sites-available/engiai
Example Nginx configuration:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:8501;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/engiai /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
2. Enable HTTPS#
Use Let’s Encrypt:
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
3. Set Up Auto-Start#
Create a systemd service to auto-start on boot:
sudo nano /etc/systemd/system/engiai.service
[Unit]
Description=EngiAI
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/home/your-user/deployments/engiai
ExecStart=/home/your-user/deployments/engiai/docker-compose-wrapper.sh up -d
ExecStop=/home/your-user/deployments/engiai/docker-compose-wrapper.sh down
User=your-user
[Install]
WantedBy=multi-user.target
Enable and start:
sudo systemctl enable engiai
sudo systemctl start engiai
4. Regular Backups#
Set up a cron job for automated backups:
crontab -e
# Add this line to backup daily at 2 AM
0 2 * * * cd ~/deployments/engiai && docker-compose exec -T postgres pg_dump -U engiai_user engineer_assistant > ~/backups/db-backup-$(date +\%Y\%m\%d).sql
Support#
For issues and support:
GitHub Issues: https://github.com/gioelemo/EngiAI/issues
Documentation: https://engiai.gioelemolinari.ch
Version#
This deployment guide targets EngiAI v1.1.0 (the authoritative version is
version in pyproject.toml; keep release in docs/source/conf.py in sync).