# How the Dream Server Installer Handles Modularity and Execution Flow

> Discover how the Dream Server installer uses a modular, phase-driven Bash orchestrator for deterministic execution, separating pure functions from install steps with error isolation.

- Repository: [Light Heart Labs/DreamServer](https://github.com/Light-Heart-Labs/DreamServer)
- Tags: internals
- Published: 2026-05-18

---

**The Dream Server installer employs a modular, phase-driven Bash orchestrator that separates pure-function libraries from imperative install steps, enabling deterministic execution through sequential phase sourcing and strict error isolation.**

The Dream Server installer from [Light-Heart-Labs/DreamServer](https://github.com/Light-Heart-Labs/DreamServer) implements a sophisticated modular architecture designed for extensibility and reliability. By organizing code into reusable utility libraries and discrete execution phases, the system achieves clear separation of concerns while maintaining deterministic installation flow. This design allows operators to customize deployments through feature flags and enables developers to extend functionality without modifying core orchestration logic.

## Modular Architecture Overview

The installer follows a **functional core / imperative shell** pattern, dividing responsibilities across three distinct layers:

### Directory Structure and Responsibilities

| Directory | Purpose | Key Characteristics |
|-----------|---------|---------------------|
| `installers/lib/` | Reusable **pure Bash functions** | No side effects; safe to load early; includes logging, UI helpers, GPU detection, and Docker image handling |
| `installers/phases/` | **Sequential install phases** | Imperative scripts that perform side effects (install packages, pull images, create directories) |
| [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh) | Central **orchestrator** | Loads libraries, parses CLI options, sets up traps, and drives the phase execution loop |

According to the [DreamServer source code](https://github.com/Light-Heart-Labs/DreamServer), files like [[`constants.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/constants.sh)](https://github.com/Light-Heart-Labs/DreamServer/blob/main/dream-server/installers/lib/constants.sh) in the `lib/` directory contain only pure functions that can be unit-tested in isolation. In contrast, phase scripts such as [[`01-preflight.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/01-preflight.sh)](https://github.com/Light-Heart-Labs/DreamServer/blob/main/dream-server/installers/phases/01-preflight.sh) execute system-changing operations in a strict order enforced by the orchestrator.

## Execution Flow in Dream Server Installer

The [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh) orchestrator implements a deterministic **8-step execution flow** that ensures consistent behavior across different environments:

### 1. Preparation and Error Handling

The script begins with Bash strict mode and installs a global error trap:

```bash
set -euo pipefail

```

Lines 17-38 of [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh) establish the `cleanup_on_error` trap that reports the current `$INSTALL_PHASE` variable if any command fails. This provides immediate context for troubleshooting by identifying exactly which phase was executing when the error occurred.

### 2. Library Loading

All library files under `installers/lib/` are sourced (lines 71-84) before any side-effect operations begin. Because these contain only pure functions, they can be loaded safely without altering system state. Optional service-registry support loads conditionally at lines 85-93.

### 3. CLI Argument Parsing

The installer processes flags such as `--dry-run`, `--tier`, and `--all` through a standard `while`/`case` loop (lines 84-121). Parsed values populate global variables that subsequent phases reference to determine behavior.

### 4. Environment Detection

After flag processing, the installer calls `detect_pkg_manager` and validates Python module requirements (lines 28-35), establishing the baseline capabilities of the target system.

### 5. Sequential Phase Execution

The core loop (lines 45-66 of [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh)) sets the `$INSTALL_PHASE` variable to a symbolic identifier before sourcing each phase script:

```bash
INSTALL_PHASE="01-preflight";    source "$SCRIPT_DIR/installers/phases/01-preflight.sh"
INSTALL_PHASE="02-detection";    source "$SCRIPT_DIR/installers/phases/02-detection.sh"
INSTALL_PHASE="03-features";     source "$SCRIPT_DIR/installers/phases/03-features.sh"

# ... continues through phase 13

```

Each phase follows a **documented contract** specifying expected inputs (e.g., `$SCRIPT_DIR`, `$INTERACTIVE`) and provided outputs (e.g., detected GPU tier, enabled services list). This contract-based approach makes modular boundaries explicit and ensures safe phase composition.

### 6. Error Isolation for Informational Phases

Phase 13 ([`13-summary.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/13-summary.sh)) executes with relaxed error handling:

```bash
set +e

```

As implemented in lines 62-66, this ensures that summary display failures— which are informational only—never abort a successful installation.

### 7. Interrupt Protection

A double-Ctrl-C guard (`interrupt_handler` at lines 44-58) prevents accidental termination during critical operations, requiring deliberate confirmation before aborting the process.

### 8. Cleanup and Finalization

The orchestrator ensures proper cleanup through the trap system, logging final status and displaying the installation log location regardless of success or failure.

## How Feature Toggles Leverage Modularity

The Dream Server installer handles modularity through **feature flags** that phase scripts consume independently. CLI flags like `--all` or specific toggles (e.g., `ENABLE_VOICE`, `ENABLE_RAG`) populate global variables during argument parsing.

Subsequent phases—particularly [[`03-features.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/03-features.sh)](https://github.com/Light-Heart-Labs/DreamServer/blob/main/dream-server/installers/phases/03-features.sh) and [[`11-services.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/11-services.sh)](https://github.com/Light-Heart-Labs/DreamServer/blob/main/dream-server/installers/phases/11-services.sh)—read these flags to determine:

- Which Docker Compose overlays to enable
- Which container images to pull
- Which configuration files to generate

Because each phase only accesses the flags it requires, adding new optional services never necessitates changes to the core orchestration logic in [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh).

## Extending the Installer with New Phases

Adding functionality to the Dream Server installer requires only two steps thanks to its modular design:

1. Create a new phase file following the naming convention:

   ```bash
   touch installers/phases/14-mycustomfeature.sh
   ```

2. Add the source instruction to [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh) in the desired execution order:

   ```bash
   INSTALL_PHASE="14-mycustomfeature"
   source "$SCRIPT_DIR/installers/phases/14-mycustomfeature.sh"
   ```

New phases automatically inherit the global error handling, logging infrastructure from `installers/lib/`, and the `$INSTALL_PHASE` context tracking. The orchestrator's trap system ensures that failures in your new phase trigger the `cleanup_on_error` routine with proper phase identification.

### Example: Running Custom Installations

Execute the installer with specific tiers and feature flags:

```bash

# Default interactive installation

./install.sh

# Non-interactive tier-2 deployment with all optional services

./install.sh --tier 2 --all --non-interactive

# Preview changes without side effects

./install.sh --dry-run

```

## Summary

The Dream Server installer achieves robust modularity and deterministic execution flow through several key architectural decisions:

- **Pure-function libraries** in `installers/lib/` provide testable utilities without side effects
- **Phase-driven execution** ensures installation steps proceed in a strict, controllable order
- **Contract-based phase interfaces** document inputs and outputs, enabling safe extension
- **Global phase tracking** via `$INSTALL_PHASE` provides clear error context for troubleshooting
- **Feature flag architecture** allows optional components without core script modifications
- **Strict error isolation** prevents informational phases from failing successful installations

This design aligns with the **functional core / imperative shell** pattern, where pure Bash utilities coordinate with imperative system modifications through a minimal, well-instrumented orchestrator.

## Frequently Asked Questions

### How does the Dream Server installer handle errors during phase execution?

The installer implements a global `ERR` trap called `cleanup_on_error` (lines 17-38 of [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh)) that activates immediately when any command exits non-zero. Because the `$INSTALL_PHASE` variable contains the current phase identifier, the error handler reports exactly which phase failed and provides a link to the detailed log file, enabling rapid root cause analysis.

### What is the difference between the `lib/` and `phases/` directories in the Dream Server installer?

The `installers/lib/` directory contains **pure functions**—reusable Bash utilities like `detect_pkg_manager` and logging helpers that produce no side effects and can be safely sourced early. The `installers/phases/` directory contains **imperative scripts** that perform actual system modifications such as installing packages, pulling Docker images, and creating directories. This separation allows the core orchestrator to load utilities first, then execute side effects in a controlled sequence.

### Can I skip specific phases when running the Dream Server installer?

While the base [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh) orchestrator executes phases sequentially from 01 through 13, the modular architecture makes it straightforward to create custom installation profiles. Since each phase is a separate file sourced conditionally, advanced users can comment out specific `source` lines or create wrapper scripts that source only required phases. However, phases are designed to depend on previous phase outputs, so skipping early phases like `01-preflight` or `02-detection` may cause downstream failures.

### How do I add custom features to the Dream Server installer without modifying core files?

Create a new phase script in `installers/phases/` following the naming convention [`XX-descriptive-name.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/XX-descriptive-name.sh), then add a source instruction to [`install-core.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/install-core.sh) after existing phases. Your phase automatically gains access to all library functions from `installers/lib/` and integrates with the global error handling and `$INSTALL_PHASE` tracking. For optional functionality, expose feature flags that later phases (like [`11-services.sh`](https://github.com/Light-Heart-Labs/DreamServer/blob/main/11-services.sh)) can check when generating Docker Compose configurations.