Skip to main content
Glama

basic-memory

project-root-env-var.md10.2 kB
# BASIC_MEMORY_PROJECT_ROOT Environment Variable **Status**: New Feature **PR**: #334 **Use Case**: Security, containerization, path constraints ## What's New v0.15.0 introduces the `BASIC_MEMORY_PROJECT_ROOT` environment variable to constrain all project paths to a specific directory. This provides security and enables safe multi-tenant deployments. ## Quick Examples ### Containerized Deployment ```bash # Docker/containerized environment export BASIC_MEMORY_PROJECT_ROOT=/app/data export BASIC_MEMORY_HOME=/app/data/basic-memory # All projects must be under /app/data bm project add my-project /app/data/my-project # ✓ Allowed bm project add my-project /tmp/unsafe # ✗ Blocked ``` ### Development Environment ```bash # Local development - no constraint (default) # BASIC_MEMORY_PROJECT_ROOT not set # Projects can be anywhere bm project add work ~/Documents/work-notes # ✓ Allowed bm project add personal ~/personal-kb # ✓ Allowed ``` ## How It Works ### Path Validation When `BASIC_MEMORY_PROJECT_ROOT` is set: 1. **All project paths are validated** against the root 2. **Paths are sanitized** to prevent directory traversal 3. **Symbolic links are resolved** and verified 4. **Escape attempts are blocked** (e.g., `../../../etc`) ### Path Sanitization ```python # Example internal validation project_root = "/app/data" user_path = "/app/data/../../../etc" # Sanitized and validated resolved_path = Path(user_path).resolve() # → "/etc" # Check if under project_root if not str(resolved_path).startswith(project_root): raise ValueError("Path must be under /app/data") ``` ## Configuration ### Set via Environment Variable ```bash # In shell or .bashrc/.zshrc export BASIC_MEMORY_PROJECT_ROOT=/app/data # Or in Docker docker run -e BASIC_MEMORY_PROJECT_ROOT=/app/data ... ``` ### Docker Deployment **Dockerfile:** ```dockerfile # Set project root for path constraints ENV BASIC_MEMORY_HOME=/app/data/basic-memory \ BASIC_MEMORY_PROJECT_ROOT=/app/data ``` **docker-compose.yml:** ```yaml services: basic-memory: environment: BASIC_MEMORY_HOME: /app/data/basic-memory BASIC_MEMORY_PROJECT_ROOT: /app/data volumes: - ./data:/app/data ``` ### Kubernetes Deployment ```yaml apiVersion: v1 kind: Pod spec: containers: - name: basic-memory env: - name: BASIC_MEMORY_PROJECT_ROOT value: "/app/data" - name: BASIC_MEMORY_HOME value: "/app/data/basic-memory" volumeMounts: - name: data-volume mountPath: /app/data ``` ## Use Cases ### 1. Container Security **Problem:** Containers shouldn't create projects outside mounted volumes **Solution:** ```bash # Set project root to volume mount export BASIC_MEMORY_PROJECT_ROOT=/app/data # Projects confined to volume bm project add notes /app/data/notes # ✓ bm project add evil /etc/passwd # ✗ Blocked ``` ### 2. Multi-Tenant SaaS **Problem:** Tenant A shouldn't access Tenant B's files **Solution:** ```bash # Per-tenant isolation export BASIC_MEMORY_PROJECT_ROOT=/app/data/tenant-${TENANT_ID} # Tenant can only create projects under their directory bm project add my-notes /app/data/tenant-123/notes # ✓ bm project add sneaky /app/data/tenant-456/notes # ✗ Blocked ``` ### 3. Shared Hosting **Problem:** Users need isolated project spaces **Solution:** ```bash # Per-user isolation export BASIC_MEMORY_PROJECT_ROOT=/home/${USER}/basic-memory # User confined to their home directory bm project add personal /home/alice/basic-memory/personal # ✓ bm project add other /home/bob/basic-memory/data # ✗ Blocked ``` ## Relationship with BASIC_MEMORY_HOME `BASIC_MEMORY_HOME` and `BASIC_MEMORY_PROJECT_ROOT` serve **different purposes**: | Variable | Purpose | Default | Example | |----------|---------|---------|---------| | `BASIC_MEMORY_HOME` | Default project location | `~/basic-memory` | Where "main" project lives | | `BASIC_MEMORY_PROJECT_ROOT` | Path constraint boundary | None (unrestricted) | Security boundary | ### Using Both Together ```bash # Typical containerized setup export BASIC_MEMORY_PROJECT_ROOT=/app/data # Constraint: all under /app/data export BASIC_MEMORY_HOME=/app/data/basic-memory # Default: main project location # This creates main project at /app/data/basic-memory # And ensures all other projects are also under /app/data ``` ### Key Differences **BASIC_MEMORY_HOME:** - Sets default project path - Used for "main" project - Does NOT enforce constraints - Optional - defaults to `~/basic-memory` **BASIC_MEMORY_PROJECT_ROOT:** - Enforces path constraints - Validates ALL project paths - Prevents path traversal - Optional - if not set, no constraints ## Validation Examples ### Valid Paths (with PROJECT_ROOT=/app/data) ```bash export BASIC_MEMORY_PROJECT_ROOT=/app/data # Direct child bm project add notes /app/data/notes # ✓ # Nested child bm project add work /app/data/projects/work # ✓ # Relative path (resolves to /app/data/relative) bm project add rel /app/data/relative # ✓ # Symlink (resolves under /app/data) ln -s /app/data/real /app/data/link bm project add linked /app/data/link # ✓ ``` ### Invalid Paths (with PROJECT_ROOT=/app/data) ```bash export BASIC_MEMORY_PROJECT_ROOT=/app/data # Path traversal attempt bm project add evil /app/data/../../../etc # ✗ Error: Path must be under /app/data # Absolute path outside root bm project add outside /tmp/data # ✗ Error: Path must be under /app/data # Symlink escaping root ln -s /etc/passwd /app/data/evil bm project add bad /app/data/evil # ✗ Error: Path must be under /app/data # Relative path escaping bm project add sneaky /app/data/../../sneaky # ✗ Error: Path must be under /app/data ``` ## Error Messages ### Path Outside Root ```bash $ bm project add test /tmp/test Error: BASIC_MEMORY_PROJECT_ROOT is set to /app/data. All projects must be created under this directory. Invalid path: /tmp/test ``` ### Escape Attempt Blocked ```bash $ bm project add evil /app/data/../../../etc Error: BASIC_MEMORY_PROJECT_ROOT is set to /app/data. All projects must be created under this directory. Invalid path: /etc ``` ## Migration Guide ### Enabling PROJECT_ROOT on Existing Setup If you have existing projects outside the desired root: 1. **Choose project root location** ```bash export BASIC_MEMORY_PROJECT_ROOT=/app/data ``` 2. **Move existing projects** ```bash # Backup first cp -r ~/old-project /app/data/old-project ``` 3. **Update config.json** ```bash # Edit ~/.basic-memory/config.json { "projects": { "main": "/app/data/basic-memory", "old-project": "/app/data/old-project" } } ``` 4. **Verify paths** ```bash bm project list # All paths should be under /app/data ``` ### Disabling PROJECT_ROOT To remove constraints: ```bash # Unset environment variable unset BASIC_MEMORY_PROJECT_ROOT # Or remove from Docker/config # Now projects can be created anywhere again ``` ## Testing Path Constraints ### Verify Configuration ```bash # Check if PROJECT_ROOT is set env | grep BASIC_MEMORY_PROJECT_ROOT # Try creating project outside root (should fail) bm project add test /tmp/test ``` ### Docker Testing ```bash # Run with constraint docker run \ -e BASIC_MEMORY_PROJECT_ROOT=/app/data \ -v $(pwd)/data:/app/data \ basic-memory:latest \ bm project add notes /app/data/notes # Verify in container docker exec -it container_id env | grep PROJECT_ROOT ``` ## Security Best Practices 1. **Always set in production**: Use PROJECT_ROOT in deployed environments 2. **Minimal permissions**: Set directory permissions to 700 or 750 3. **Audit project creation**: Log all project add/remove operations 4. **Regular validation**: Periodically check project paths haven't escaped 5. **Volume mounts**: Ensure PROJECT_ROOT matches Docker volume mounts ## Troubleshooting ### Projects Not Creating **Problem:** Can't create projects with PROJECT_ROOT set ```bash $ bm project add test /app/data/test Error: Path must be under /app/data ``` **Solution:** Verify PROJECT_ROOT is correct ```bash echo $BASIC_MEMORY_PROJECT_ROOT # Should match expected path ``` ### Paths Resolving Incorrectly **Problem:** Symlinks not working as expected **Solution:** Check symlink target ```bash ls -la /app/data/link # → /app/data/link -> /some/target # Ensure target is under PROJECT_ROOT realpath /app/data/link ``` ### Docker Volume Issues **Problem:** PROJECT_ROOT doesn't match volume mount **Solution:** Align environment and volume ```yaml # docker-compose.yml environment: BASIC_MEMORY_PROJECT_ROOT: /app/data # ← Must match volume mount volumes: - ./data:/app/data # ← Mount point ``` ## Implementation Details ### Path Sanitization Algorithm ```python def sanitize_and_validate_path(path: str, project_root: str) -> str: """Sanitize path and validate against project root.""" # Convert to absolute path base_path = Path(project_root).resolve() target_path = Path(path).resolve() # Get as POSIX string for comparison resolved_path = target_path.as_posix() base_posix = base_path.as_posix() # Verify resolved path is under project_root if not resolved_path.startswith(base_posix): raise ValueError( f"BASIC_MEMORY_PROJECT_ROOT is set to {project_root}. " f"All projects must be created under this directory. " f"Invalid path: {path}" ) return resolved_path ``` ### Config Loading ```python class BasicMemoryConfig(BaseSettings): project_root: Optional[str] = Field( default=None, description="If set, all projects must be created underneath this directory" ) model_config = SettingsConfigDict( env_prefix="BASIC_MEMORY_", # Maps BASIC_MEMORY_PROJECT_ROOT extra="ignore", ) ``` ## See Also - `basic-memory-home.md` - Default project location - `env-var-overrides.md` - Environment variable precedence - Docker deployment guide - Security best practices

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/basicmachines-co/basic-memory'

If you have feedback or need assistance with the MCP directory API, please join our Discord server