# Core Services Managed by Project N.O.M.A.D.: Complete Technical Overview

> Explore the six core services managed by Project N.O.M.A.D. including Kiwix Qdrant Ollama CyberChef FlatNotes and Kolibri orchestrated with Docker. Get a full technical overview.

- Repository: [Crosstalk Solutions/project-nomad](https://github.com/Crosstalk-Solutions/project-nomad)
- Tags: technical-overview
- Published: 2026-03-16

---

**Project N.O.M.A.D. manages six containerized core services—Kiwix, Qdrant, Ollama, CyberChef, FlatNotes, and Kolibri—defined in the service seeder and orchestrated via Docker with centralized constants in `SERVICE_NAMES`.**

Project N.O.M.A.D. (Network-Optimized Modular-Application-Deployment) by Crosstalk-Solutions is an open-source, offline-ready application deployment platform. It ships with a curated set of core services that can be installed, started, stopped, and updated through both the web UI and CLI, with all definitions centralized in the **service seeder** and referenced throughout the codebase via the `SERVICE_NAMES` constant.

## Core Services Managed by Project N.O.M.A.D.

The platform defines six essential services in [`admin/database/seeders/service_seeder.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/database/seeders/service_seeder.ts), each configured with specific Docker images and deployment parameters. These services cover information retrieval, AI/ML, data manipulation, and education.

### Kiwix: Information Library

**Kiwix** provides offline access to Wikipedia, medical references, and other encyclopedic content without requiring internet connectivity. The service runs the `ghcr.io/kiwix/kiwix-serve:3.8.1` container image and is referenced in code as `SERVICE_NAMES.KIWIX` with the value `nomad_kiwix_server`.

### Qdrant: Vector Database

**Qdrant** stores and searches high-dimensional embeddings for RAG (Retrieval-Augmented Generation) and semantic search capabilities. It uses the `qdrant/qdrant:v1.16` image and is identified by `SERVICE_NAMES.QDRANT` (`nomad_qdrant`). This service serves as a dependency for the AI assistant functionality.

### Ollama: AI Assistant

**Ollama** delivers a local Large Language Model (LLM) chat interface that requires no external API calls, operating entirely offline. Running on `ollama/ollama:0.15.2`, this service depends on Qdrant for vector storage and is referenced as `SERVICE_NAMES.OLLAMA` (`nomad_ollama`).

### CyberChef: Data Tools

**CyberChef** functions as a "Swiss-army-knife" for data encoding, encryption, and analysis. The service uses the `ghcr.io/gchq/cyberchef:10.19.4` image and is identified by `SERVICE_NAMES.CYBERCHEF` (`nomad_cyberchef`).

### FlatNotes: Notes

**FlatNotes** offers simple markdown-based note-taking with local storage capabilities. It deploys using the `dullage/flatnotes:v5.5.4` image and is referenced as `SERVICE_NAMES.FLATNOTES` (`nomad_flatnotes`).

### Kolibri: Education Platform

**Kolibri** serves as an offline learning platform designed for schools, supporting videos, quizzes, and structured curriculum delivery. The service runs `treehouses/kolibri:0.12.8` and is identified by `SERVICE_NAMES.KOLIBRI` (`nomad_kolibri`).

## How Project N.O.M.A.D. Manages Services

The platform employs a layered architecture for service management, combining database persistence with Docker orchestration to handle the **core services managed by Project N.O.M.A.D.**

### Persistence Layer

Service definitions are stored in the `services` table, modeled by [`admin/app/models/service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/app/models/service.ts). Key fields include `service_name`, `container_image`, `installed`, `installation_status`, and optional `depends_on` (e.g., Ollama depends on Qdrant). The **service seeder** populates these records on first run via [`admin/database/seeders/service_seeder.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/database/seeders/service_seeder.ts), ensuring all six core services are present in the database with their default configurations.

### Docker Orchestration

The `DockerService` class ([`admin/app/services/docker_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/app/services/docker_service.ts)) manages container lifecycle operations using the `SERVICE_NAMES` constants. It handles starting, stopping, and retrieving URLs for containers. For example, fetching a service URL uses the constant identifier:

```typescript
const url = await this.getServiceURL(SERVICE_NAMES.OLLAMA);

```

The implementation at line 443 of [`docker_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/docker_service.ts) resolves the container's bound host port to construct accessible URLs.

### Installation Flow

The `ServiceSeeder` runs during initial setup, executing the `run()` method (lines 64-73) to populate the database with default service entries. This ensures that core services are immediately available for installation through the administrative interface.

## Working with Core Services Programmatically

Developers interact with these services through TypeScript models and service classes. The following examples demonstrate common operations against the `services` table and Docker runtime.

### Listing All Core Services

Query the database for all six services using the canonical identifiers:

```typescript
import Service from '#models/service'

async function listCoreServices() {
  const services = await Service.query()
    .whereIn('service_name', [
      SERVICE_NAMES.KIWIX,
      SERVICE_NAMES.QDRANT,
      SERVICE_NAMES.OLLAMA,
      SERVICE_NAMES.CYBERCHEF,
      SERVICE_NAMES.FLATNOTES,
      SERVICE_NAMES.KOLIBRI,
    ])
    .select('service_name', 'friendly_name', 'installed', 'ui_location')

  return services
}

```

This query leverages the `Service` Lucid ORM model and the central `SERVICE_NAMES` enumeration to retrieve current installation status and UI endpoints.

### Checking Service Installation Status

Verify whether a specific service like Ollama is installed using `SystemService`:

```typescript
import SystemService from '#app/services/system_service'

async function isOllamaReady() {
  const systemService = new SystemService()
  return await systemService.checkServiceInstalled(SERVICE_NAMES.OLLAMA)
}

```

The `checkServiceInstalled` method (line 74 of [`system_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/system_service.ts)) queries the `installed` boolean flag from the corresponding database record.

### Retrieving Service UI URLs

Construct accessible web interfaces for installed services through `DockerService`:

```typescript
import DockerService from '#app/services/docker_service'

async function getServiceUI(name: string) {
  const docker = new DockerService()
  const url = await docker.getServiceURL(name)
  return `${url}/${await docker.getServiceUIPath(name)}`
}

// Example: UI URL for Kiwix
const kiwixUI = await getServiceUI(SERVICE_NAMES.KIWIX)

```

This pattern combines `getServiceURL` (line 443 of [`docker_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/docker_service.ts)) with path resolution to generate complete navigation links.

## Summary

- **Project N.O.M.A.D.** manages six containerized **core services**: Kiwix, Qdrant, Ollama, CyberChef, FlatNotes, and Kolibri.
- Service identities are centralized in [`admin/constants/service_names.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/constants/service_names.ts) via the `SERVICE_NAMES` constant object.
- Default configurations are seeded via [`admin/database/seeders/service_seeder.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/database/seeders/service_seeder.ts) on first run.
- Runtime management occurs through [`admin/app/services/docker_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/app/services/docker_service.ts), which handles container lifecycle and URL discovery.
- Database persistence uses the `Service` model ([`admin/app/models/service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/app/models/service.ts)) to track installation states and dependencies.
- High-level health checks are available through [`admin/app/services/system_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/app/services/system_service.ts).

## Frequently Asked Questions

### What is Project N.O.M.A.D.?

Project N.O.M.A.D. (Network-Optimized Modular-Application-Deployment) is an open-source platform by Crosstalk-Solutions designed for offline-first deployment of containerized applications. It enables users to install, manage, and run services like AI assistants and educational tools without requiring persistent internet connectivity.

### How does Project N.O.M.A.D. handle Docker container orchestration?

The platform uses the `DockerService` class ([`admin/app/services/docker_service.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/app/services/docker_service.ts)) to abstract container operations. This service reads the `SERVICE_NAMES` constants to start, stop, and restart containers, retrieve bound port URLs, and apply configuration updates through a standardized TypeScript API.

### Can additional services be added beyond the six core services?

While the **service seeder** ([`admin/database/seeders/service_seeder.ts`](https://github.com/Crosstalk-Solutions/project-nomad/blob/main/admin/database/seeders/service_seeder.ts)) defines six default services, the architecture supports extension through the `Service` model and `SERVICE_NAMES` pattern. New services can be added to the database with corresponding container images, though they require manual configuration and potential updates to the orchestration logic.

### Why does Ollama depend on Qdrant in Project N.O.M.A.D.?

**Ollama** utilizes **Qdrant** as its vector database backend to store and search high-dimensional embeddings for RAG (Retrieval-Augmented Generation) capabilities. This dependency is encoded in the `depends_on` field of the service definition, ensuring Qdrant initializes before Ollama during the startup sequence.