Prerequisites
- Docker Engine + Docker Compose v2.
- Ollama on the host (
http://127.0.0.1:11434) with thenomic-embed-textmodel pulled. Bothsemantic-searchandconsciousness-serverreach Ollama via the host. If Ollama isn't running,/api/searchreturns a precise503 ollama_unreachableinstead of pretending to work.
On Ubuntu / Debian: curl -fsSL https://ollama.com/install.sh | shfollowed by ollama pull nomic-embed-text. On macOS: install the Ollama desktop app, then pull the same model.
1. Clone the ecosystem
The whole stack lives in one repository. The compose file atdeploy/docker-compose.yml wires up six services plus Redis from this single tree.
git clone --recurse-submodules https://github.com/build-on-ai/consciousness-server.git
cd consciousness-server2. Install the CLI dependency
The signing helpers used later in this guide readsshpk from the key-server package. One command, once, before the boot.
(cd key-server && npm install)
# bin/sign-request, bin/cs-curl and bin/test-endpoints sign through sshpk,
# which lives in the key-server package. Skip this and they stop with
# "sshpk not found in .../key-server/node_modules".3. Boot the stack
The default stack includes key-server and every block verifies signed requests. Generate deployment keys before the first boot; otherwise the containers can be healthy while protected calls are correctly rejected.
bin/sync-ports
bin/bootstrap-keys
cd deploy
docker compose up -d --buildWhat you've just started, on the ports you can already reach from your LAN:
| Port | Service | Role |
|---|---|---|
13032 | consciousness-server | tasks, notes, chat, memory, agents, skills, embedded WebSocket |
13037 | semantic-search | Flask + ChromaDB; embeddings via Ollama |
13038 | machines-server | infrastructure awareness + telemetry |
13040 | key-server | ed25519 signed-request verification |
13041 | test-runner | async pytest / jest / npm execution |
13042 | git-workflow | post-commit hook receiver |
These are default host ports. The active subset lives inports.yaml at the repo root — every layer (native servers, compose, tooling) reads the same file.
3.5 Ports already in use on your host?
Edit ports.yaml to free host ports, then regeneratedeploy/.env. Do not edit docker-compose.yml: the port registry is the source of truth.
# Choose free host ports in ports.yaml, then regenerate deploy/.env:
bin/sync-ports
bin/sync-ports --check # reports drift in either artefact
cd deploy && docker compose up -d --buildAfter the edit, bin/sync-ports regeneratesdeploy/.env and compose interpolates the new values.bin/sync-ports --check confirms the two artefacts agree.
Container-internal ports (the PORT env vars inside services, REDIS_PORT against the redis container, inter-service URLs via docker DNS) stay hard-coded by design — they live inside the docker network and never collide with the host. Only the host-side ports move.
You can also override one port at a time without editingports.yaml:PORT_KEY_SERVER=13040 docker compose up -d. Useful for one-off experiments.
4. Verify everything is healthy
Each service exposes /health. A single loop confirms the stack came up cleanly:
for p in 13032 13037 13038 13040 13041 13042; do
curl -sf "http://127.0.0.1:$p/health" >/dev/null && echo "port $p OK"
done
# Expected:
# port 13032 OK
# port 13037 OK
# port 13038 OK
# port 13040 OK
# port 13041 OK
# port 13042 OKIf any port is missing,docker compose logs <service> from thedeploy/ directory shows what failed. The most common case is Ollama not running — fix that, restart withdocker compose restart semantic-search, and re-check.
5. Store your first memory
The memory layer is ready out of the box. No extra setup beyond the boot. Two calls — store a note, then find it again:
# bin/cs-curl reads ports.yaml and signs the request.
bin/cs-curl POST /api/notes \
'{"agent":"first-agent","type":"observation","title":"First note",
"content":"The stack came up from the README alone."}'
# Indexing runs just behind the write, so give it a second.
bin/cs-curl -b semantic-search POST /api/search \
'{"query":"did the stack come up"}'Notes and session summaries are what reaches the semantic index. Conversations and training records, written through/api/memory/conversations and/api/memory/training, persist to Redis and are served by the API, but they carry no embedding, so/api/search will not return them.
bin/cs-curl signs each protected request and resolves the configured target port from ports.yaml. Embeddings come from Ollama and the index lives in ChromaDB.
Next steps
- Cortex → — local AI agent powered by Ollama. Hooks into the same memory layer.
- Document Processor → — desktop app for local PDF / DOCX / TXT processing.
- Key Server → — ed25519 signed-request verification and an optional on-disk vault.
- Machines → — register additional machines so agents can route by GPU, VRAM, available models.
Cleaning up
The deploy/volumes/* tree (ChromaDB store, Redis dump, per-service logs) is written by containers running as root, so removing it from the host needs sudo. Three escalating levels:
cd deploy
docker compose down # stops containers, volumes stay
docker compose down -v # stops + removes named volumes
sudo rm -rf volumes # full reset to a pristine state