# How the ODS Installer Orchestrates the Installation Process: A 13-Phase Bash Pipeline

> Discover how the ODS installer orchestrates its 13-phase Bash pipeline for robust and secure installations. Learn about its pre-flight checks, error handling, and atomic locking.

- Repository: [Osmantic/ODS](https://github.com/Osmantic/ODS)
- Tags: internals
- Published: 2026-08-30

---

**The ODS installer orchestrates the installation process through a deterministic Bash pipeline centered on [`install-core.sh`](https://github.com/Osmantic/ODS/blob/main/install-core.sh), which sequences 13 discrete phases—from pre-flight validation to health checks—while using strict error handling (`set -euo pipefail`) and atomic locking to prevent concurrent model modifications.**

The Osmantic/ODS repository delivers a containerized data stack deployment system designed for diverse hardware targets. Understanding how the ODS installer orchestrates the installation process reveals a modular architecture that isolates pure helper functions from stateful installation logic, enabling reliable deployments across NVIDIA, AMD, and Apple Silicon environments.

## The Orchestrator Entry Point and Safety Foundations

The entire installation lifecycle is driven by **[`ods/install-core.sh`](https://github.com/Osmantic/ODS/blob/main/ods/install-core.sh)**, which serves as the single entry point and central orchestrator. Before executing any phase-specific logic, the script establishes rigorous safety mechanisms to ensure predictable failure behavior.

At lines 17–38, the installer configures Bash for strict error handling:

```bash
set -euo pipefail

```

This setting causes the script to exit immediately on errors, treat unset variables as fatal, and propagate pipeline failures. The orchestrator also initializes a global **`INSTALL_PHASE`** variable to track execution context and registers a **`cleanup_on_error`** trap that reports the specific phase name when failures occur. A defensive SIGINT handler prevents accidental cancellation through "double-tap" confirmation.

## Library Architecture: Pure Functions vs. Phase Scripts

The orchestrator maintains strict separation between stateless utilities and stateful installation steps. During initialization (lines 69–94), [`install-core.sh`](https://github.com/Osmantic/ODS/blob/main/install-core.sh) sources all files under **`installers/lib/`**, including:

- [`constants.sh`](https://github.com/Osmantic/ODS/blob/main/constants.sh) – Configuration constants
- [`logging.sh`](https://github.com/Osmantic/ODS/blob/main/logging.sh) – Output formatting utilities  
- [`detection.sh`](https://github.com/Osmantic/ODS/blob/main/detection.sh) – Hardware inspection functions
- [`tier-map.sh`](https://github.com/Osmantic/ODS/blob/main/tier-map.sh) – GPU-to-tier mapping logic

These libraries contain **pure functions** with no side effects; they perform calculations and return data without modifying system state. The orchestrator only invokes them when needed, ensuring that side effects occur exclusively within the phase scripts located in **`installers/phases/`**.

## The 13-Phase Installation Pipeline

The orchestrator progresses through thirteen distinct phases, setting `INSTALL_PHASE` before sourcing each corresponding script. This modular approach allows individual phases to fail with precise context while maintaining idempotency.

### Phase 01 – Pre-flight Validation

**[`installers/phases/01-preflight.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/01-preflight.sh)** performs system sanity checks before any installation work begins. This phase verifies the operating system compatibility, confirms required tools (`curl`, `jq`) are present, inspects optional tooling availability, validates firewall states, checks filesystem suitability, and detects existing installations that might conflict with the deployment.

### Phase 02 – Hardware Detection and Tier Mapping

**[`installers/phases/02-detection.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/02-detection.sh)** executes hardware detection routines from [`installers/lib/detection.sh`](https://github.com/Osmantic/ODS/blob/main/installers/lib/detection.sh) to determine GPU capabilities. Using **[`tier-map.sh`](https://github.com/Osmantic/ODS/blob/main/tier-map.sh)**, the system calculates the appropriate hardware tier, which determines which machine learning models and container configurations will be selected for the deployment.

### Phase 02b – External Service Integration

**[`installers/phases/02b-external-services.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/02b-external-services.sh)** prepares integrations with optional external LLM providers such as Lemonade or Ollama. This phase activates when flags like `--external-llm-url` are detected during argument parsing.

### Phase 03 – Feature Selection

**[`installers/phases/03-features.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/03-features.sh)** enables or disables optional services—including Voice, Workflows, and RAG (Retrieval-Augmented Generation)—based on environment variables populated during command-line argument processing.

### Phase 04 – System Requirements

**[`installers/phases/04-requirements.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/04-requirements.sh)** installs missing system packages using the distribution-specific package manager detected during pre-flight. This includes kernel headers, GPU drivers, and dependency libraries required by subsequent container operations.

### Phase 05 – Docker Preparation

**[`installers/phases/05-docker.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/05-docker.sh)** ensures the Docker daemon is present and correctly configured. The phase pulls base compose files and configures daemon settings appropriate for the detected GPU type (NVIDIA, AMD, or Apple Silicon).

### Phase 06 – Directory Structure and Permissions

**[`installers/phases/06-directories.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/06-directories.sh)** creates the `$INSTALL_DIR` directory tree and establishes strict permissions. The orchestrator generates environment files and immediately applies restrictive permissions (e.g., `chmod 600 .env`) to protect sensitive configuration data.

### Phase 07 – Development Tools

**[`installers/phases/07-devtools.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/07-devtools.sh)** installs optional debugging utilities such as `git` configuration helpers and enhanced `jq` tooling. These utilities support troubleshooting but are not required for runtime operation.

### Phase 08 – Container Image Acquisition

**[`installers/phases/08-images.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/08-images.sh)** pulls required container images for the LLM inference engine, dashboard, and any enabled optional services. The phase selects the appropriate GPU overlay file—[`docker-compose.amd.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.amd.yml), [`docker-compose.nvidia.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.nvidia.yml), or [`docker-compose.apple.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.apple.yml)—based on earlier detection results.

### Phase 09 – Offline Mode Configuration

**[`installers/phases/09-offline.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/09-offline.sh)** disables network-dependent steps when the `--offline` flag is set. This configuration supports air-gapped deployments, particularly useful for Apple Silicon machines operating without internet connectivity.

### Phase 10 – AMD GPU Optimization

**[`installers/phases/10-amd-tuning.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/10-amd-tuning.sh)** applies AMD-specific optimizations, including ROCm driver settings and memory allocation adjustments, when AMD GPUs are detected during the hardware discovery phase.

### Phase 11 – Service Deployment

**[`installers/phases/11-services.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/11-services.sh)** generates the final [`docker-compose.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.yml) by merging the base configuration with GPU-specific overlays and enabled feature extensions. The orchestrator then executes `docker compose up -d` to launch the containerized stack.

### Phase 12 – Health Verification

**[`installers/phases/12-health.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/12-health.sh)** polls each container’s health endpoint to verify successful startup. The phase implements retry logic and reports detailed status information for each service before declaring the installation successful.

### Phase 13 – Installation Summary

**[`installers/phases/13-summary.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/13-summary.sh)** prints URLs, access shortcuts, and post-installation instructions. This phase executes with `set +e` to ensure that cosmetic output failures never abort the installation after successful service deployment.

## Concurrency Control and Error Handling

Before executing Phase 08 (image pulling), the orchestrator acquires a model lifecycle lock via **`ods_model_lifecycle_lock_acquire`** (lines 45–47). This atomic locking mechanism prevents concurrent installer instances from downloading models or modifying configurations simultaneously, protecting against corruption during parallel installations. The lock is released only after services are successfully brought online.

The combination of `set -euo pipefail`, the `INSTALL_PHASE` tracking variable, and the `cleanup_on_error` trap ensures that any failure immediately halts execution while reporting the exact phase where the error occurred, simplifying debugging and log analysis.

## Command-Line Interface and Customization

The orchestrator parses flags in a `while [[ $# -gt 0 ]]` loop (lines 20–73), populating environment variables such as `ENABLE_VOICE`, `ENABLE_RAG`, and `INSTALL_TIER` that drive conditional logic throughout the phases.

Common invocation patterns include:

```bash

# Standard interactive installation

./install.sh

# Force tier 2 hardware profile with voice and RAG enabled, non-interactive mode

./install.sh --tier 2 --voice --rag --non-interactive

# Dry-run mode using existing Docker installation

./install.sh --skip-docker --dry-run

# Cloud deployment with external LLM provider

./install.sh --cloud --external-llm-url https://api.openai.com/v1 --external-llm-provider ollama

```

## Summary

- **[`install-core.sh`](https://github.com/Osmantic/ODS/blob/main/install-core.sh)** serves as the central orchestrator, implementing strict error handling with `set -euo pipefail` and phase-tracking via the `INSTALL_PHASE` variable.
- The installation pipeline executes **13 discrete phases**, from pre-flight validation ([`01-preflight.sh`](https://github.com/Osmantic/ODS/blob/main/01-preflight.sh)) through deployment ([`11-services.sh`](https://github.com/Osmantic/ODS/blob/main/11-services.sh)) to final health checks ([`12-health.sh`](https://github.com/Osmantic/ODS/blob/main/12-health.sh)).
- **Pure function libraries** in `installers/lib/` remain side-effect-free, while phase scripts in `installers/phases/` handle all stateful system modifications.
- **Atomic locking** via `ods_model_lifecycle_lock_acquire` prevents race conditions during model downloads and configuration changes.
- GPU-specific logic uses **tier mapping** and overlay compose files to support NVIDIA, AMD, and Apple Silicon hardware targets through a unified interface.

## Frequently Asked Questions

### What is the entry point for the ODS installer?

The entry point is **[`ods/install-core.sh`](https://github.com/Osmantic/ODS/blob/main/ods/install-core.sh)**, a Bash script that acts as the central orchestrator. It configures error handling, sources pure-function libraries from `installers/lib/`, parses command-line arguments, and sequentially executes the 13 installation phases located in `installers/phases/`.

### How does the ODS installer handle hardware detection and GPU tiers?

During **Phase 02**, the orchestrator sources [`installers/phases/02-detection.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/02-detection.sh), which calls hardware detection routines from [`installers/lib/detection.sh`](https://github.com/Osmantic/ODS/blob/main/installers/lib/detection.sh). The system uses **[`tier-map.sh`](https://github.com/Osmantic/ODS/blob/main/tier-map.sh)** to calculate the appropriate hardware tier based on GPU capabilities, then selects corresponding Docker Compose overlays ([`docker-compose.nvidia.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.nvidia.yml), [`docker-compose.amd.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.amd.yml), or [`docker-compose.apple.yml`](https://github.com/Osmantic/ODS/blob/main/docker-compose.apple.yml)) during Phase 08.

### What safety mechanisms prevent installation failures or concurrent modifications?

The installer implements **`set -euo pipefail`** to exit immediately on errors, an **`INSTALL_PHASE`** variable to track execution context, and a **`cleanup_on_error`** trap that reports the failing phase. Additionally, **`ods_model_lifecycle_lock_acquire`** creates an atomic lock before model downloads (lines 45–47), preventing concurrent installer instances from corrupting shared resources.

### How can I run the ODS installer in offline or cloud-only mode?

For **offline mode**, use the `--offline` flag to skip network-dependent steps (handled in Phase 09 via [`installers/phases/09-offline.sh`](https://github.com/Osmantic/ODS/blob/main/installers/phases/09-offline.sh)). For **cloud deployments**, use `--cloud` combined with `--external-llm-url` and `--external-llm-provider` flags to bypass local GPU detection and use external LLM services instead of local containerized models.