Skip to main content

Local Development Environment Setup

This guide walks you through configuring a complete CitadelMesh development environment optimized for productivity.

Development Tools Installation

.NET Development

Install .NET 8.0 SDK

macOS (Homebrew):

brew install dotnet@8

Windows (winget):

winget install Microsoft.DotNet.SDK.8

Linux (Ubuntu/Debian):

wget https://dot.net/v1/dotnet-install.sh
chmod +x dotnet-install.sh
./dotnet-install.sh --version 8.0

Verify:

dotnet --version
# Output: 8.0.x

Install Aspire Workload

Aspire is CitadelMesh's orchestration engine:

dotnet workload update
dotnet workload install aspire

Verify:

dotnet workload list
# Should show: aspire 8.x.x

Python Development

Install Python 3.12+

macOS (Homebrew):

brew install python@3.12

Windows (winget):

winget install Python.Python.3.12

Linux (pyenv recommended):

curl https://pyenv.run | bash
pyenv install 3.12
pyenv global 3.12

Create Virtual Environment

cd /path/to/CitadelMesh/src/agents

# Create virtual environment
python3.12 -m venv .venv

# Activate
source .venv/bin/activate # macOS/Linux
.venv\Scripts\activate # Windows

# Install dependencies
pip install --upgrade pip
pip install -r requirements.txt

Expected packages:

  • langgraph>=0.0.32 - Agent state machines
  • langchain>=0.1.0 - LLM orchestration
  • opentelemetry-api>=1.15.0 - Observability
  • structlog>=22.1.0 - Structured logging
  • nats-py>=2.6.0 - Event bus client
  • protobuf>=6.32.0 - Protocol buffers
  • grpcio>=1.75.0 - gRPC communication

Node.js Development (MCP Adapters)

Install Node.js 20+

macOS (Homebrew):

brew install node@20

Windows (winget):

winget install OpenJS.NodeJS.LTS

Linux (nvm recommended):

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 20
nvm use 20

Install MCP Dependencies

cd /path/to/CitadelMesh/mcp-servers/ecostruxure-ebo

npm install

Expected packages:

  • @modelcontextprotocol/sdk - MCP protocol implementation
  • zod - Runtime type validation
  • typescript - Type safety

Docker Desktop

Install Docker

macOS:

brew install --cask docker
# Launch Docker Desktop from Applications

Windows: Download from docker.com/products/docker-desktop

Linux:

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Log out and back in

Verify:

docker --version
docker compose version

Configure Resources (Recommended):

  • CPUs: 4+
  • Memory: 8GB+
  • Disk: 50GB+

Configuration Files

1. Environment Variables

Create .env in the project root:

cd /path/to/CitadelMesh

.env file:

# Infrastructure
ASPIRE_DASHBOARD_PORT=5000
NATS_URL=nats://localhost:4222
REDIS_URL=redis://localhost:6379
POSTGRES_URL=postgresql://postgres:citadel123@localhost:5432/citadel-db

# Security & Identity
OPA_URL=http://localhost:8181
SPIRE_SERVER_ADDRESS=localhost:8081
SPIRE_AGENT_SOCKET=/run/spire/sockets/agent.sock

# Observability
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
JAEGER_UI_URL=http://localhost:16686

# Development
CITADEL_ENV=development
LOG_LEVEL=DEBUG
ENABLE_MOCK_MODE=true

# Agent Configuration
AGENT_RUNTIME=python
ENABLE_SAFETY_CHECKS=true
ENABLE_TELEMETRY=true

# MCP Servers
MCP_ECOSTRUXURE_URL=http://localhost:3001
MCP_SECURITY_EXPERT_URL=http://localhost:3002

2. .NET Configuration

src/CitadelMesh.AppHost/appsettings.Development.json:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Aspire": "Debug"
}
},
"AllowedHosts": "*",
"Dashboard": {
"Port": 5000,
"EnableAuthentication": false
}
}

src/microservices/CitadelMesh.Safety/appsettings.Development.json:

{
"Logging": {
"LogLevel": {
"Default": "Information",
"CitadelMesh": "Debug"
}
},
"OPA": {
"BaseUrl": "http://localhost:8181",
"PolicyPath": "v1/data/citadel",
"Timeout": 5000
}
}

3. Python Configuration

src/agents/.env:

# Agent Runtime
NATS_URL=nats://localhost:4222
OPA_URL=http://localhost:8181
SPIFFE_ID=spiffe://citadel.local/agent/security

# Logging
LOG_LEVEL=INFO
LOG_FORMAT=json

# Telemetry
OTEL_SERVICE_NAME=citadel-agent
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317

4. Docker Compose Override

For local development, create docker-compose.override.yml:

version: '3.9'

services:
opa:
volumes:
- ./policies:/policies:rw # Read-write for hot reload
environment:
- OPA_LOG_LEVEL=debug

nats:
ports:
- "8222:8222" # Monitoring UI

IDE Setup

Install Extensions

# Install via command palette (Cmd/Ctrl + Shift + P)
code --install-extension ms-dotnettools.csdevkit
code --install-extension ms-python.python
code --install-extension ms-azuretools.vscode-docker
code --install-extension redhat.vscode-yaml
code --install-extension tsandall.opa

Workspace Settings

Create .vscode/settings.json:

{
"dotnet.defaultSolution": "CitadelMesh.sln",
"python.defaultInterpreterPath": "${workspaceFolder}/src/agents/.venv/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"files.associations": {
"*.rego": "rego"
},
"opa.path": "/usr/local/bin/opa",
"opa.checkOnSave": true
}

Launch Configurations

Create .vscode/launch.json:

{
"version": "0.2.0",
"configurations": [
{
"name": "Aspire AppHost",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/src/CitadelMesh.AppHost/bin/Debug/net8.0/CitadelMesh.AppHost.dll",
"args": [],
"cwd": "${workspaceFolder}/src/CitadelMesh.AppHost",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": "Python: Security Agent",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/src/agents/security/demo_security_agent.py",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}/src"
}
},
{
"name": "Node: MCP Server",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/mcp-servers/ecostruxure-ebo/dist/index.js",
"preLaunchTask": "npm: build - mcp-servers/ecostruxure-ebo",
"outFiles": ["${workspaceFolder}/mcp-servers/ecostruxure-ebo/dist/**/*.js"]
}
]
}

Visual Studio 2022 (Windows/Mac)

  1. Open CitadelMesh.sln

  2. Right-click solution → Manage NuGet Packages

  3. Install Aspire packages:

    • Aspire.Hosting.AppHost
    • Aspire.Hosting.Redis
    • Aspire.Hosting.PostgreSQL
  4. Set CitadelMesh.AppHost as startup project

  5. Press F5 to run

Development Workflow

1. Start Infrastructure

# Option A: Using Aspire (Recommended)
cd src/CitadelMesh.AppHost
dotnet run

# Option B: Using Docker Compose
docker compose -f docker-compose-spire.yml up -d

2. Develop Agents

cd src/agents
source .venv/bin/activate

# Run agent in dev mode
python security/security_agent.py

3. Develop MCP Adapters

cd mcp-servers/ecostruxure-ebo

# Watch mode (auto-rebuild on change)
npm run dev

# In another terminal, test the server
node dist/index.js

4. Edit OPA Policies

# Policies are hot-reloaded automatically
vim policies/security.rego

# Validate policy
opa test policies/security.rego policies/security_test.rego

5. View Logs and Traces

Troubleshooting

Issue: Port Conflicts

Error: Failed to bind to address https://localhost:5000

Solution:

# Find process using port 5000
lsof -ti:5000 | xargs kill -9 # macOS/Linux
netstat -ano | findstr :5000 # Windows

# Or change port in appsettings.Development.json

Issue: Python Import Errors

Error: ModuleNotFoundError: No module named 'citadel'

Solution:

# Ensure PYTHONPATH is set
export PYTHONPATH=/path/to/CitadelMesh/src
# Or add to .env file

Issue: Docker Containers Not Starting

Error: Cannot connect to Docker daemon

Solution:

# Start Docker Desktop
open -a Docker # macOS
# Wait for Docker to fully start (check system tray icon)

# Verify
docker ps

Issue: OPA Policies Not Loading

Error: Policy bundle not found

Solution:

# Check OPA logs
docker logs citadel-opa

# Verify policy syntax
opa check policies/*.rego

# Manually load bundle
curl -X PUT http://localhost:8181/v1/policies/citadel/security \
-H 'Content-Type: text/plain' \
-d @policies/security.rego

Issue: SPIRE Identity Issues

Error: Failed to attest workload

Solution:

# Restart SPIRE agent
docker restart citadel-spire-agent

# Register workload manually
docker exec citadel-spire-server \
/opt/spire/bin/spire-server entry create \
-spiffeID spiffe://citadel.local/agent/security \
-parentID spiffe://citadel.local/agent \
-selector unix:uid:1000

Issue: .NET Build Failures

Error: The workload 'aspire' is not installed

Solution:

dotnet workload update
dotnet workload install aspire
dotnet restore
dotnet build

Development Best Practices

1. Hot Reload Workflow

  • .NET: Hot reload enabled by default in Aspire
  • Python: Use watchdog for auto-restart:
    pip install watchdog[watchmedo]
    watchmedo auto-restart --pattern="*.py" -- python agent.py
  • OPA: Policies auto-reload when files change

2. Testing Locally

# Run unit tests
dotnet test # .NET tests
pytest src/agents/tests # Python tests
npm test # MCP adapter tests

# Integration tests
./scripts/integration-test.sh

3. Clean Rebuild

# Clean all build artifacts
dotnet clean
rm -rf src/agents/.venv
rm -rf mcp-servers/*/node_modules

# Full rebuild
dotnet restore && dotnet build
pip install -r src/agents/requirements.txt
cd mcp-servers/ecostruxure-ebo && npm install

Next Steps

Environment Checklist

Before proceeding, ensure:

  • .NET 8.0 SDK installed and verified
  • Python 3.12+ with virtual environment configured
  • Node.js 20+ for MCP development
  • Docker Desktop running with 8GB+ memory
  • All .env files created
  • IDE configured with extensions
  • Aspire dashboard accessible at https://localhost:5000
  • OPA policies loading successfully

Environment ready! Continue to Aspire Dashboard Guide.