#!/bin/bash # Mortdecai Gateway — fully automated setup # Just run: ./setup.sh # Everything downloads and configures automatically. set -e MODEL_URL="${MODEL_URL:-https://mortdec.ai/dl/m4gguf/mortdecai-0.4.0.gguf}" MODEL_NAME="mortdecai:0.4.0" echo "=== Mortdecai Gateway Setup ===" echo "" # Generate API key if not set if [ ! -f .env ]; then KEY="mk_$(openssl rand -hex 16)" cat > .env << EOF API_KEY=$KEY GPU_TDP_WATTS=54 SYSTEM_OVERHEAD_WATTS=30 ELECTRICITY_RATE=0.15 SPENDING_CAP=10.00 EOF echo "Generated API key: $KEY" echo "Saved to .env" else echo ".env already exists" KEY=$(grep API_KEY .env | cut -d= -f2) fi # Start containers echo "" echo "Starting containers..." docker compose up -d # Wait for Ollama to be ready echo "Waiting for Ollama to start..." for i in $(seq 1 60); do if curl -s http://localhost:11434/api/tags > /dev/null 2>&1; then echo "Ollama is ready" break fi if [ $i -eq 60 ]; then echo "ERROR: Ollama failed to start after 2 minutes" echo "Check: docker logs mortdecai-ollama" exit 1 fi sleep 2 done # Check if model already loaded LOADED=$(curl -s http://localhost:11434/api/tags 2>/dev/null | python3 -c "import sys,json; print('yes' if any('$MODEL_NAME' in m['name'] for m in json.load(sys.stdin).get('models',[])) else 'no')" 2>/dev/null || echo "no") if [ "$LOADED" = "yes" ]; then echo "Model $MODEL_NAME already loaded" else # Download GGUF mkdir -p models GGUF_PATH="models/${MODEL_NAME}.gguf" if [ ! -f "$GGUF_PATH" ]; then echo "" echo "Downloading model (~5.3 GB)..." echo "Source: $MODEL_URL" curl -L -o "$GGUF_PATH" "$MODEL_URL" --progress-bar echo "Download complete" else echo "GGUF already downloaded" fi # Create Modelfile cat > models/Modelfile << 'MEOF' FROM /models/mortdecai:0.4.0.gguf TEMPLATE """{{- if .Messages }} {{- if or .System .Tools }}<|im_start|>system {{- if .System }} {{ .System }} {{- end }} <|im_end|> {{ end }} {{- range $m := .Messages }} {{- if eq $m.Role "user" }}<|im_start|>user {{ $m.Content }}<|im_end|> {{- else if eq $m.Role "assistant" }}<|im_start|>assistant {{ $m.Content }}<|im_end|> {{- end }} {{- end }}<|im_start|>assistant {{ end }}""" PARAMETER stop <|im_end|> PARAMETER stop <|im_start|> PARAMETER temperature 0.7 MEOF echo "Loading model into Ollama..." docker exec mortdecai-ollama ollama create "$MODEL_NAME" -f /models/Modelfile echo "Model loaded as $MODEL_NAME" fi # Quick test echo "" echo "Running test inference..." RESULT=$(curl -s http://localhost:8434/api/chat \ -H "Authorization: Bearer $KEY" \ -H "Content-Type: application/json" \ -d "{\"model\": \"$MODEL_NAME\", \"messages\": [{\"role\": \"user\", \"content\": \"say hello\"}], \"stream\": false}" 2>/dev/null) if echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['message']['content'][:80])" 2>/dev/null; then echo "Test passed!" else echo "Test inference returned unexpected result (model may still be loading)" echo "Try again in a minute: curl -s http://localhost:8434/health" fi echo "" echo "=========================================" echo " Mortdecai Gateway is ready!" echo "=========================================" echo "" echo " Dashboard: http://localhost:8434/dashboard" echo " Health: http://localhost:8434/health" echo " API Key: $KEY" echo "" echo " Send this to Seth:" echo " - Your public IP" echo " - Port: 8434" echo " - API Key: $KEY" echo "" echo " To stop: docker compose down" echo " To start: docker compose up -d" echo "========================================="