How the Dream Server Installer Handles Modularity and Execution Flow

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 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 Central orchestrator Loads libraries, parses CLI options, sets up traps, and drives the phase execution loop

According to the DreamServer source code, files like [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/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 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:

set -euo pipefail

Lines 17-38 of 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) sets the $INSTALL_PHASE variable to a symbolic identifier before sourcing each phase script:

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) executes with relaxed error handling:

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/dream-server/installers/phases/03-features.sh) and [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.

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:

    touch installers/phases/14-mycustomfeature.sh
  2. Add the source instruction to install-core.sh in the desired execution order:

    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:


# 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) 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 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, then add a source instruction to 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) can check when generating Docker Compose configurations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →