Docker-based infrastructure for the MONITOR system.
This directory contains the Docker Compose configuration for running the complete MONITOR database stack:
- Neo4j - Canonical graph database (truth layer)
- MongoDB - Narrative documents and proposals
- Qdrant - Vector database for semantic search
- MinIO - Binary object storage (PDFs, images)
- OpenSearch - Full-text search (optional)
cp .env.example .envEdit .env with your passwords and configuration.
docker compose up -ddocker compose psAll services should show Up status.
-
Neo4j Browser: http://localhost:7474
- Username:
neo4j - Password:
<your NEO4J_PASSWORD from .env>
- Username:
-
MinIO Console: http://localhost:9001
- Username:
monitor - Password:
<your MINIO_PASSWORD from .env>
- Username:
-
OpenSearch Dashboards: http://localhost:5601
- Username:
admin - Password:
<your OPENSEARCH_PASSWORD from .env>
- Username:
Ports:
7474: HTTP (Browser UI)7687: Bolt (Database connection)
Volumes:
./neo4j/data: Database files./neo4j/logs: Log files./neo4j/import: CSV import directory./neo4j/plugins: APOC and GDS plugins
Configuration:
- Heap: 512MB initial, 2GB max
- Page cache: 1GB
- Plugins: APOC, Graph Data Science
Connection String:
bolt://localhost:7687
Ports:
27017: MongoDB server
Volumes:
./mongodb/data: Database files./mongodb/configdb: Configuration./mongodb/init: Initialization scripts
Connection String:
mongodb://monitor:<password>@localhost:27017/monitor
Collections:
scenes- Narrative scenesturns- Turn-by-turn logsproposed_changes- Canonization stagingresolutions- Dice/rules outcomescharacter_memories- NPC/PC memoriesdocuments- Ingested source documentssnippets- Document chunkscharacter_sheets- Character sheets
Ports:
6333: REST API6334: gRPC
Volumes:
./qdrant/storage: Vector indices
REST API:
http://localhost:6333
Collections:
scene_chunks- Scene summaries and turn embeddingsmemory_chunks- Character memory embeddingssnippet_chunks- Document snippet embeddings
Ports:
9000: S3-compatible API9001: Web Console
Volumes:
./minio/data: Object storage
Default Buckets:
monitor-documents- Uploaded PDFs/manualsmonitor-images- Character art, mapsmonitor-exports- Backup exports
S3 Endpoint:
http://localhost:9000
Ports:
9200: REST API9600: Performance Analyzer5601: Dashboards UI
Volumes:
./opensearch/data: Index data
REST API:
https://localhost:9200
Indices:
monitor-scenes- Scene full-text searchmonitor-facts- Fact full-text searchmonitor-snippets- Document snippet search
Run these Cypher commands in Neo4j Browser to create constraints:
CREATE CONSTRAINT entity_concreta_id IF NOT EXISTS
FOR (n:EntityInstance) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT entity_axiomatica_id IF NOT EXISTS
FOR (n:EntityArchetype) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT universe_id IF NOT EXISTS
FOR (n:Universe) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT story_id IF NOT EXISTS
FOR (n:Story) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT fact_id IF NOT EXISTS
FOR (n:Fact) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT event_id IF NOT EXISTS
FOR (n:Event) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT source_id IF NOT EXISTS
FOR (n:Source) REQUIRE n.id IS UNIQUE;
CREATE CONSTRAINT axiom_id IF NOT EXISTS
FOR (n:Axiom) REQUIRE n.id IS UNIQUE;Create indices:
CREATE INDEX entity_universe IF NOT EXISTS
FOR (n:EntityInstance) ON (n.universe_id);
CREATE INDEX fact_universe IF NOT EXISTS
FOR (n:Fact) ON (n.universe_id);
CREATE INDEX fact_canon_level IF NOT EXISTS
FOR (n:Fact) ON (n.canon_level);
CREATE INDEX story_universe IF NOT EXISTS
FOR (n:Story) ON (n.universe_id);Create a file at ./mongodb/init/01-init.js:
db = db.getSiblingDB('monitor');
// Create collections with validation
db.createCollection('scenes', {
validator: {
$jsonSchema: {
bsonType: 'object',
required: ['scene_id', 'story_id', 'universe_id', 'title', 'status'],
properties: {
scene_id: { bsonType: 'string' },
story_id: { bsonType: 'string' },
universe_id: { bsonType: 'string' },
title: { bsonType: 'string' },
status: { enum: ['active', 'finalizing', 'completed'] }
}
}
}
});
// Create indices
db.scenes.createIndex({ scene_id: 1 }, { unique: true });
db.scenes.createIndex({ story_id: 1, order: 1 });
db.scenes.createIndex({ status: 1 });
db.createCollection('proposed_changes');
db.proposed_changes.createIndex({ proposal_id: 1 }, { unique: true });
db.proposed_changes.createIndex({ scene_id: 1, status: 1 });
db.proposed_changes.createIndex({ status: 1 });
db.createCollection('character_memories');
db.character_memories.createIndex({ memory_id: 1 }, { unique: true });
db.character_memories.createIndex({ entity_id: 1, importance: -1 });
db.createCollection('documents');
db.documents.createIndex({ doc_id: 1 }, { unique: true });
db.documents.createIndex({ source_id: 1 });
db.createCollection('snippets');
db.snippets.createIndex({ snippet_id: 1 }, { unique: true });
db.snippets.createIndex({ doc_id: 1, chunk_index: 1 });Create collections via REST API:
# Scene chunks
curl -X PUT 'http://localhost:6333/collections/scene_chunks' \
-H 'Content-Type: application/json' \
-d '{
"vectors": {
"size": 1536,
"distance": "Cosine"
}
}'
# Memory chunks
curl -X PUT 'http://localhost:6333/collections/memory_chunks' \
-H 'Content-Type: application/json' \
-d '{
"vectors": {
"size": 1536,
"distance": "Cosine"
}
}'
# Snippet chunks
curl -X PUT 'http://localhost:6333/collections/snippet_chunks' \
-H 'Content-Type: application/json' \
-d '{
"vectors": {
"size": 1536,
"distance": "Cosine"
}
}'
# Create payload indices
curl -X PUT 'http://localhost:6333/collections/scene_chunks/index' \
-H 'Content-Type: application/json' \
-d '{
"field_name": "universe_id",
"field_schema": "keyword"
}'Create buckets via MinIO Console or mc client:
# Install MinIO client
wget https://dl.min.io/client/mc/release/linux-amd64/mc
chmod +x mc
sudo mv mc /usr/local/bin/
# Configure
mc alias set monitor http://localhost:9000 monitor <MINIO_PASSWORD>
# Create buckets
mc mb monitor/monitor-documents
mc mb monitor/monitor-images
mc mb monitor/monitor-exports
# Set policies
mc policy set download monitor/monitor-images
mc policy set private monitor/monitor-documentsdocker compose exec neo4j neo4j-admin database dump neo4j --to-path=/var/lib/neo4j/data/dumpsdocker compose exec mongodb mongodump --uri="mongodb://monitor:<password>@localhost:27017/monitor" --out=/data/backupdocker compose exec qdrant tar -czf /qdrant/storage/backup.tar.gz /qdrant/storagedocker compose exec neo4j neo4j-admin database load neo4j --from-path=/var/lib/neo4j/data/dumpsdocker compose exec mongodb mongorestore --uri="mongodb://monitor:<password>@localhost:27017/monitor" /data/backup# Neo4j
curl http://localhost:7474/
# MongoDB
docker compose exec mongodb mongosh --eval "db.adminCommand('ping')"
# Qdrant
curl http://localhost:6333/healthz
# MinIO
curl http://localhost:9000/minio/health/live
# OpenSearch
curl -k https://localhost:9200/_cluster/health# All services
docker compose logs -f
# Specific service
docker compose logs -f neo4j
docker compose logs -f mongodb
docker compose logs -f qdrantdocker compose statsCheck logs:
docker compose logs neo4jCommon issues:
- APOC plugin mismatch → ensure plugin version matches Neo4j version
- Memory limits → increase heap/pagecache in .env
Check authentication:
docker compose exec mongodb mongosh -u monitor -p <password>List collections:
curl http://localhost:6333/collectionsCreate if missing (see Initialization section above).
Check credentials in .env match what you're using.
Reset admin password:
docker compose down
rm -rf ./minio/data
docker compose up -d minioEdit docker-compose.yml:
environment:
- NEO4J_dbms_memory_heap_initial__size=1G
- NEO4J_dbms_memory_heap_max__size=4G
- NEO4J_dbms_memory_pagecache_size=2GAdd to docker-compose.yml:
command: --wiredTigerCacheSizeGB=2For large datasets, tune HNSW parameters:
curl -X PATCH 'http://localhost:6333/collections/scene_chunks' \
-H 'Content-Type: application/json' \
-d '{
"hnsw_config": {
"m": 32,
"ef_construct": 200
}
}'- Change all default passwords in
.env - Enable TLS for all services
- Configure firewall rules (only expose necessary ports)
- Enable authentication on all services
- Set up backup rotation
- Configure log aggregation
- Enable audit logging
- Set up monitoring/alerting
- Review and harden Docker security settings
In production, use separate networks:
networks:
frontend:
internal: false
backend:
internal: trueOnly expose MCP server to frontend network.
- DATABASE_INTEGRATION.md - Data layer architecture
- DATA_LAYER_API.md - API specifications
- MCP_TRANSPORT.md - MCP tool definitions
- ONTOLOGY.md - Data model specification