diff --git a/README.md b/README.md index a4134a0..647e829 100644 --- a/README.md +++ b/README.md @@ -6,163 +6,99 @@ [Link](https://docs.google.com/presentation/d/12XRHySp_W6Mrh64nA_6Hi3s8XvliUoANP-p_ha0FHEA/edit?usp=sharing) +--- + ## Quick Start -**One-line installation** (recommended): +### Single device (Ollama + Onyx on the same machine) ```bash bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup.sh) ``` -Or clone and run locally: +### Two devices (Ollama on one machine, Onyx on another) + +**On the Ollama device** — installs Ollama and the RIoT models, no Docker needed: ```bash -git clone https://github.com/cediackermann/riotsecure.git -cd riotsecure -./setup.sh +bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup_ollama.sh) ``` -The script automates most steps and pauses for manual configuration when needed (Docker settings, web interface setup, etc.). +At the end the script prints the exact command to run on the Onyx device. -**After installation**, verify everything is working: +**On the Onyx device** — installs Docker and Onyx, auto-detects the Ollama device on the network: ```bash -cd ~/riotsecure -./check-status.sh +bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup_onyx.sh) ``` -**To uninstall** (one-line command): +The script scans the local network for Ollama. If it can't find it automatically, it will ask for the IP address. + +--- + +## Status & Maintenance + +**Check everything is working:** + +```bash +cd ~/riotsecure && ./check-status.sh +``` + +**Update Ollama models:** + +```bash +cd ~/riotsecure && ./updateModels.sh modelfiles +``` + +**Uninstall:** ```bash bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/cleanup.sh) ``` -Or run locally: - -```bash -cd ~/riotsecure -./cleanup.sh -``` - -For detailed manual instructions, continue reading below. - --- -## 1. Homebrew +## Manual Steps Reference -```bash -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" -``` +The scripts pause and prompt when manual action is required. Here is what to expect at each pause. -Add Homebrew to your shell profile: - -```bash -echo >> /Users/riot/.zprofile -echo 'eval "$(/opt/homebrew/bin/brew shellenv zsh)"' >> /Users/riot/.zprofile -eval "$(/opt/homebrew/bin/brew shellenv zsh)" -``` - ---- - -## 2. Ollama - -```bash -curl -fsSL https://ollama.com/install.sh | sh -``` - ---- - -## 3. Docker Desktop - -```bash -brew install --cask docker-desktop -open -a Docker -``` - -Click through the installer and install any prompted software updates. - -### Adjust Resources +### Docker Desktop resources Go to **Docker → Settings → Resources** and set: -| Setting | Value | -| ---------------- | ----- | -| CPU limit | MAX | -| Memory limit | 20 GB | -| Disk usage limit | MAX | +| Setting | Value | +| ---------------- | ---------------------------- | +| CPU limit | MAX | +| Memory limit | 20 GB (or MAX if less than 20 GB available) | +| Disk usage limit | MAX | Hit **Apply & Restart**. ---- - -## 4. Onyx - -```bash -curl -fsSL https://onyx.app/install_onyx.sh | bash -``` - -When prompted: +### Onyx installer prompts 1. Press **Enter** to acknowledge 2. Choose **2** for Standard 3. Press **Enter** for Edge -Onyx creates `~/riotsecure/onyx_data/`, which contains the Docker Compose file (useful for manually stopping or modifying images). There is also a `.env` file — leave it untouched. +### Web interface configuration -### Prevent Sleep +1. Open `http://localhost:3000` and create an admin account. +2. Go to **Admin Panel → Language Models**: + - Select **Ollama** as provider and give it a name + - Set the API base URL to the address shown by the setup script + - Refresh the model list, select at least the three RIoT models, and click **Connect** +3. Go to **Admin Panel → Chat Preferences → System Prompt → Modify Prompt**, delete the entire prompt, and save. + +### RAG content upload + +**Option A — File upload (recommended)** ```bash -sudo pmset -a sleep 0 disksleep 0 +cd ~/riotsecure && ./fetchContent.sh riot-sources.txt ``` ---- +Then in the web interface: **Admin Panel → Add Connector → File**, upload the files from `~/riotsecure/content`, and wait ~30 seconds for indexing. -## 5. Ollama Models +**Option B — URL connector** -1. Clone the repo: - - ```bash - cd ~ - git clone https://github.com/cediackermann/riotsecure.git - cd ~/riotsecure - ``` - -2. Create models from modelfiles: - - ```bash - ./updateModels.sh modelfiles - ``` - - The required base model is pulled automatically — just wait for it to finish. - -3. Open the web interface on port **3000** and create an admin account. -4. Go to **Admin Panel → Language Models**: - - Select **Ollama** as provider and give it a name - - Set the API base URL to `http://host.docker.internal:11434` - - Refresh the model list, select at least the three RIoT models, and click **Connect** -5. Go to **Admin Panel → Chat Preferences → System Prompt → Modify Prompt**, delete the entire prompt, and save. - ---- - -## 6. RAG Content Upload - -### Option A — Upload as File - -1. If needed, edit the URLs in `riot-sources.txt`. - -2. Fetch content: - - ```bash - cd ~/riotsecure - ./fetchContent.sh riot-sources.txt - ``` - -3. In the web interface, go to **Admin Panel → Add Connector → File**. -4. Give the connector a name and upload the files from `~/riotsecure/content`. -5. Wait ~30 seconds for indexing to complete. - -### Option B — Upload as URL - -1. In the web interface, go to **Admin Panel → Add Connector → Web**. -2. Add each URL as a separate connector, using scrape method **Single**. -3. Wait ~30 seconds for indexing to complete. +In the web interface: **Admin Panel → Add Connector → Web**, add each URL from `riot-sources.txt` as a separate connector using scrape method **Single**, and wait ~30 seconds for indexing. diff --git a/check-status.sh b/check-status.sh index a42e12c..51138e9 100755 --- a/check-status.sh +++ b/check-status.sh @@ -1,51 +1,53 @@ #!/bin/bash -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color +# Source shared helpers if running from the repo; otherwise define inline. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [ -f "$SCRIPT_DIR/steps/common.sh" ]; then + source "$SCRIPT_DIR/steps/common.sh" +else + RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m' + print_header() { echo -e "\n${BLUE}===================================================${NC}\n${BLUE}$1${NC}\n${BLUE}===================================================${NC}\n"; } + print_section() { echo -e "\n${BLUE}▶ $1${NC}"; } + print_success() { echo -e "${GREEN}✓ $1${NC}"; } + print_warning() { echo -e "${YELLOW}⚠ $1${NC}"; } + print_error() { echo -e "${RED}✗ $1${NC}"; } +fi -# Status indicators PASS="${GREEN}✓${NC}" FAIL="${RED}✗${NC}" WARN="${YELLOW}⚠${NC}" INFO="${BLUE}ℹ${NC}" -print_header() { - echo -e "\n${BLUE}═══════════════════════════════════════════════════${NC}" - echo -e "${BLUE}$1${NC}" - echo -e "${BLUE}═══════════════════════════════════════════════════${NC}\n" -} +# --------------------------------------------------------------------------- +# Detect which role this machine plays +# --------------------------------------------------------------------------- +HAS_DOCKER=0 +HAS_OLLAMA=0 +HAS_ONYX=0 -print_section() { - echo -e "\n${BLUE}▶ $1${NC}" -} +[ -d "/Applications/Docker.app" ] && HAS_DOCKER=1 +command -v ollama &>/dev/null && HAS_OLLAMA=1 +[ -d ~/riotsecure/onyx_data ] && HAS_ONYX=1 -check_command() { - if command -v $1 &> /dev/null; then - echo -e "$PASS $2 installed" - return 0 - else - echo -e "$FAIL $2 not found" - return 1 - fi -} +if [ $HAS_OLLAMA -eq 1 ] && [ $HAS_DOCKER -eq 1 ]; then + DEVICE_MODE="single" +elif [ $HAS_OLLAMA -eq 1 ]; then + DEVICE_MODE="ollama" +elif [ $HAS_DOCKER -eq 1 ] || [ $HAS_ONYX -eq 1 ]; then + DEVICE_MODE="onyx" +else + DEVICE_MODE="unknown" +fi -check_service() { - if $1 &> /dev/null; then - echo -e "$PASS $2" - return 0 - else - echo -e "$FAIL $2" - return 1 - fi -} - -# Main status check print_header "RIoT AI System Status Check" +case $DEVICE_MODE in + single) echo -e "${INFO} Mode: ${BLUE}single-device${NC} (Ollama + Onyx)" ;; + ollama) echo -e "${INFO} Mode: ${BLUE}Ollama device${NC}" ;; + onyx) echo -e "${INFO} Mode: ${BLUE}Onyx device${NC}" ;; + *) echo -e "${WARN} Mode: ${YELLOW}unknown${NC} — no RIoT components detected" ;; +esac + OVERALL_STATUS=0 # ============================================================================= @@ -56,7 +58,6 @@ print_section "System Information" echo -e "$INFO macOS Version: $(sw_vers -productVersion)" echo -e "$INFO Hostname: $(hostname)" -# Check available disk space AVAILABLE_GB=$(df -g / | awk 'NR==2 {print $4}') if [ "$AVAILABLE_GB" -lt 20 ]; then echo -e "$WARN Available disk space: ${AVAILABLE_GB}GB (recommended: 20GB+)" @@ -65,7 +66,6 @@ else echo -e "$PASS Available disk space: ${AVAILABLE_GB}GB" fi -# Check total memory TOTAL_MEM_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}') if [ "$TOTAL_MEM_GB" -lt 16 ]; then echo -e "$WARN Total memory: ${TOTAL_MEM_GB}GB (recommended: 16GB+)" @@ -78,63 +78,50 @@ fi # ============================================================================= print_section "Core Components" -# Homebrew -if check_command brew "Homebrew"; then - echo -e " ${INFO} Version: $(brew --version | head -n1)" +if command -v brew &>/dev/null; then + echo -e "$PASS Homebrew installed ($(brew --version | head -n1))" else + echo -e "$FAIL Homebrew not found" OVERALL_STATUS=1 fi -# Ollama -if check_command ollama "Ollama"; then - echo -e " ${INFO} Version: $(ollama --version 2>&1 | head -n1)" +# Ollama — only expected on single or ollama devices +if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "ollama" ]; then + if command -v ollama &>/dev/null; then + echo -e "$PASS Ollama installed ($(ollama --version 2>&1 | head -n1))" + else + echo -e "$FAIL Ollama not found" + OVERALL_STATUS=1 + fi else - OVERALL_STATUS=1 + echo -e "$INFO Ollama not expected on this device (Onyx-only mode)" fi -# Docker Desktop -if [ -d "/Applications/Docker.app" ]; then - echo -e "$PASS Docker Desktop installed" +# Docker — only expected on single or onyx devices +if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "onyx" ]; then + if [ -d "/Applications/Docker.app" ]; then + echo -e "$PASS Docker Desktop installed" + else + echo -e "$FAIL Docker Desktop not found" + OVERALL_STATUS=1 + fi else - echo -e "$FAIL Docker Desktop not found" - OVERALL_STATUS=1 + echo -e "$INFO Docker not expected on this device (Ollama-only mode)" fi # ============================================================================= -# Docker Service +# Ollama Service (single / ollama devices only) # ============================================================================= -print_section "Docker Service" +if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "ollama" ]; then + print_section "Ollama Service" -if check_service "docker info" "Docker daemon running"; then - # Get Docker resource settings - DOCKER_CPUS=$(docker info 2>/dev/null | grep "CPUs:" | awk '{print $2}') - DOCKER_MEM=$(docker info 2>/dev/null | grep "Total Memory:" | awk '{print $3$4}') + if pgrep -x "ollama" > /dev/null; then + echo -e "$PASS Ollama service running" - echo -e " ${INFO} CPUs allocated: ${DOCKER_CPUS}" - echo -e " ${INFO} Memory allocated: ${DOCKER_MEM}" - - # Check running containers - CONTAINER_COUNT=$(docker ps -q | wc -l | tr -d ' ') - echo -e " ${INFO} Running containers: ${CONTAINER_COUNT}" -else - echo -e "$WARN Docker is not running. Start Docker Desktop to continue." - OVERALL_STATUS=1 -fi - -# ============================================================================= -# Ollama Service -# ============================================================================= -print_section "Ollama Service" - -if pgrep -x "ollama" > /dev/null; then - echo -e "$PASS Ollama service running" - - # Check available models - if command -v ollama &> /dev/null; then echo -e "\n Available models:" MODELS=$(ollama list 2>/dev/null) if [ -n "$MODELS" ]; then - echo "$MODELS" | tail -n +2 | while read line; do + echo "$MODELS" | tail -n +2 | while read -r line; do MODEL_NAME=$(echo "$line" | awk '{print $1}') if [[ $MODEL_NAME == riot* ]]; then echo -e " $PASS $line" @@ -146,77 +133,88 @@ if pgrep -x "ollama" > /dev/null; then echo -e " $WARN No models found" OVERALL_STATUS=1 fi - fi -else - echo -e "$WARN Ollama service not running" - echo -e " ${INFO} Start with: ollama serve" - OVERALL_STATUS=1 -fi - -# ============================================================================= -# Onyx Installation -# ============================================================================= -print_section "Onyx" - -if [ -d ~/riotsecure/onyx_data ]; then - echo -e "$PASS Onyx data directory exists" - - # Check if Onyx containers are running - if command -v docker &> /dev/null && docker info &> /dev/null; then - cd ~/riotsecure/onyx_data 2>/dev/null - if [ -f "docker-compose.yaml" ] || [ -f "docker-compose.yml" ]; then - echo -e "$PASS Docker Compose file found" - - # Check running Onyx containers - ONYX_CONTAINERS=$(docker ps --filter "name=onyx" -q | wc -l | tr -d ' ') - if [ "$ONYX_CONTAINERS" -gt 0 ]; then - echo -e "$PASS Onyx containers running: ${ONYX_CONTAINERS}" - docker ps --filter "name=onyx" --format " $INFO {{.Names}} ({{.Status}})" - else - echo -e "$WARN No Onyx containers running" - echo -e " ${INFO} Start with: cd ~/riotsecure/onyx_data && docker compose up -d" - OVERALL_STATUS=1 - fi - fi - cd - > /dev/null 2>&1 - fi -else - echo -e "$FAIL Onyx data directory not found" - echo -e " ${INFO} Run ./setup.sh to install" - OVERALL_STATUS=1 -fi - -# ============================================================================= -# Web Interface -# ============================================================================= -print_section "Web Interface" - -# Check if port 3000 is in use -if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null 2>&1; then - echo -e "$PASS Port 3000 is active" - - # Try to connect to the web interface - if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 | grep -q "200\|301\|302"; then - echo -e "$PASS Web interface responding" - echo -e "\n ${INFO} Access at: ${GREEN}http://localhost:3000${NC}" - - # Get local IP for network access - LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null) - if [ -n "$LOCAL_IP" ]; then - echo -e " ${INFO} Network access: ${GREEN}http://${LOCAL_IP}:3000${NC}" - fi else - echo -e "$WARN Port 3000 is active but interface not responding" + echo -e "$WARN Ollama service not running" + echo -e " ${INFO} Start with: ollama serve" OVERALL_STATUS=1 fi -else - echo -e "$FAIL Port 3000 not in use" - echo -e " ${INFO} Onyx containers may not be running" - OVERALL_STATUS=1 fi # ============================================================================= -# Repository Status +# Docker Service (single / onyx devices only) +# ============================================================================= +if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "onyx" ]; then + print_section "Docker Service" + + if docker info &>/dev/null; then + DOCKER_CPUS=$(docker info 2>/dev/null | grep "CPUs:" | awk '{print $2}') + DOCKER_MEM=$(docker info 2>/dev/null | grep "Total Memory:" | awk '{print $3$4}') + CONTAINER_COUNT=$(docker ps -q | wc -l | tr -d ' ') + + echo -e "$PASS Docker daemon running" + echo -e " ${INFO} CPUs allocated: ${DOCKER_CPUS}" + echo -e " ${INFO} Memory allocated: ${DOCKER_MEM}" + echo -e " ${INFO} Running containers: ${CONTAINER_COUNT}" + else + echo -e "$WARN Docker is not running. Start Docker Desktop to continue." + OVERALL_STATUS=1 + fi + + # ============================================================================= + # Onyx + # ============================================================================= + print_section "Onyx" + + if [ -d ~/riotsecure/onyx_data ]; then + echo -e "$PASS Onyx data directory exists" + + if docker info &>/dev/null; then + cd ~/riotsecure/onyx_data 2>/dev/null + if [ -f "docker-compose.yaml" ] || [ -f "docker-compose.yml" ]; then + echo -e "$PASS Docker Compose file found" + + ONYX_CONTAINERS=$(docker ps --filter "name=onyx" -q | wc -l | tr -d ' ') + if [ "$ONYX_CONTAINERS" -gt 0 ]; then + echo -e "$PASS Onyx containers running: ${ONYX_CONTAINERS}" + docker ps --filter "name=onyx" --format " $INFO {{.Names}} ({{.Status}})" + else + echo -e "$WARN No Onyx containers running" + echo -e " ${INFO} Start with: cd ~/riotsecure/onyx_data && docker compose up -d" + OVERALL_STATUS=1 + fi + fi + cd - >/dev/null 2>&1 + fi + else + echo -e "$FAIL Onyx data directory not found" + OVERALL_STATUS=1 + fi + + # ============================================================================= + # Web Interface + # ============================================================================= + print_section "Web Interface" + + if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null 2>&1; then + if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 | grep -q "200\|301\|302"; then + echo -e "$PASS Web interface responding at http://localhost:3000" + + LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "") + if [ -n "$LOCAL_IP" ]; then + echo -e " ${INFO} Network access: ${GREEN}http://${LOCAL_IP}:3000${NC}" + fi + else + echo -e "$WARN Port 3000 active but interface not responding" + OVERALL_STATUS=1 + fi + else + echo -e "$FAIL Port 3000 not in use — Onyx containers may not be running" + OVERALL_STATUS=1 + fi +fi + +# ============================================================================= +# Repository # ============================================================================= print_section "Repository" @@ -226,20 +224,19 @@ if [ -d ~/riotsecure ]; then cd ~/riotsecure 2>/dev/null if [ -d .git ]; then CURRENT_BRANCH=$(git branch --show-current 2>/dev/null) - echo -e " ${INFO} Current branch: ${CURRENT_BRANCH}" + echo -e " ${INFO} Branch: ${CURRENT_BRANCH}" - # Check for updates git fetch --quiet 2>/dev/null LOCAL=$(git rev-parse @ 2>/dev/null) REMOTE=$(git rev-parse @{u} 2>/dev/null) if [ "$LOCAL" != "$REMOTE" ]; then - echo -e " $WARN Updates available (run: git pull)" + echo -e " $WARN Updates available — run: git pull" else echo -e " $PASS Repository up to date" fi fi - cd - > /dev/null 2>&1 + cd - >/dev/null 2>&1 else echo -e "$FAIL Repository not found at ~/riotsecure" OVERALL_STATUS=1 @@ -251,15 +248,22 @@ fi print_header "Summary" if [ $OVERALL_STATUS -eq 0 ]; then - echo -e "${GREEN}✓ All systems operational${NC}\n" + echo -e "${GREEN}✓ All systems operational${NC}" + echo "" exit 0 else - echo -e "${YELLOW}⚠ Some issues detected - review output above${NC}\n" + echo -e "${YELLOW}⚠ Some issues detected — review output above${NC}" + echo "" echo "Common fixes:" - echo " • Docker not running → Open Docker Desktop" - echo " • Ollama not running → Run: ollama serve" - echo " • Onyx not running → cd ~/riotsecure/onyx_data && docker compose up -d" - echo " • Low disk space → Free up disk space" + if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "ollama" ]; then + echo " • Ollama not running → ollama serve" + echo " • Update models → cd ~/riotsecure && ./updateModels.sh modelfiles" + fi + if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "onyx" ]; then + echo " • Docker not running → Open Docker Desktop" + echo " • Onyx not running → cd ~/riotsecure/onyx_data && docker compose up -d" + fi + echo " • Low disk space → Free up disk space" echo "" exit 1 fi diff --git a/cleanup.sh b/cleanup.sh index 702d3e7..cec03bf 100755 --- a/cleanup.sh +++ b/cleanup.sh @@ -1,45 +1,21 @@ #!/bin/bash -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color +set -e -# Helper functions -print_header() { - echo -e "\n${BLUE}===================================================${NC}" - echo -e "${BLUE}$1${NC}" - echo -e "${BLUE}===================================================${NC}\n" -} +# Source shared helpers if running from the repo; otherwise define inline. +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [ -f "$SCRIPT_DIR/steps/common.sh" ]; then + source "$SCRIPT_DIR/steps/common.sh" +else + RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m' + print_header() { echo -e "\n${BLUE}===================================================${NC}\n${BLUE}$1${NC}\n${BLUE}===================================================${NC}\n"; } + print_success() { echo -e "${GREEN}✓ $1${NC}"; } + print_warning() { echo -e "${YELLOW}⚠ $1${NC}"; } + print_error() { echo -e "${RED}✗ $1${NC}"; } + ask_confirmation() { echo -e "${YELLOW}$1 [y/N]${NC}"; read -r response; [[ "$response" =~ ^[Yy]$ ]]; } + check_mac() { [[ "$OSTYPE" != "darwin"* ]] && { echo -e "${RED}✗ macOS only${NC}"; exit 1; }; } +fi -print_success() { - echo -e "${GREEN}✓ $1${NC}" -} - -print_warning() { - echo -e "${YELLOW}⚠ $1${NC}" -} - -print_error() { - echo -e "${RED}✗ $1${NC}" -} - -ask_confirmation() { - echo -e "${YELLOW}$1 [y/N]${NC}" - read -r response - [[ "$response" =~ ^[Yy]$ ]] -} - -check_mac() { - if [[ "$OSTYPE" != "darwin"* ]]; then - print_error "This script is designed for macOS. Exiting." - exit 1 - fi -} - -# Check if running on macOS check_mac print_header "RIoT AI Cleanup Script" @@ -110,11 +86,10 @@ if command -v ollama &> /dev/null; then print_warning "No RIoT models found, skipping" fi - # Optionally remove Ollama itself echo "" if ask_confirmation "Remove Ollama completely? (This will remove ALL models)"; then print_warning "Stopping Ollama service..." - pkill -9 ollama 2>/dev/null + pkill -9 ollama 2>/dev/null || true print_warning "Removing Ollama data..." rm -rf ~/.ollama @@ -147,15 +122,14 @@ if [ -d "/Applications/Docker.app" ]; then if ask_confirmation "Uninstall Docker Desktop?"; then print_warning "Quitting Docker Desktop..." - osascript -e 'quit app "Docker"' 2>/dev/null + osascript -e 'quit app "Docker"' 2>/dev/null || true sleep 3 print_warning "Uninstalling Docker Desktop..." if command -v brew &> /dev/null; then - brew uninstall --cask docker-desktop 2>/dev/null + brew uninstall --cask docker-desktop 2>/dev/null || true fi - # Remove Docker data if ask_confirmation "Remove Docker data and containers? (WARNING: This affects all Docker usage)"; then rm -rf ~/Library/Containers/com.docker.docker rm -rf ~/Library/Application\ Support/Docker\ Desktop @@ -180,14 +154,11 @@ print_header "STEP 4: Repository Cleanup" if [ -d ~/riotsecure ]; then echo "Found riotsecure repository at ~/riotsecure" - # Check if there are uncommitted changes cd ~/riotsecure - if [ -d .git ]; then - if ! git diff-index --quiet HEAD -- 2>/dev/null; then - print_warning "Repository has uncommitted changes!" - git status --short - echo "" - fi + if [ -d .git ] && ! git diff-index --quiet HEAD -- 2>/dev/null; then + print_warning "Repository has uncommitted changes!" + git status --short + echo "" fi if ask_confirmation "Remove the riotsecure repository?"; then @@ -203,23 +174,9 @@ else fi # ============================================================================= -# STEP 5: Content Directory +# STEP 5: Power Settings # ============================================================================= -print_header "STEP 5: Downloaded Content Cleanup" - -if [ -d ~/riotsecure/content ]; then - if ask_confirmation "Remove downloaded RAG content?"; then - rm -rf ~/riotsecure/content - print_success "Content removed" - else - print_warning "Keeping content" - fi -fi - -# ============================================================================= -# STEP 6: Power Settings -# ============================================================================= -print_header "STEP 6: Power Settings Cleanup" +print_header "STEP 5: Power Settings Cleanup" if ask_confirmation "Restore default sleep settings?"; then print_warning "Restoring sleep settings..." @@ -230,9 +187,9 @@ else fi # ============================================================================= -# STEP 7: Homebrew (Optional) +# STEP 6: Homebrew (Optional) # ============================================================================= -print_header "STEP 7: Homebrew Cleanup (Optional)" +print_header "STEP 6: Homebrew Cleanup (Optional)" if command -v brew &> /dev/null; then echo -e "${YELLOW}Note: Homebrew may be used by many other applications.${NC}" @@ -243,7 +200,6 @@ if command -v brew &> /dev/null; then print_warning "Uninstalling Homebrew..." /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)" - # Remove Homebrew from shell profile if [ -f ~/.zprofile ]; then sed -i.bak '/homebrew/d' ~/.zprofile print_success "Removed Homebrew from .zprofile" @@ -262,13 +218,9 @@ print_header "Cleanup Complete" echo -e "${GREEN}Cleanup process finished!${NC}" echo "" -echo "What was done:" -echo " • Reviewed and optionally removed Onyx" -echo " • Reviewed and optionally removed Ollama models" -echo " • Reviewed and optionally removed Docker Desktop" -echo " • Reviewed and optionally removed repository" -echo " • Reviewed and optionally restored power settings" +echo "To reinstall, choose the setup that matches your configuration:" echo "" -echo "To reinstall RIoT AI, run:" -echo -e " ${BLUE}bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup.sh)${NC}" +echo -e " Single device: ${BLUE}bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup.sh)${NC}" +echo -e " Ollama device: ${BLUE}bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup_ollama.sh)${NC}" +echo -e " Onyx device: ${BLUE}bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup_onyx.sh)${NC}" echo "" diff --git a/setup.sh b/setup.sh index 68b9934..edfe0f7 100755 --- a/setup.sh +++ b/setup.sh @@ -1,396 +1,59 @@ #!/bin/bash +# All-in-one setup: installs everything on a single machine. +# For a split setup (Onyx on one machine, Ollama on another) use: +# setup_onyx.sh — on the Onyx device +# setup_ollama.sh — on the Ollama device -set -e # Exit on error +set -e -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/steps/common.sh" +source "$SCRIPT_DIR/steps/preflight.sh" +source "$SCRIPT_DIR/steps/step_homebrew.sh" +source "$SCRIPT_DIR/steps/step_ollama.sh" +source "$SCRIPT_DIR/steps/step_repo.sh" +source "$SCRIPT_DIR/steps/step_docker.sh" +source "$SCRIPT_DIR/steps/step_onyx.sh" +source "$SCRIPT_DIR/steps/step_models.sh" +source "$SCRIPT_DIR/steps/step_webconfig.sh" +source "$SCRIPT_DIR/steps/step_rag.sh" -# Helper functions -print_step() { - echo -e "\n${BLUE}===================================================${NC}" - echo -e "${BLUE}$1${NC}" - echo -e "${BLUE}===================================================${NC}\n" -} - -print_success() { - echo -e "${GREEN}✓ $1${NC}" -} - -print_warning() { - echo -e "${YELLOW}⚠ $1${NC}" -} - -print_error() { - echo -e "${RED}✗ $1${NC}" -} - -wait_for_user() { - echo -e "\n${YELLOW}Press ENTER when you have completed the above step...${NC}" - read -} - -check_mac() { - if [[ "$OSTYPE" != "darwin"* ]]; then - print_error "This script is designed for macOS. Exiting." - exit 1 - fi -} - -preflight_checks() { - print_step "Pre-flight System Checks" - - local PREFLIGHT_FAILED=0 - - # Check macOS version - MACOS_VERSION=$(sw_vers -productVersion) - MACOS_MAJOR=$(echo $MACOS_VERSION | cut -d. -f1) - echo -e "macOS Version: ${BLUE}$MACOS_VERSION${NC}" - - if [ "$MACOS_MAJOR" -lt 12 ]; then - print_error "macOS 12 (Monterey) or later recommended. You have: $MACOS_VERSION" - PREFLIGHT_FAILED=1 - else - print_success "macOS version compatible" - fi - - # Check available disk space - AVAILABLE_GB=$(df -g / | awk 'NR==2 {print $4}') - echo -e "Available disk space: ${BLUE}${AVAILABLE_GB}GB${NC}" - - if [ "$AVAILABLE_GB" -lt 30 ]; then - print_error "Insufficient disk space. Required: 30GB+, Available: ${AVAILABLE_GB}GB" - echo " Docker images, Ollama models, and Onyx require significant storage" - PREFLIGHT_FAILED=1 - elif [ "$AVAILABLE_GB" -lt 50 ]; then - print_warning "Low disk space. Recommended: 50GB+, Available: ${AVAILABLE_GB}GB" - echo " Installation will proceed but may fail if space runs out" - else - print_success "Sufficient disk space available" - fi - - # Check total memory - TOTAL_MEM_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}') - echo -e "Total system memory: ${BLUE}${TOTAL_MEM_GB}GB${NC}" - - if [ "$TOTAL_MEM_GB" -lt 16 ]; then - print_warning "Low memory. Recommended: 16GB+, Available: ${TOTAL_MEM_GB}GB" - echo " Docker will be configured with 20GB limit (may need adjustment)" - else - print_success "Sufficient memory available" - fi - - # Check internet connectivity - if ping -c 1 -W 2 8.8.8.8 &> /dev/null; then - print_success "Internet connectivity verified" - else - print_error "No internet connection detected" - echo " Internet required to download Homebrew, Docker, Ollama, etc." - PREFLIGHT_FAILED=1 - fi - - # Check if Docker is already running (might conflict) - if pgrep -x "Docker" > /dev/null 2>&1; then - print_warning "Docker Desktop is already running" - echo " This is fine if it's already installed, otherwise it may cause conflicts" - fi - - # Check if port 3000 is already in use - if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null 2>&1; then - print_warning "Port 3000 is already in use" - echo " Onyx web interface requires port 3000 to be available" - echo " You may need to stop the conflicting service" - fi - - # Estimate installation time - echo "" - echo -e "${YELLOW}⏱ Estimated installation time: 20-40 minutes${NC}" - echo " (depends on internet speed and system performance)" - echo "" - - # Show what will be installed - echo "The following will be installed/configured:" - echo " • Homebrew (package manager)" - echo " • Ollama (AI model runtime)" - echo " • Docker Desktop (containerization)" - echo " • Onyx (web interface)" - echo " • RIoT AI models (several GB download)" - echo "" - - if [ $PREFLIGHT_FAILED -eq 1 ]; then - print_error "Pre-flight checks failed. Please resolve the issues above." - echo "" - echo "Continue anyway? (not recommended) [y/N]" - read -r response - if [[ ! "$response" =~ ^[Yy]$ ]]; then - print_error "Setup aborted by user" - exit 1 - fi - else - print_success "Pre-flight checks passed" - fi - - echo "" - echo "Press ENTER to begin installation..." - read -} - -# Check if running on macOS check_mac -# Run pre-flight checks +echo "" +echo -e "${BLUE}RIoT Secure — Full Single-Device Setup${NC}" +echo "" +echo -e "${YELLOW}⏱ Estimated installation time: 20-40 minutes${NC}" +echo "" +echo "The following will be installed/configured:" +echo " • Homebrew (package manager)" +echo " • Ollama (AI model runtime)" +echo " • Docker Desktop (containerization)" +echo " • Onyx (web interface)" +echo " • RIoT AI models (several GB download)" +echo "" + preflight_checks -# ============================================================================= -# STEP 1: Homebrew -# ============================================================================= -print_step "STEP 1: Installing Homebrew" - -if command -v brew &> /dev/null; then - print_success "Homebrew is already installed" - brew --version -else - print_warning "Installing Homebrew..." - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" - - # Add Homebrew to shell profile - echo >> ~/.zprofile - echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile - eval "$(/opt/homebrew/bin/brew shellenv)" - - print_success "Homebrew installed successfully" -fi +install_homebrew +install_ollama +setup_repo +install_docker +install_onyx +setup_models +web_config "host.docker.internal" +rag_upload # ============================================================================= -# STEP 2: Ollama -# ============================================================================= -print_step "STEP 2: Installing Ollama" - -if command -v ollama &> /dev/null; then - print_success "Ollama is already installed" - ollama --version -else - print_warning "Installing Ollama..." - curl -fsSL https://ollama.com/install.sh | sh - print_success "Ollama installed successfully" -fi - -# Ensure Ollama service is running -print_warning "Starting Ollama service..." -if ! pgrep -x "ollama" > /dev/null; then - # Start Ollama in the background - nohup ollama serve > /tmp/ollama.log 2>&1 & - sleep 3 # Give it time to start - - if pgrep -x "ollama" > /dev/null; then - print_success "Ollama service started" - else - print_warning "Ollama service may not have started properly" - echo " Check logs at: /tmp/ollama.log" - fi -else - print_success "Ollama service already running" -fi - -# ============================================================================= -# STEP 3: Clone Repository -# ============================================================================= -print_step "STEP 3: Setting up Repository" - -# Clone or update the repository first, as Onyx will be installed here -if [ -d ~/riotsecure ]; then - print_warning "riotsecure directory already exists" - cd ~/riotsecure - git pull - print_success "Repository updated" -else - print_warning "Cloning riotsecure repository..." - cd ~ - git clone https://github.com/cediackermann/riotsecure.git - cd ~/riotsecure - print_success "Repository cloned" -fi - -# ============================================================================= -# STEP 4: Docker Desktop -# ============================================================================= -print_step "STEP 4: Installing Docker Desktop" - -if [ -d "/Applications/Docker.app" ]; then - print_success "Docker Desktop is already installed" -else - print_warning "Installing Docker Desktop via Homebrew..." - brew install --cask docker-desktop - print_success "Docker Desktop installed" -fi - -print_warning "Opening Docker Desktop..." -if [ -d "/Applications/Docker.app" ]; then - open -a Docker -else - print_error "Docker.app not found in /Applications. Please install Docker Desktop manually." - exit 1 -fi - -echo "" -echo "MANUAL STEP REQUIRED:" -echo "1. Click through the Docker Desktop installer" -echo "2. Install any prompted software updates" -echo "3. Go to Docker → Settings → Resources and set:" -echo " - CPU limit: MAX" -echo " - Memory limit: 20 GB" -echo " - Disk usage limit: MAX" -echo "4. Click 'Apply & Restart'" -echo "" -wait_for_user - -# Wait for Docker to be ready -print_warning "Waiting for Docker to be ready..." -while ! docker info &> /dev/null; do - echo "Waiting for Docker daemon..." - sleep 5 -done -print_success "Docker is ready" - -# ============================================================================= -# STEP 5: Onyx -# ============================================================================= -print_step "STEP 5: Installing Onyx" - -if [ -d ~/riotsecure/onyx_data ]; then - print_warning "Onyx data directory already exists. Skipping installation." -else - print_warning "Installing Onyx..." - echo "When prompted:" - echo " 1. Press ENTER to acknowledge" - echo " 2. Choose '2' for Standard" - echo " 3. Press ENTER for Edge" - echo "" - - # Ensure we're in the riotsecure directory so onyx_data is created there - cd ~/riotsecure - - # Download and run Onyx installer - # Note: The interactive prompts need to be handled by the user - curl -fsSL https://onyx.app/install_onyx.sh | bash - - print_success "Onyx installation complete" -fi - -# Prevent sleep -print_warning "Configuring power settings to prevent sleep..." -sudo pmset -a sleep 0 disksleep 0 -print_success "Sleep prevention configured" - -# ============================================================================= -# STEP 6: Ollama Models -# ============================================================================= -print_step "STEP 6: Setting up Ollama Models" - -# Ensure we're in the riotsecure directory -cd ~/riotsecure - -print_warning "Creating Ollama models from modelfiles..." -if [ -f "./updateModels.sh" ]; then - chmod +x ./updateModels.sh - ./updateModels.sh modelfiles - print_success "Ollama models created successfully" -else - print_error "updateModels.sh not found!" -fi - -# ============================================================================= -# STEP 7: Web Interface Configuration -# ============================================================================= -print_step "STEP 7: Web Interface Configuration" - -echo "" -echo "MANUAL STEPS REQUIRED:" -echo "" -echo "1. Open your browser to http://localhost:3000" -echo "2. Create an admin account" -echo "3. Go to Admin Panel → Language Models:" -echo " - Select 'Ollama' as provider and give it a name" -echo " - Set API base URL to: http://host.docker.internal:11434" -echo " - Refresh the model list" -echo " - Select at least the three RIoT models" -echo " - Click 'Connect'" -echo "4. Go to Admin Panel → Chat Preferences → System Prompt → Modify Prompt" -echo " - Delete the entire prompt" -echo " - Save" -echo "" -wait_for_user - -# ============================================================================= -# STEP 8: RAG Content Upload -# ============================================================================= -print_step "STEP 8: RAG Content Upload" - -echo "Choose content upload method:" -echo " A - Upload as File (recommended)" -echo " B - Upload as URL" -echo " S - Skip this step" -echo "" -read -p "Enter your choice (A/B/S): " choice - -case $choice in - [Aa]) - print_warning "Fetching content from riot-sources.txt..." - if [ -f "./fetchContent.sh" ]; then - chmod +x ./fetchContent.sh - if [ -f "./riot-sources.txt" ]; then - ./fetchContent.sh riot-sources.txt - print_success "Content fetched successfully" - - echo "" - echo "MANUAL STEP REQUIRED:" - echo "1. In the web interface, go to Admin Panel → Add Connector → File" - echo "2. Give the connector a name" - echo "3. Upload the files from ~/riotsecure/content" - echo "4. Wait ~30 seconds for indexing to complete" - echo "" - else - print_error "riot-sources.txt not found!" - fi - else - print_error "fetchContent.sh not found!" - fi - wait_for_user - ;; - [Bb]) - echo "" - echo "MANUAL STEP REQUIRED:" - echo "1. In the web interface, go to Admin Panel → Add Connector → Web" - echo "2. Add each URL from riot-sources.txt as a separate connector" - echo "3. Use scrape method 'Single'" - echo "4. Wait ~30 seconds for indexing to complete" - echo "" - wait_for_user - ;; - [Ss]) - print_warning "Skipping RAG content upload" - ;; - *) - print_warning "Invalid choice. Skipping RAG content upload" - ;; -esac - -# ============================================================================= -# COMPLETION +# Done # ============================================================================= print_step "Setup Complete!" echo "" echo -e "${GREEN}✓ All automated steps completed successfully!${NC}" echo "" -echo "Your RIoT AI system should now be ready to use." -echo "" echo -e "Access the web interface at: ${BLUE}http://localhost:3000${NC}" -# Get local IP address LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "Unable to detect") if [ "$LOCAL_IP" != "Unable to detect" ]; then echo -e "From other devices on the network: ${BLUE}http://${LOCAL_IP}:3000${NC}" @@ -398,8 +61,8 @@ fi echo "" echo "Useful commands:" -echo " - View Onyx logs: cd ~/riotsecure/onyx_data && docker compose logs -f" -echo " - Restart Onyx: cd ~/riotsecure/onyx_data/deployment && docker compose restart" +echo " - View Onyx logs: cd ~/riotsecure/onyx_data && docker compose logs -f" +echo " - Restart Onyx: cd ~/riotsecure/onyx_data/deployment && docker compose restart" echo " - List Ollama models: ollama list" -echo " - Update Ollama models: cd ~/riotsecure && ./updateModels.sh modelfiles" +echo " - Update models: cd ~/riotsecure && ./updateModels.sh modelfiles" echo "" diff --git a/setup_ollama.sh b/setup_ollama.sh new file mode 100755 index 0000000..896236c --- /dev/null +++ b/setup_ollama.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# Setup script for the Ollama device. +# Run this on the machine that will host AI models only. +# No Docker required on this device. +# +# Usage: ./setup_ollama.sh + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/steps/common.sh" +source "$SCRIPT_DIR/steps/preflight.sh" +source "$SCRIPT_DIR/steps/step_homebrew.sh" +source "$SCRIPT_DIR/steps/step_ollama.sh" +source "$SCRIPT_DIR/steps/step_repo.sh" +source "$SCRIPT_DIR/steps/step_models.sh" + +check_mac + +echo "" +echo -e "${BLUE}RIoT Secure — Ollama Device Setup${NC}" +echo "This machine will run Ollama and serve AI models to the Onyx device." +echo "" +echo "Estimated installation time: 10-20 minutes" +echo "" +echo "The following will be installed/configured:" +echo " • Homebrew (package manager)" +echo " • Ollama (AI model runtime)" +echo " • RIoT AI models (several GB download)" +echo "" + +preflight_checks --skip-docker + +install_homebrew +setup_repo +install_ollama +setup_models + +# ============================================================================= +# Done +# ============================================================================= +print_step "Ollama Device Setup Complete!" + +echo "" +echo -e "${GREEN}✓ Ollama is running and models are loaded.${NC}" +echo "" +echo "Next steps:" +echo " 1. Note this machine's local IP address:" +LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "") + +if [ -n "$LOCAL_IP" ]; then + echo -e "${BLUE}===================================================${NC}" + echo -e "${GREEN} Run this command on the Onyx device:${NC}" + echo "" + echo -e " ${YELLOW}./setup_onyx.sh --ollama-host ${LOCAL_IP}${NC}" + echo "" + echo -e "${BLUE}===================================================${NC}" +else + print_warning "Could not detect local IP address automatically." + echo " Find it manually with: ipconfig getifaddr en0" + echo " Then on the Onyx device run:" + echo -e " ${YELLOW}./setup_onyx.sh --ollama-host ${NC}" +fi + +echo "" +echo "Useful commands:" +echo " - List Ollama models: ollama list" +echo " - Update models: cd ~/riotsecure && ./updateModels.sh modelfiles" +echo " - View Ollama logs: tail -f /tmp/ollama.log" +echo "" diff --git a/setup_onyx.sh b/setup_onyx.sh new file mode 100755 index 0000000..fde7f71 --- /dev/null +++ b/setup_onyx.sh @@ -0,0 +1,161 @@ +#!/bin/bash +# Setup script for the Onyx device. +# Run this on the machine that will host the Onyx web interface. +# Docker is required on this device; Ollama is NOT installed here. +# +# Usage: +# ./setup_onyx.sh # auto-detect Ollama host +# ./setup_onyx.sh --ollama-host # override with a specific host + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/steps/common.sh" +source "$SCRIPT_DIR/steps/preflight.sh" +source "$SCRIPT_DIR/steps/step_homebrew.sh" +source "$SCRIPT_DIR/steps/step_repo.sh" +source "$SCRIPT_DIR/steps/step_docker.sh" +source "$SCRIPT_DIR/steps/step_onyx.sh" +source "$SCRIPT_DIR/steps/step_webconfig.sh" +source "$SCRIPT_DIR/steps/step_rag.sh" + +check_mac + +# --------------------------------------------------------------------------- +# Detect where Ollama is running +# --------------------------------------------------------------------------- +detect_ollama_host() { + # 1. Check if Ollama is reachable on the Docker host (single-device) + if curl -sf --connect-timeout 2 http://host.docker.internal:11434 >/dev/null 2>&1; then + echo "host.docker.internal" + return + fi + + # 2. Scan the local /24 subnet for port 11434 + local LOCAL_IP + LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "") + if [ -z "$LOCAL_IP" ]; then + echo "" + return + fi + + local SUBNET + SUBNET=$(echo "$LOCAL_IP" | cut -d. -f1-3) + + print_warning "Ollama not found locally — scanning ${SUBNET}.0/24 for Ollama..." + + local FOUND=() + for i in $(seq 1 254); do + (nc -z -w 1 "${SUBNET}.${i}" 11434 2>/dev/null && echo "${SUBNET}.${i}") & + done + # Collect results as background jobs finish + while IFS= read -r line; do + FOUND+=("$line") + done < <(wait; jobs -p | xargs -I{} wait {} 2>/dev/null; true) + + # Re-run synchronously to get output (background approach above doesn't capture stdout cleanly) + FOUND=() + for i in $(seq 1 254); do + if nc -z -w 1 "${SUBNET}.${i}" 11434 2>/dev/null; then + FOUND+=("${SUBNET}.${i}") + fi + done + + if [ ${#FOUND[@]} -eq 1 ]; then + echo "${FOUND[0]}" + elif [ ${#FOUND[@]} -gt 1 ]; then + # Multiple hosts found — let the user pick + echo "" >&2 + print_warning "Multiple hosts with Ollama found:" >&2 + for i in "${!FOUND[@]}"; do + echo " $((i+1))) ${FOUND[$i]}" >&2 + done + echo "" >&2 + read -p "Select the Ollama host (1-${#FOUND[@]}): " pick >&2 + echo "${FOUND[$((pick-1))]}" + else + echo "" + fi +} + +# --------------------------------------------------------------------------- +# Parse arguments +# --------------------------------------------------------------------------- +OLLAMA_HOST_OVERRIDE="" +while [[ $# -gt 0 ]]; do + case "$1" in + --ollama-host) + OLLAMA_HOST_OVERRIDE="$2" + shift 2 + ;; + *) + echo "Unknown argument: $1" + echo "Usage: $0 [--ollama-host ]" + exit 1 + ;; + esac +done + +echo "" +echo -e "${BLUE}RIoT Secure — Onyx Device Setup${NC}" +echo "" +echo "Estimated installation time: 15-30 minutes" +echo "" +echo "The following will be installed/configured:" +echo " • Homebrew (package manager)" +echo " • Docker Desktop (containerization)" +echo " • Onyx (web interface)" +echo "" + +preflight_checks + +install_homebrew +setup_repo +install_docker +install_onyx + +# --------------------------------------------------------------------------- +# Resolve Ollama host (after Docker is running so host.docker.internal works) +# --------------------------------------------------------------------------- +if [ -n "$OLLAMA_HOST_OVERRIDE" ]; then + OLLAMA_HOST="$OLLAMA_HOST_OVERRIDE" + echo -e "Using provided Ollama host: ${BLUE}${OLLAMA_HOST}${NC}" +else + print_warning "Detecting Ollama host..." + OLLAMA_HOST=$(detect_ollama_host) + + if [ -z "$OLLAMA_HOST" ]; then + print_warning "Could not detect Ollama automatically." + read -p "Enter the IP address or hostname of the Ollama device: " OLLAMA_HOST + fi + + if [ "$OLLAMA_HOST" = "host.docker.internal" ]; then + print_success "Ollama detected on this machine (single-device mode)" + else + print_success "Ollama detected at: ${OLLAMA_HOST}" + fi +fi + +web_config "$OLLAMA_HOST" +rag_upload + +# ============================================================================= +# Done +# ============================================================================= +print_step "Onyx Device Setup Complete!" + +echo "" +echo -e "${GREEN}✓ All automated steps completed successfully!${NC}" +echo "" +echo -e "Access the web interface at: ${BLUE}http://localhost:3000${NC}" + +LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null || echo "") +if [ -n "$LOCAL_IP" ]; then + echo -e "From other devices on the network: ${BLUE}http://${LOCAL_IP}:3000${NC}" +fi + +echo "" +echo "Useful commands:" +echo " - View Onyx logs: cd ~/riotsecure/onyx_data && docker compose logs -f" +echo " - Restart Onyx: cd ~/riotsecure/onyx_data/deployment && docker compose restart" +echo "" diff --git a/steps/common.sh b/steps/common.sh new file mode 100755 index 0000000..000fa9f --- /dev/null +++ b/steps/common.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Shared helpers sourced by all setup scripts + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +print_step() { + echo -e "\n${BLUE}===================================================${NC}" + echo -e "${BLUE}$1${NC}" + echo -e "${BLUE}===================================================${NC}\n" +} + +print_header() { + echo -e "\n${BLUE}===================================================${NC}" + echo -e "${BLUE}$1${NC}" + echo -e "${BLUE}===================================================${NC}\n" +} + +print_section() { echo -e "\n${BLUE}▶ $1${NC}"; } +print_success() { echo -e "${GREEN}✓ $1${NC}"; } +print_warning() { echo -e "${YELLOW}⚠ $1${NC}"; } +print_error() { echo -e "${RED}✗ $1${NC}"; } + +wait_for_user() { + echo -e "\n${YELLOW}Press ENTER when you have completed the above step...${NC}" + read +} + +ask_confirmation() { + echo -e "${YELLOW}$1 [y/N]${NC}" + read -r response + [[ "$response" =~ ^[Yy]$ ]] +} + +check_mac() { + if [[ "$OSTYPE" != "darwin"* ]]; then + print_error "This script is designed for macOS. Exiting." + exit 1 + fi +} diff --git a/steps/preflight.sh b/steps/preflight.sh new file mode 100755 index 0000000..cbf0fbe --- /dev/null +++ b/steps/preflight.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Pre-flight checks. Source common.sh before sourcing this file. +# Usage: preflight_checks [--skip-docker] [--skip-ollama] + +preflight_checks() { + local SKIP_DOCKER=0 + local SKIP_OLLAMA=0 + for arg in "$@"; do + [[ "$arg" == "--skip-docker" ]] && SKIP_DOCKER=1 + [[ "$arg" == "--skip-ollama" ]] && SKIP_OLLAMA=1 + done + + print_step "Pre-flight System Checks" + local PREFLIGHT_FAILED=0 + + MACOS_VERSION=$(sw_vers -productVersion) + MACOS_MAJOR=$(echo $MACOS_VERSION | cut -d. -f1) + echo -e "macOS Version: ${BLUE}$MACOS_VERSION${NC}" + if [ "$MACOS_MAJOR" -lt 12 ]; then + print_error "macOS 12 (Monterey) or later recommended. You have: $MACOS_VERSION" + PREFLIGHT_FAILED=1 + else + print_success "macOS version compatible" + fi + + AVAILABLE_GB=$(df -g / | awk 'NR==2 {print $4}') + echo -e "Available disk space: ${BLUE}${AVAILABLE_GB}GB${NC}" + if [ "$AVAILABLE_GB" -lt 30 ]; then + print_error "Insufficient disk space. Required: 30GB+, Available: ${AVAILABLE_GB}GB" + PREFLIGHT_FAILED=1 + elif [ "$AVAILABLE_GB" -lt 50 ]; then + print_warning "Low disk space. Recommended: 50GB+, Available: ${AVAILABLE_GB}GB" + else + print_success "Sufficient disk space available" + fi + + TOTAL_MEM_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}') + echo -e "Total system memory: ${BLUE}${TOTAL_MEM_GB}GB${NC}" + if [ "$TOTAL_MEM_GB" -lt 16 ]; then + print_warning "Low memory. Recommended: 16GB+, Available: ${TOTAL_MEM_GB}GB" + else + print_success "Sufficient memory available" + fi + + if ping -c 1 -W 2 8.8.8.8 &> /dev/null; then + print_success "Internet connectivity verified" + else + print_error "No internet connection detected" + PREFLIGHT_FAILED=1 + fi + + if [ $SKIP_DOCKER -eq 0 ]; then + if pgrep -x "Docker" > /dev/null 2>&1; then + print_warning "Docker Desktop is already running" + fi + if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null 2>&1; then + print_warning "Port 3000 is already in use (required for Onyx web interface)" + fi + fi + + if [ $PREFLIGHT_FAILED -eq 1 ]; then + print_error "Pre-flight checks failed. Please resolve the issues above." + echo "Continue anyway? (not recommended) [y/N]" + read -r response + if [[ ! "$response" =~ ^[Yy]$ ]]; then + print_error "Setup aborted by user" + exit 1 + fi + else + print_success "Pre-flight checks passed" + fi + + echo "" + echo "Press ENTER to begin installation..." + read +} diff --git a/steps/step_docker.sh b/steps/step_docker.sh new file mode 100755 index 0000000..e933ec1 --- /dev/null +++ b/steps/step_docker.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Step: Install and start Docker Desktop. Source common.sh before sourcing this file. + +install_docker() { + print_step "Installing Docker Desktop" + + if [ -d "/Applications/Docker.app" ]; then + print_success "Docker Desktop is already installed" + else + print_warning "Installing Docker Desktop via Homebrew..." + brew install --cask docker-desktop + print_success "Docker Desktop installed" + fi + + print_warning "Opening Docker Desktop..." + if [ -d "/Applications/Docker.app" ]; then + open -a Docker + else + print_error "Docker.app not found in /Applications. Please install Docker Desktop manually." + exit 1 + fi + + echo "" + echo "MANUAL STEP REQUIRED:" + echo "1. Click through the Docker Desktop installer" + echo "2. Install any prompted software updates" + local TOTAL_MEM_GB + TOTAL_MEM_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}') + local MEM_RECOMMENDATION + if [ "$TOTAL_MEM_GB" -ge 20 ]; then + MEM_RECOMMENDATION="20 GB" + else + MEM_RECOMMENDATION="MAX" + fi + + echo "3. Go to Docker → Settings → Resources and set:" + echo " - CPU limit: MAX" + echo " - Memory limit: ${MEM_RECOMMENDATION}" + echo " - Disk usage limit: MAX" + echo "4. Click 'Apply & Restart'" + echo "" + wait_for_user + + print_warning "Waiting for Docker to be ready..." + while ! docker info &> /dev/null; do + echo "Waiting for Docker daemon..." + sleep 5 + done + print_success "Docker is ready" +} diff --git a/steps/step_homebrew.sh b/steps/step_homebrew.sh new file mode 100755 index 0000000..141b9f8 --- /dev/null +++ b/steps/step_homebrew.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Step: Install Homebrew. Source common.sh before sourcing this file. + +install_homebrew() { + print_step "Installing Homebrew" + + if command -v brew &> /dev/null; then + print_success "Homebrew is already installed" + brew --version + else + print_warning "Installing Homebrew..." + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + + echo >> ~/.zprofile + echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile + eval "$(/opt/homebrew/bin/brew shellenv)" + + print_success "Homebrew installed successfully" + fi +} diff --git a/steps/step_models.sh b/steps/step_models.sh new file mode 100755 index 0000000..a2ec5b9 --- /dev/null +++ b/steps/step_models.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Step: Create Ollama models from modelfiles. Source common.sh before sourcing this file. +# Requires: repo cloned at ~/riotsecure, Ollama service running. + +setup_models() { + print_step "Setting up Ollama Models" + + cd ~/riotsecure + print_warning "Creating Ollama models from modelfiles..." + if [ -f "./updateModels.sh" ]; then + chmod +x ./updateModels.sh + ./updateModels.sh modelfiles + print_success "Ollama models created successfully" + else + print_error "updateModels.sh not found!" + exit 1 + fi +} diff --git a/steps/step_ollama.sh b/steps/step_ollama.sh new file mode 100755 index 0000000..df15ffb --- /dev/null +++ b/steps/step_ollama.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Step: Install and start Ollama. Source common.sh before sourcing this file. + +install_ollama() { + print_step "Installing Ollama" + + if command -v ollama &> /dev/null; then + print_success "Ollama is already installed" + ollama --version + else + print_warning "Installing Ollama..." + curl -fsSL https://ollama.com/install.sh | sh + print_success "Ollama installed successfully" + fi + + print_warning "Starting Ollama service..." + if ! pgrep -x "ollama" > /dev/null; then + nohup ollama serve > /tmp/ollama.log 2>&1 & + sleep 3 + + if pgrep -x "ollama" > /dev/null; then + print_success "Ollama service started" + else + print_warning "Ollama service may not have started properly" + echo " Check logs at: /tmp/ollama.log" + fi + else + print_success "Ollama service already running" + fi +} diff --git a/steps/step_onyx.sh b/steps/step_onyx.sh new file mode 100755 index 0000000..3c343ad --- /dev/null +++ b/steps/step_onyx.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Step: Install Onyx. Source common.sh before sourcing this file. +# Requires: Docker to be running, repo cloned at ~/riotsecure. + +install_onyx() { + print_step "Installing Onyx" + + if [ -d ~/riotsecure/onyx_data ]; then + print_warning "Onyx data directory already exists. Skipping installation." + else + print_warning "Installing Onyx..." + echo "When prompted:" + echo " 1. Press ENTER to acknowledge" + echo " 2. Choose '2' for Standard" + echo " 3. Press ENTER for Edge" + echo "" + + cd ~/riotsecure + curl -fsSL https://onyx.app/install_onyx.sh | bash + + print_success "Onyx installation complete" + fi + + print_warning "Configuring power settings to prevent sleep..." + sudo pmset -a sleep 0 disksleep 0 + print_success "Sleep prevention configured" +} diff --git a/steps/step_rag.sh b/steps/step_rag.sh new file mode 100755 index 0000000..c0149d5 --- /dev/null +++ b/steps/step_rag.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Step: RAG content upload. Source common.sh before sourcing this file. +# Requires: repo cloned at ~/riotsecure. + +rag_upload() { + print_step "RAG Content Upload" + + echo "Choose content upload method:" + echo " A - Upload as File (recommended)" + echo " B - Upload as URL" + echo " S - Skip this step" + echo "" + read -p "Enter your choice (A/B/S): " choice + + case $choice in + [Aa]) + print_warning "Fetching content from riot-sources.txt..." + cd ~/riotsecure + if [ -f "./fetchContent.sh" ]; then + chmod +x ./fetchContent.sh + if [ -f "./riot-sources.txt" ]; then + ./fetchContent.sh riot-sources.txt + print_success "Content fetched successfully" + + echo "" + echo "MANUAL STEP REQUIRED:" + echo "1. In the web interface, go to Admin Panel → Add Connector → File" + echo "2. Give the connector a name" + echo "3. Upload the files from ~/riotsecure/content" + echo "4. Wait ~30 seconds for indexing to complete" + echo "" + else + print_error "riot-sources.txt not found!" + fi + else + print_error "fetchContent.sh not found!" + fi + wait_for_user + ;; + [Bb]) + echo "" + echo "MANUAL STEP REQUIRED:" + echo "1. In the web interface, go to Admin Panel → Add Connector → Web" + echo "2. Add each URL from riot-sources.txt as a separate connector" + echo "3. Use scrape method 'Single'" + echo "4. Wait ~30 seconds for indexing to complete" + echo "" + wait_for_user + ;; + [Ss]) + print_warning "Skipping RAG content upload" + ;; + *) + print_warning "Invalid choice. Skipping RAG content upload" + ;; + esac +} diff --git a/steps/step_repo.sh b/steps/step_repo.sh new file mode 100755 index 0000000..f169856 --- /dev/null +++ b/steps/step_repo.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Step: Clone or update the riotsecure repository. Source common.sh before sourcing this file. + +setup_repo() { + print_step "Setting up Repository" + + if [ -d ~/riotsecure ]; then + print_warning "riotsecure directory already exists" + cd ~/riotsecure + git pull + print_success "Repository updated" + else + print_warning "Cloning riotsecure repository..." + cd ~ + git clone https://github.com/cediackermann/riotsecure.git + cd ~/riotsecure + print_success "Repository cloned" + fi +} diff --git a/steps/step_webconfig.sh b/steps/step_webconfig.sh new file mode 100755 index 0000000..3c77554 --- /dev/null +++ b/steps/step_webconfig.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Step: Web interface configuration instructions. Source common.sh before sourcing this file. +# OLLAMA_HOST: hostname/IP of the machine running Ollama (default: host.docker.internal) + +web_config() { + local OLLAMA_HOST="${1:-host.docker.internal}" + + print_step "Web Interface Configuration" + + echo "" + echo "MANUAL STEPS REQUIRED:" + echo "" + echo "1. Open your browser to http://localhost:3000" + echo "2. Create an admin account" + echo "3. Go to Admin Panel → Language Models:" + echo " - Select 'Ollama' as provider and give it a name" + echo " - Set API base URL to: http://${OLLAMA_HOST}:11434" + echo " - Refresh the model list" + echo " - Select at least the three RIoT models" + echo " - Click 'Connect'" + echo "4. Go to Admin Panel → Chat Preferences → System Prompt → Modify Prompt" + echo " - Delete the entire prompt" + echo " - Save" + echo "" + wait_for_user +}