Refactor setup into modular steps; add split-device support

- Extract shared helpers into steps/common.sh (colors, print_*, wait_for_user, ask_confirmation)
- Split each install step into its own sourced script under steps/
- setup.sh now sources step files instead of duplicating logic
- Add setup_ollama.sh: Ollama-only device setup (no Docker)
- Add setup_onyx.sh: Onyx-only device setup with auto-detection of Ollama host via network scan
- setup_ollama.sh prints ready-to-run setup_onyx.sh command with detected IP at completion
- Docker memory recommendation is MAX when machine has <20 GB RAM, 20 GB otherwise
- cleanup.sh and check-status.sh source steps/common.sh with inline curl fallback
- check-status.sh detects device mode (single/ollama/onyx) and skips irrelevant checks
- cleanup.sh reinstall message lists all three setup one-liners
- README updated with split-device one-liner commands
This commit is contained in:
cediackermann 2026-04-24 09:53:25 +02:00
parent 4ba7722dd7
commit ef27add5d3
16 changed files with 876 additions and 724 deletions

156
README.md
View file

@ -6,163 +6,99 @@
[Link](https://docs.google.com/presentation/d/12XRHySp_W6Mrh64nA_6Hi3s8XvliUoANP-p_ha0FHEA/edit?usp=sharing) [Link](https://docs.google.com/presentation/d/12XRHySp_W6Mrh64nA_6Hi3s8XvliUoANP-p_ha0FHEA/edit?usp=sharing)
---
## Quick Start ## Quick Start
**One-line installation** (recommended): ### Single device (Ollama + Onyx on the same machine)
```bash ```bash
bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup.sh) 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 ```bash
git clone https://github.com/cediackermann/riotsecure.git bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup_ollama.sh)
cd riotsecure
./setup.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 ```bash
cd ~/riotsecure bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup_onyx.sh)
./check-status.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
bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/cleanup.sh) 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 The scripts pause and prompt when manual action is required. Here is what to expect at each pause.
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```
Add Homebrew to your shell profile: ### Docker Desktop resources
```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
Go to **Docker → Settings → Resources** and set: Go to **Docker → Settings → Resources** and set:
| Setting | Value | | Setting | Value |
| ---------------- | ----- | | ---------------- | ---------------------------- |
| CPU limit | MAX | | CPU limit | MAX |
| Memory limit | 20 GB | | Memory limit | 20 GB (or MAX if less than 20 GB available) |
| Disk usage limit | MAX | | Disk usage limit | MAX |
Hit **Apply & Restart**. Hit **Apply & Restart**.
--- ### Onyx installer prompts
## 4. Onyx
```bash
curl -fsSL https://onyx.app/install_onyx.sh | bash
```
When prompted:
1. Press **Enter** to acknowledge 1. Press **Enter** to acknowledge
2. Choose **2** for Standard 2. Choose **2** for Standard
3. Press **Enter** for Edge 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**:
```bash
sudo pmset -a sleep 0 disksleep 0
```
---
## 5. Ollama Models
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 - Select **Ollama** as provider and give it a name
- Set the API base URL to `http://host.docker.internal:11434` - 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** - 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. 3. Go to **Admin Panel → Chat Preferences → System Prompt → Modify Prompt**, delete the entire prompt, and save.
--- ### RAG content upload
## 6. RAG Content Upload **Option A — File upload (recommended)**
### Option A — Upload as File
1. If needed, edit the URLs in `riot-sources.txt`.
2. Fetch content:
```bash ```bash
cd ~/riotsecure cd ~/riotsecure && ./fetchContent.sh riot-sources.txt
./fetchContent.sh riot-sources.txt
``` ```
3. In the web interface, go to **Admin Panel → Add Connector → File**. Then in the web interface: **Admin Panel → Add Connector → File**, upload the files from `~/riotsecure/content`, and wait ~30 seconds for indexing.
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 **Option B — URL connector**
1. In the web interface, go to **Admin Panel → Add Connector → Web**. 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.
2. Add each URL as a separate connector, using scrape method **Single**.
3. Wait ~30 seconds for indexing to complete.

View file

@ -1,51 +1,53 @@
#!/bin/bash #!/bin/bash
# Colors for output # Source shared helpers if running from the repo; otherwise define inline.
RED='\033[0;31m' SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GREEN='\033[0;32m' if [ -f "$SCRIPT_DIR/steps/common.sh" ]; then
YELLOW='\033[1;33m' source "$SCRIPT_DIR/steps/common.sh"
BLUE='\033[0;34m' else
NC='\033[0m' # No Color 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}" PASS="${GREEN}${NC}"
FAIL="${RED}${NC}" FAIL="${RED}${NC}"
WARN="${YELLOW}${NC}" WARN="${YELLOW}${NC}"
INFO="${BLUE}${NC}" INFO="${BLUE}${NC}"
print_header() { # ---------------------------------------------------------------------------
echo -e "\n${BLUE}═══════════════════════════════════════════════════${NC}" # Detect which role this machine plays
echo -e "${BLUE}$1${NC}" # ---------------------------------------------------------------------------
echo -e "${BLUE}═══════════════════════════════════════════════════${NC}\n" HAS_DOCKER=0
} HAS_OLLAMA=0
HAS_ONYX=0
print_section() { [ -d "/Applications/Docker.app" ] && HAS_DOCKER=1
echo -e "\n${BLUE}$1${NC}" command -v ollama &>/dev/null && HAS_OLLAMA=1
} [ -d ~/riotsecure/onyx_data ] && HAS_ONYX=1
check_command() { if [ $HAS_OLLAMA -eq 1 ] && [ $HAS_DOCKER -eq 1 ]; then
if command -v $1 &> /dev/null; then DEVICE_MODE="single"
echo -e "$PASS $2 installed" elif [ $HAS_OLLAMA -eq 1 ]; then
return 0 DEVICE_MODE="ollama"
elif [ $HAS_DOCKER -eq 1 ] || [ $HAS_ONYX -eq 1 ]; then
DEVICE_MODE="onyx"
else else
echo -e "$FAIL $2 not found" DEVICE_MODE="unknown"
return 1
fi 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" 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 OVERALL_STATUS=0
# ============================================================================= # =============================================================================
@ -56,7 +58,6 @@ print_section "System Information"
echo -e "$INFO macOS Version: $(sw_vers -productVersion)" echo -e "$INFO macOS Version: $(sw_vers -productVersion)"
echo -e "$INFO Hostname: $(hostname)" echo -e "$INFO Hostname: $(hostname)"
# Check available disk space
AVAILABLE_GB=$(df -g / | awk 'NR==2 {print $4}') AVAILABLE_GB=$(df -g / | awk 'NR==2 {print $4}')
if [ "$AVAILABLE_GB" -lt 20 ]; then if [ "$AVAILABLE_GB" -lt 20 ]; then
echo -e "$WARN Available disk space: ${AVAILABLE_GB}GB (recommended: 20GB+)" 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" echo -e "$PASS Available disk space: ${AVAILABLE_GB}GB"
fi fi
# Check total memory
TOTAL_MEM_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}') TOTAL_MEM_GB=$(sysctl -n hw.memsize | awk '{print int($1/1024/1024/1024)}')
if [ "$TOTAL_MEM_GB" -lt 16 ]; then if [ "$TOTAL_MEM_GB" -lt 16 ]; then
echo -e "$WARN Total memory: ${TOTAL_MEM_GB}GB (recommended: 16GB+)" echo -e "$WARN Total memory: ${TOTAL_MEM_GB}GB (recommended: 16GB+)"
@ -78,63 +78,50 @@ fi
# ============================================================================= # =============================================================================
print_section "Core Components" print_section "Core Components"
# Homebrew if command -v brew &>/dev/null; then
if check_command brew "Homebrew"; then echo -e "$PASS Homebrew installed ($(brew --version | head -n1))"
echo -e " ${INFO} Version: $(brew --version | head -n1)"
else else
echo -e "$FAIL Homebrew not found"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
# Ollama # Ollama — only expected on single or ollama devices
if check_command ollama "Ollama"; then if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "ollama" ]; then
echo -e " ${INFO} Version: $(ollama --version 2>&1 | head -n1)" if command -v ollama &>/dev/null; then
echo -e "$PASS Ollama installed ($(ollama --version 2>&1 | head -n1))"
else else
echo -e "$FAIL Ollama not found"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
else
echo -e "$INFO Ollama not expected on this device (Onyx-only mode)"
fi
# Docker Desktop # Docker — only expected on single or onyx devices
if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "onyx" ]; then
if [ -d "/Applications/Docker.app" ]; then if [ -d "/Applications/Docker.app" ]; then
echo -e "$PASS Docker Desktop installed" echo -e "$PASS Docker Desktop installed"
else else
echo -e "$FAIL Docker Desktop not found" echo -e "$FAIL Docker Desktop not found"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
# =============================================================================
# Docker Service
# =============================================================================
print_section "Docker 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}')
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 else
echo -e "$WARN Docker is not running. Start Docker Desktop to continue." echo -e "$INFO Docker not expected on this device (Ollama-only mode)"
OVERALL_STATUS=1
fi fi
# ============================================================================= # =============================================================================
# Ollama Service # Ollama Service (single / ollama devices only)
# ============================================================================= # =============================================================================
if [ "$DEVICE_MODE" = "single" ] || [ "$DEVICE_MODE" = "ollama" ]; then
print_section "Ollama Service" print_section "Ollama Service"
if pgrep -x "ollama" > /dev/null; then if pgrep -x "ollama" > /dev/null; then
echo -e "$PASS Ollama service running" echo -e "$PASS Ollama service running"
# Check available models
if command -v ollama &> /dev/null; then
echo -e "\n Available models:" echo -e "\n Available models:"
MODELS=$(ollama list 2>/dev/null) MODELS=$(ollama list 2>/dev/null)
if [ -n "$MODELS" ]; then 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}') MODEL_NAME=$(echo "$line" | awk '{print $1}')
if [[ $MODEL_NAME == riot* ]]; then if [[ $MODEL_NAME == riot* ]]; then
echo -e " $PASS $line" echo -e " $PASS $line"
@ -146,28 +133,46 @@ if pgrep -x "ollama" > /dev/null; then
echo -e " $WARN No models found" echo -e " $WARN No models found"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
fi
else else
echo -e "$WARN Ollama service not running" echo -e "$WARN Ollama service not running"
echo -e " ${INFO} Start with: ollama serve" echo -e " ${INFO} Start with: ollama serve"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
fi
# ============================================================================= # =============================================================================
# Onyx Installation # 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" print_section "Onyx"
if [ -d ~/riotsecure/onyx_data ]; then if [ -d ~/riotsecure/onyx_data ]; then
echo -e "$PASS Onyx data directory exists" echo -e "$PASS Onyx data directory exists"
# Check if Onyx containers are running if docker info &>/dev/null; then
if command -v docker &> /dev/null && docker info &> /dev/null; then
cd ~/riotsecure/onyx_data 2>/dev/null cd ~/riotsecure/onyx_data 2>/dev/null
if [ -f "docker-compose.yaml" ] || [ -f "docker-compose.yml" ]; then if [ -f "docker-compose.yaml" ] || [ -f "docker-compose.yml" ]; then
echo -e "$PASS Docker Compose file found" echo -e "$PASS Docker Compose file found"
# Check running Onyx containers
ONYX_CONTAINERS=$(docker ps --filter "name=onyx" -q | wc -l | tr -d ' ') ONYX_CONTAINERS=$(docker ps --filter "name=onyx" -q | wc -l | tr -d ' ')
if [ "$ONYX_CONTAINERS" -gt 0 ]; then if [ "$ONYX_CONTAINERS" -gt 0 ]; then
echo -e "$PASS Onyx containers running: ${ONYX_CONTAINERS}" echo -e "$PASS Onyx containers running: ${ONYX_CONTAINERS}"
@ -182,7 +187,6 @@ if [ -d ~/riotsecure/onyx_data ]; then
fi fi
else else
echo -e "$FAIL Onyx data directory not found" echo -e "$FAIL Onyx data directory not found"
echo -e " ${INFO} Run ./setup.sh to install"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
@ -191,32 +195,26 @@ fi
# ============================================================================= # =============================================================================
print_section "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 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 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 "$PASS Web interface responding at http://localhost:3000"
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 || echo "")
LOCAL_IP=$(ipconfig getifaddr en0 2>/dev/null || ipconfig getifaddr en1 2>/dev/null)
if [ -n "$LOCAL_IP" ]; then if [ -n "$LOCAL_IP" ]; then
echo -e " ${INFO} Network access: ${GREEN}http://${LOCAL_IP}:3000${NC}" echo -e " ${INFO} Network access: ${GREEN}http://${LOCAL_IP}:3000${NC}"
fi fi
else else
echo -e "$WARN Port 3000 is active but interface not responding" echo -e "$WARN Port 3000 active but interface not responding"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
else else
echo -e "$FAIL Port 3000 not in use" echo -e "$FAIL Port 3000 not in use — Onyx containers may not be running"
echo -e " ${INFO} Onyx containers may not be running"
OVERALL_STATUS=1 OVERALL_STATUS=1
fi fi
fi
# ============================================================================= # =============================================================================
# Repository Status # Repository
# ============================================================================= # =============================================================================
print_section "Repository" print_section "Repository"
@ -226,15 +224,14 @@ if [ -d ~/riotsecure ]; then
cd ~/riotsecure 2>/dev/null cd ~/riotsecure 2>/dev/null
if [ -d .git ]; then if [ -d .git ]; then
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null) 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 git fetch --quiet 2>/dev/null
LOCAL=$(git rev-parse @ 2>/dev/null) LOCAL=$(git rev-parse @ 2>/dev/null)
REMOTE=$(git rev-parse @{u} 2>/dev/null) REMOTE=$(git rev-parse @{u} 2>/dev/null)
if [ "$LOCAL" != "$REMOTE" ]; then if [ "$LOCAL" != "$REMOTE" ]; then
echo -e " $WARN Updates available (run: git pull)" echo -e " $WARN Updates available — run: git pull"
else else
echo -e " $PASS Repository up to date" echo -e " $PASS Repository up to date"
fi fi
@ -251,14 +248,21 @@ fi
print_header "Summary" print_header "Summary"
if [ $OVERALL_STATUS -eq 0 ]; then if [ $OVERALL_STATUS -eq 0 ]; then
echo -e "${GREEN}✓ All systems operational${NC}\n" echo -e "${GREEN}✓ All systems operational${NC}"
echo ""
exit 0 exit 0
else 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 "Common fixes:"
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 " • 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 " • Onyx not running → cd ~/riotsecure/onyx_data && docker compose up -d"
fi
echo " • Low disk space → Free up disk space" echo " • Low disk space → Free up disk space"
echo "" echo ""
exit 1 exit 1

View file

@ -1,45 +1,21 @@
#!/bin/bash #!/bin/bash
# Colors for output set -e
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions # Source shared helpers if running from the repo; otherwise define inline.
print_header() { SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo -e "\n${BLUE}===================================================${NC}" if [ -f "$SCRIPT_DIR/steps/common.sh" ]; then
echo -e "${BLUE}$1${NC}" source "$SCRIPT_DIR/steps/common.sh"
echo -e "${BLUE}===================================================${NC}\n" 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() { print_success() { echo -e "${GREEN}$1${NC}"; }
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]$ ]]; }
print_warning() { check_mac() { [[ "$OSTYPE" != "darwin"* ]] && { echo -e "${RED}✗ macOS only${NC}"; exit 1; }; }
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 fi
}
# Check if running on macOS
check_mac check_mac
print_header "RIoT AI Cleanup Script" print_header "RIoT AI Cleanup Script"
@ -110,11 +86,10 @@ if command -v ollama &> /dev/null; then
print_warning "No RIoT models found, skipping" print_warning "No RIoT models found, skipping"
fi fi
# Optionally remove Ollama itself
echo "" echo ""
if ask_confirmation "Remove Ollama completely? (This will remove ALL models)"; then if ask_confirmation "Remove Ollama completely? (This will remove ALL models)"; then
print_warning "Stopping Ollama service..." print_warning "Stopping Ollama service..."
pkill -9 ollama 2>/dev/null pkill -9 ollama 2>/dev/null || true
print_warning "Removing Ollama data..." print_warning "Removing Ollama data..."
rm -rf ~/.ollama rm -rf ~/.ollama
@ -147,15 +122,14 @@ if [ -d "/Applications/Docker.app" ]; then
if ask_confirmation "Uninstall Docker Desktop?"; then if ask_confirmation "Uninstall Docker Desktop?"; then
print_warning "Quitting Docker Desktop..." print_warning "Quitting Docker Desktop..."
osascript -e 'quit app "Docker"' 2>/dev/null osascript -e 'quit app "Docker"' 2>/dev/null || true
sleep 3 sleep 3
print_warning "Uninstalling Docker Desktop..." print_warning "Uninstalling Docker Desktop..."
if command -v brew &> /dev/null; then 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 fi
# Remove Docker data
if ask_confirmation "Remove Docker data and containers? (WARNING: This affects all Docker usage)"; then 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/Containers/com.docker.docker
rm -rf ~/Library/Application\ Support/Docker\ Desktop rm -rf ~/Library/Application\ Support/Docker\ Desktop
@ -180,15 +154,12 @@ print_header "STEP 4: Repository Cleanup"
if [ -d ~/riotsecure ]; then if [ -d ~/riotsecure ]; then
echo "Found riotsecure repository at ~/riotsecure" echo "Found riotsecure repository at ~/riotsecure"
# Check if there are uncommitted changes
cd ~/riotsecure cd ~/riotsecure
if [ -d .git ]; then if [ -d .git ] && ! git diff-index --quiet HEAD -- 2>/dev/null; then
if ! git diff-index --quiet HEAD -- 2>/dev/null; then
print_warning "Repository has uncommitted changes!" print_warning "Repository has uncommitted changes!"
git status --short git status --short
echo "" echo ""
fi fi
fi
if ask_confirmation "Remove the riotsecure repository?"; then if ask_confirmation "Remove the riotsecure repository?"; then
cd ~ cd ~
@ -203,23 +174,9 @@ else
fi fi
# ============================================================================= # =============================================================================
# STEP 5: Content Directory # STEP 5: Power Settings
# ============================================================================= # =============================================================================
print_header "STEP 5: Downloaded Content Cleanup" print_header "STEP 5: Power Settings 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"
if ask_confirmation "Restore default sleep settings?"; then if ask_confirmation "Restore default sleep settings?"; then
print_warning "Restoring sleep settings..." print_warning "Restoring sleep settings..."
@ -230,9 +187,9 @@ else
fi 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 if command -v brew &> /dev/null; then
echo -e "${YELLOW}Note: Homebrew may be used by many other applications.${NC}" 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..." print_warning "Uninstalling Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)" /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/uninstall.sh)"
# Remove Homebrew from shell profile
if [ -f ~/.zprofile ]; then if [ -f ~/.zprofile ]; then
sed -i.bak '/homebrew/d' ~/.zprofile sed -i.bak '/homebrew/d' ~/.zprofile
print_success "Removed Homebrew from .zprofile" print_success "Removed Homebrew from .zprofile"
@ -262,13 +218,9 @@ print_header "Cleanup Complete"
echo -e "${GREEN}Cleanup process finished!${NC}" echo -e "${GREEN}Cleanup process finished!${NC}"
echo "" echo ""
echo "What was done:" echo "To reinstall, choose the setup that matches your configuration:"
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 "" echo ""
echo "To reinstall RIoT AI, run:" echo -e " Single device: ${BLUE}bash <(curl -fsSL https://raw.githubusercontent.com/cediackermann/riotsecure/main/setup.sh)${NC}"
echo -e " ${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 "" echo ""

395
setup.sh
View file

@ -1,117 +1,30 @@
#!/bin/bash #!/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 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
RED='\033[0;31m' source "$SCRIPT_DIR/steps/common.sh"
GREEN='\033[0;32m' source "$SCRIPT_DIR/steps/preflight.sh"
YELLOW='\033[1;33m' source "$SCRIPT_DIR/steps/step_homebrew.sh"
BLUE='\033[0;34m' source "$SCRIPT_DIR/steps/step_ollama.sh"
NC='\033[0m' # No Color 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 check_mac
print_step() {
echo -e "\n${BLUE}===================================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}===================================================${NC}\n"
}
print_success() { echo ""
echo -e "${GREEN}$1${NC}" echo -e "${BLUE}RIoT Secure — Full Single-Device Setup${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 ""
echo -e "${YELLOW}⏱ Estimated installation time: 20-40 minutes${NC}" echo -e "${YELLOW}⏱ Estimated installation time: 20-40 minutes${NC}"
echo " (depends on internet speed and system performance)"
echo "" echo ""
# Show what will be installed
echo "The following will be installed/configured:" echo "The following will be installed/configured:"
echo " • Homebrew (package manager)" echo " • Homebrew (package manager)"
echo " • Ollama (AI model runtime)" echo " • Ollama (AI model runtime)"
@ -120,277 +33,27 @@ preflight_checks() {
echo " • RIoT AI models (several GB download)" echo " • RIoT AI models (several GB download)"
echo "" 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
preflight_checks preflight_checks
# ============================================================================= install_homebrew
# STEP 1: Homebrew install_ollama
# ============================================================================= setup_repo
print_step "STEP 1: Installing Homebrew" install_docker
install_onyx
if command -v brew &> /dev/null; then setup_models
print_success "Homebrew is already installed" web_config "host.docker.internal"
brew --version rag_upload
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
# ============================================================================= # =============================================================================
# STEP 2: Ollama # Done
# =============================================================================
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
# ============================================================================= # =============================================================================
print_step "Setup Complete!" print_step "Setup Complete!"
echo "" echo ""
echo -e "${GREEN}✓ All automated steps completed successfully!${NC}" echo -e "${GREEN}✓ All automated steps completed successfully!${NC}"
echo "" 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}" 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") 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 if [ "$LOCAL_IP" != "Unable to detect" ]; then
echo -e "From other devices on the network: ${BLUE}http://${LOCAL_IP}:3000${NC}" echo -e "From other devices on the network: ${BLUE}http://${LOCAL_IP}:3000${NC}"
@ -401,5 +64,5 @@ echo "Useful commands:"
echo " - View Onyx logs: cd ~/riotsecure/onyx_data && docker compose logs -f" echo " - View Onyx logs: cd ~/riotsecure/onyx_data && docker compose logs -f"
echo " - Restart Onyx: cd ~/riotsecure/onyx_data/deployment && docker compose restart" echo " - Restart Onyx: cd ~/riotsecure/onyx_data/deployment && docker compose restart"
echo " - List Ollama models: ollama list" echo " - List Ollama models: ollama list"
echo " - Update Ollama models: cd ~/riotsecure && ./updateModels.sh modelfiles" echo " - Update models: cd ~/riotsecure && ./updateModels.sh modelfiles"
echo "" echo ""

70
setup_ollama.sh Executable file
View file

@ -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 <this-machine-IP>${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 ""

161
setup_onyx.sh Executable file
View file

@ -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 <IP> # 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 <IP or hostname>]"
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 ""

43
steps/common.sh Executable file
View file

@ -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
}

76
steps/preflight.sh Executable file
View file

@ -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
}

50
steps/step_docker.sh Executable file
View file

@ -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"
}

20
steps/step_homebrew.sh Executable file
View file

@ -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
}

18
steps/step_models.sh Executable file
View file

@ -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
}

30
steps/step_ollama.sh Executable file
View file

@ -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
}

27
steps/step_onyx.sh Executable file
View file

@ -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"
}

57
steps/step_rag.sh Executable file
View file

@ -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
}

19
steps/step_repo.sh Executable file
View file

@ -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
}

26
steps/step_webconfig.sh Executable file
View file

@ -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
}