#!/bin/bash set -e echo "🤖 ============ JARVIS FULL DEPLOYMENT ============" echo "" # ============ COLORS ============ GREEN='\033[0;32m' BLUE='\033[0;34m' YELLOW='\033[1;33m' RED='\033[0;31m' NC='\033[0m' # ============ CONFIGURATION ============ DOMAIN="${1:-jarvis.local}" JARVIS_HOME="/home/jarvis-core/jarvis" echo -e "${BLUE}📍 Setup Directory: $JARVIS_HOME${NC}" echo -e "${BLUE}📍 Domain: $DOMAIN${NC}" echo "" # ============ 1. SYSTEM UPDATE ============ echo -e "${YELLOW}[1/9] System Update...${NC}" sudo apt-get update -qq sudo apt-get upgrade -y -qq sudo apt-get install -y -qq curl wget git htop net-tools openssl python3-pip > /dev/null 2>&1 echo -e "${GREEN}✅ System updated${NC}" # ============ 2. DOCKER INSTALLATION ============ echo -e "${YELLOW}[2/9] Installing Docker...${NC}" if ! command -v docker &> /dev/null; then curl -fsSL https://get.docker.com -o get-docker.sh > /dev/null 2>&1 bash get-docker.sh > /dev/null 2>&1 rm -f get-docker.sh sudo usermod -aG docker jarvis-core echo -e "${GREEN}✅ Docker installed${NC}" else echo -e "${GREEN}✅ Docker already installed${NC}" fi # ============ 3. DOCKER COMPOSE ============ echo -e "${YELLOW}[3/9] Installing Docker Compose...${NC}" if ! command -v docker-compose &> /dev/null; then COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d'"' -f4) sudo curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose > /dev/null 2>&1 sudo chmod +x /usr/local/bin/docker-compose echo -e "${GREEN}✅ Docker Compose installed${NC}" else echo -e "${GREEN}✅ Docker Compose already installed${NC}" fi # ============ 4. PROJECT STRUCTURE ============ echo -e "${YELLOW}[4/9] Creating project structure...${NC}" mkdir -p $JARVIS_HOME/{config,data,logs,api,web} cd $JARVIS_HOME mkdir -p data/{postgres,redis,milvus,etcd,ollama,n8n} mkdir -p logs/{api,n8n,nginx} echo -e "${GREEN}✅ Project structure created${NC}" # ============ 5. DOCKER NETWORK ============ echo -e "${YELLOW}[5/9] Creating Docker network...${NC}" docker network create jarvis-net 2>/dev/null || true echo -e "${GREEN}✅ Docker network ready${NC}" # ============ 6. DOCKER-COMPOSE.YML ============ echo -e "${YELLOW}[6/9] Writing docker-compose.yml...${NC}" cat > docker-compose.yml << 'EOF' version: '3.9' services: traefik: image: traefik:v2.10 container_name: jarvis-traefik command: - "--api.insecure=true" - "--providers.docker=true" - "--providers.docker.exposedbydefault=false" - "--entrypoints.web.address=:80" - "--entrypoints.websecure.address=:443" ports: - "80:80" - "443:443" - "8080:8080" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro networks: - jarvis-net restart: unless-stopped postgres: image: postgres:16-alpine container_name: jarvis-postgres environment: POSTGRES_DB: jarvis POSTGRES_USER: jarvis POSTGRES_PASSWORD: ${DB_PASSWORD:-ChangeMe123!} volumes: - postgres_data:/var/lib/postgresql/data - ./init-db.sql:/docker-entrypoint-initdb.d/init.sql ports: - "5432:5432" networks: - jarvis-net healthcheck: test: ["CMD-SHELL", "pg_isready -U jarvis"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped redis: image: redis:7-alpine container_name: jarvis-redis command: redis-server --appendonly yes volumes: - redis_data:/data ports: - "6379:6379" networks: - jarvis-net healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped milvus: image: milvusdb/milvus:v0.4.0 container_name: jarvis-milvus environment: ETCD_ENDPOINTS: etcd:2379 COMMON_STORAGETYPE: local volumes: - milvus_data:/var/lib/milvus ports: - "19530:19530" - "9091:9091" depends_on: etcd: condition: service_healthy networks: - jarvis-net restart: unless-stopped etcd: image: quay.io/coreos/etcd:v3.5.5 container_name: jarvis-etcd environment: - ETCD_AUTO_COMPACTION_MODE=revision - ETCD_AUTO_COMPACTION_RETENTION=1000 - ETCD_QUOTA_BACKEND_BYTES=4294967296 volumes: - etcd_data:/etcd ports: - "2379:2379" networks: - jarvis-net healthcheck: test: ["CMD", "etcdctl", "endpoint", "health"] interval: 10s timeout: 5s retries: 5 command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd restart: unless-stopped ollama: image: ollama/ollama:latest container_name: jarvis-ollama environment: - OLLAMA_HOST=0.0.0.0:11434 volumes: - ollama_data:/root/.ollama ports: - "11434:11434" networks: - jarvis-net restart: unless-stopped n8n: image: n8n:latest container_name: jarvis-n8n environment: - DB_TYPE=postgresdb - DB_POSTGRESDB_HOST=postgres - DB_POSTGRESDB_USER=jarvis - DB_POSTGRESDB_PASSWORD=${DB_PASSWORD:-ChangeMe123!} - DB_POSTGRESDB_DATABASE=n8n - N8N_HOST=${DOMAIN:-localhost} - N8N_PORT=5678 - WEBHOOK_TUNNEL_URL=http://n8n:5678/ - GENERIC_TIMEZONE=Europe/Berlin volumes: - n8n_data:/home/node/.n8n ports: - "5678:5678" depends_on: postgres: condition: service_healthy networks: - jarvis-net labels: - "traefik.enable=true" - "traefik.http.routers.n8n.rule=Host(`n8n.${DOMAIN:-localhost}`)" - "traefik.http.services.n8n.loadbalancer.server.port=5678" restart: unless-stopped jarvis-api: image: python:3.11-slim container_name: jarvis-api working_dir: /app command: > bash -c "pip install -q -r requirements.txt && uvicorn main:app --host 0.0.0.0 --port 8000 --reload" environment: - DATABASE_URL=postgresql://jarvis:${DB_PASSWORD:-ChangeMe123!}@postgres:5432/jarvis - REDIS_URL=redis://redis:6379 - MILVUS_HOST=milvus - MILVUS_PORT=19530 - OLLAMA_HOST=http://ollama:11434 - CLAUDE_API_KEY=${CLAUDE_API_KEY:-} - LOG_LEVEL=info volumes: - ./api:/app ports: - "8000:8000" depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - jarvis-net labels: - "traefik.enable=true" - "traefik.http.routers.api.rule=Host(`api.${DOMAIN:-localhost}`)" - "traefik.http.services.api.loadbalancer.server.port=8000" restart: unless-stopped networks: jarvis-net: driver: bridge volumes: postgres_data: redis_data: milvus_data: etcd_data: ollama_data: n8n_data: EOF echo -e "${GREEN}✅ docker-compose.yml created${NC}" # ============ 7. ENV FILE ============ echo -e "${YELLOW}[7/9] Creating .env file...${NC}" cat > .env << EOF DOMAIN=$DOMAIN DB_PASSWORD=$(openssl rand -base64 32) CLAUDE_API_KEY= OLLAMA_MODEL=mistral LOG_LEVEL=info JWT_SECRET=$(openssl rand -base64 32) API_KEY_ADMIN=$(openssl rand -base64 32) N8N_ENCRYPTION_KEY=$(openssl rand -base64 32) EOF chmod 600 .env echo -e "${GREEN}✅ .env created${NC}" # ============ 8. DATABASE & API ============ echo -e "${YELLOW}[8/9] Creating database schema...${NC}" cat > init-db.sql << 'EOF' CREATE DATABASE jarvis; CREATE DATABASE n8n; \c jarvis; CREATE TABLE users (id SERIAL PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, api_key VARCHAR(255) UNIQUE, role VARCHAR(50) DEFAULT 'user', is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP); CREATE TABLE conversations (id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(255), context JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP); CREATE INDEX idx_conversations_user_id ON conversations(user_id); CREATE TABLE messages (id SERIAL PRIMARY KEY, conversation_id INTEGER NOT NULL REFERENCES conversations(id) ON DELETE CASCADE, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, role VARCHAR(50) NOT NULL, content TEXT NOT NULL, tokens_used INTEGER, metadata JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP); CREATE INDEX idx_messages_conversation_id ON messages(conversation_id); CREATE TABLE tasks (id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, description TEXT, task_type VARCHAR(100), status VARCHAR(50) DEFAULT 'pending', priority INTEGER DEFAULT 0, data JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at TIMESTAMP); CREATE INDEX idx_tasks_user_id ON tasks(user_id); CREATE TABLE documents (id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, document_type VARCHAR(100), metadata JSONB, embedding_id VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP); INSERT INTO users (username, email, password_hash, role) VALUES ('admin', 'admin@jarvis.local', '$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3djPvga3jaK', 'admin') ON CONFLICT DO NOTHING; EOF # Create API directory and files mkdir -p api cat > api/requirements.txt << 'EOF' fastapi==0.104.1 uvicorn[standard]==0.24.0 python-dotenv==1.0.0 pydantic==2.5.0 psycopg2-binary==2.9.9 redis==5.0.1 pymilvus==2.3.4 anthropic==0.14.0 aiohttp==3.9.1 requests==2.31.0 EOF cat > api/main.py << 'EOF' from fastapi import FastAPI from datetime import datetime import os app = FastAPI(title="JARVIS API", version="0.1.0") @app.get("/health") async def health(): return {"status": "healthy", "timestamp": datetime.now()} @app.get("/api/v1/admin/stats") async def stats(): return {"status": "ok", "timestamp": datetime.now()} @app.post("/api/v1/chat") async def chat(message: str): return {"response": f"Echo: {message}", "timestamp": datetime.now()} if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000) EOF echo -e "${GREEN}✅ Database schema and API created${NC}" # ============ 9. PERMISSIONS ============ echo -e "${YELLOW}[9/9] Setting permissions...${NC}" sudo chown -R jarvis-core:jarvis-core $JARVIS_HOME chmod -R 755 $JARVIS_HOME chmod 600 .env echo -e "${GREEN}✅ Permissions set${NC}" # ============ DEPLOYMENT ============ echo "" echo -e "${GREEN}============================================${NC}" echo -e "${GREEN}🚀 STARTING DOCKER CONTAINERS...${NC}" echo -e "${GREEN}============================================${NC}" echo "" docker-compose up -d echo "" echo -e "${BLUE}Waiting for services to start... (30s)${NC}" sleep 30 echo "" echo -e "${GREEN}============================================${NC}" echo -e "${GREEN}✅ JARVIS DEPLOYED SUCCESSFULLY!${NC}" echo -e "${GREEN}============================================${NC}" echo "" echo -e "${BLUE}📍 Services:${NC}" echo " 🌐 Web Dashboard: http://$DOMAIN:3000 (⏳ coming soon)" echo " 📡 API: http://$DOMAIN:8000" echo " 📡 API Docs: http://$DOMAIN:8000/docs" echo " ⚙️ n8n: http://$DOMAIN:5678" echo " 🔌 Traefik: http://$DOMAIN:8080" echo "" echo -e "${BLUE}📊 Database Access:${NC}" echo " PostgreSQL: localhost:5432 (user: jarvis)" echo " Redis: localhost:6379" echo " Milvus: localhost:19530" echo " Ollama: localhost:11434" echo "" echo -e "${BLUE}📝 Next steps:${NC}" echo " 1. Edit .env - Add CLAUDE_API_KEY" echo " 2. Restart API: docker-compose restart jarvis-api" echo " 3. Check logs: docker-compose logs -f" echo "" echo -e "${YELLOW}⚠️ Important:${NC}" echo " • Change default admin password in database" echo " • Setup SSL/HTTPS in production" echo " • Configure regular backups" echo "" # Status echo -e "${BLUE}📊 Container Status:${NC}" docker-compose ps echo "" echo -e "${GREEN}🎉 Ready to go! Start building with JARVIS!${NC}"