Product Deployment

Deploy the MeshOptixIQ Network Discovery engine into your production environment.

System Requirements

Minimum

  • CPU: 2 vCPUs
  • RAM: 4 GB
  • Disk: 20 GB SSD
  • OS: Linux (Ubuntu 22.04 LTS)

Recommended (Enterprise)

  • CPU: 4+ vCPUs
  • RAM: 8-16 GB
  • Disk: 100 GB NVMe
  • Network: 1Gbps+ to mgmt VLAN

Network Prerequisites

The host running the discovery agent must have:

Database Configuration

MeshOptixIQ supports both graph and relational backends. Configure the backend using the GRAPH_BACKEND environment variable.

Neo4j (Default)

Best for deep graph traversal and visualization.

GRAPH_BACKEND=neo4j
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=secret

PostgreSQL

Best for operational stability and recursive CTE optimizations.

GRAPH_BACKEND=postgres
POSTGRES_DSN=postgresql://user:pass@localhost:5432/db

Deployment Options

Option A: Docker Container (Preferred)

Run the discovery engine as a stateless container. It creates the graph and exits, or runs on a schedule.

# 1. Pull the image
docker pull meshoptixiq/discovery-agent:latest

# 2. Run a one-off discovery
docker run -d \
  -e NEO4J_URI=bolt://neo4j.corp.local:7687 \
  -e NEO4J_PASSWORD=my-secret-pw \
  -v /opt/meshoptix/config.yaml:/app/config.yaml \
  meshoptixiq/discovery-agent:latest

Option B: Systemd Service

For persistent deployments on a dedicated VM.

[Unit]
Description=MeshOptixIQ Discovery Agent
After=network.target

[Service]
Type=simple
User=meshoptix
ExecStart=/opt/meshoptix/venv/bin/python -m network_discovery.start_agent
Restart=always

[Install]
WantedBy=multi-user.target

Enterprise Deployment Patterns

Docker Compose Stack (Production)

Complete production stack with Neo4j, API server, and scheduled discovery:

version: '3.8'

services:
  neo4j:
    image: neo4j:5.15
    environment:
      NEO4J_AUTH: neo4j/production-password-here
      NEO4J_dbms_memory_heap_initial__size: 2G
      NEO4J_dbms_memory_heap_max__size: 4G
      NEO4J_dbms_memory_pagecache_size: 2G
    volumes:
      - neo4j-data:/data
      - neo4j-logs:/logs
    ports:
      - "7687:7687"
    restart: unless-stopped

  meshoptixiq-api:
    image: meshoptixiq/discovery-agent:latest
    environment:
      NEO4J_URI: bolt://neo4j:7687
      NEO4J_PASSWORD: production-password-here
      MESHOPTIXIQ_LICENSE_KEY: ${MESHOPTIXIQ_LICENSE_KEY}
      API_KEY: ${API_KEY}
      CORS_ORIGINS: "https://dashboard.example.com"
    ports:
      - "8000:8000"
    depends_on:
      - neo4j
    restart: unless-stopped
    command: ["uvicorn", "network_discovery.api.main:app", "--host", "0.0.0.0"]

  meshoptixiq-discovery:
    image: meshoptixiq/discovery-agent:latest
    environment:
      NEO4J_URI: bolt://neo4j:7687
      NEO4J_PASSWORD: production-password-here
      MESHOPTIXIQ_LICENSE_KEY: ${MESHOPTIXIQ_LICENSE_KEY}
    volumes:
      - ./inventory.yaml:/app/inventory.yaml:ro
    depends_on:
      - neo4j
    restart: unless-stopped
    command: ["python", "-m", "network_discovery.scheduler"]

volumes:
  neo4j-data:
  neo4j-logs:

Kubernetes Deployment

For large-scale enterprise deployments using Kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: meshoptixiq-api
  namespace: network-discovery
spec:
  replicas: 3
  selector:
    matchLabels:
      app: meshoptixiq-api
  template:
    metadata:
      labels:
        app: meshoptixiq-api
    spec:
      containers:
      - name: api
        image: meshoptixiq/discovery-agent:latest
        ports:
        - containerPort: 8000
        env:
        - name: NEO4J_URI
          value: "bolt://neo4j-service:7687"
        - name: NEO4J_PASSWORD
          valueFrom:
            secretKeyRef:
              name: neo4j-credentials
              key: password
        - name: MESHOPTIXIQ_LICENSE_KEY
          valueFrom:
            secretKeyRef:
              name: meshoptixiq-license
              key: license-key
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: meshoptixiq-api
              key: api-key
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "2Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: meshoptixiq-api-service
  namespace: network-discovery
spec:
  selector:
    app: meshoptixiq-api
  ports:
  - port: 80
    targetPort: 8000
  type: LoadBalancer

High Availability Configuration

For mission-critical deployments:

Scheduled Discovery (Cron)

Run discovery on a schedule using cron:

# Edit crontab
crontab -e

# Add daily discovery at 2 AM
0 2 * * * docker run --rm \
  -e NEO4J_URI="bolt://localhost:7687" \
  -e NEO4J_PASSWORD="secret" \
  -e MESHOPTIXIQ_LICENSE_KEY="${MESHOPTIXIQ_LICENSE_KEY}" \
  -v /opt/meshoptix/inventory.yaml:/app/inventory.yaml \
  meshoptixiq/discovery-agent:latest \
  meshq ingest --source /app/inventory.yaml \
  >> /var/log/meshoptixiq-discovery.log 2>&1

Security Considerations

Network Access Controls

  • Read-Only SSH Access: Service account should have privilege level 15 (Cisco) but restricted to show commands via TACACS+/RADIUS
  • Firewall Rules: Allow only SSH (22) from MeshOptixIQ host to network devices
  • Management VLAN: Deploy MeshOptixIQ in dedicated management VLAN with restricted access

Secrets Management

Do NOT store credentials in plaintext. Use one of these approaches:

  • Environment Variables: Reference from orchestrator secrets
  • AWS Secrets Manager: Use IAM role-based retrieval
  • HashiCorp Vault: Dynamic credential generation
  • Kubernetes Secrets: Encrypted at rest with KMS
  • Enterprise Container: Built-in secrets resolver pulls from Vault, AWS, Azure, or GCP at startup — no credentials in the Compose file

Enterprise Container

The enterprise image (meshoptixiq/discovery-agent:enterprise-latest) adds a startup secrets resolver, OIDC authentication, SIEM audit logging, and APM observability. Credentials are fetched at boot and never touch disk.

docker run -d \
  -e SECRETS_PROVIDER=vault \
  -e VAULT_ADDR=https://vault.corp.local:8200 \
  -e VAULT_AUTH_METHOD=approle \
  -e VAULT_ROLE_ID=${VAULT_ROLE_ID} \
  -e VAULT_SECRET_ID=${VAULT_SECRET_ID} \
  -e VAULT_SECRET_PATH=secret/data/meshoptixiq \
  -e AUTH_MODE=both \
  -e OIDC_DISCOVERY_URL=https://company.okta.com/.well-known/openid-configuration \
  -e OIDC_CLIENT_ID=meshoptixiq-api-client \
  -e AUDIT_LOG_ENABLED=true \
  -e SPLUNK_HEC_URL=https://splunk.corp.local:8088/services/collector/event \
  -e SPLUNK_HEC_TOKEN=${SPLUNK_HEC_TOKEN} \
  -p 8000:8000 \
  meshoptixiq/discovery-agent:enterprise-latest

See the User Guide — Chapter 13 for full enterprise feature documentation.

API Security

  • API Key Authentication: Set API_KEY environment variable
  • CORS Configuration: Restrict CORS_ORIGINS to trusted domains only
  • TLS Termination: Use reverse proxy (Nginx, Traefik) for HTTPS
  • Rate Limiting: Implement at load balancer or API gateway level

Monitoring & Alerting

See the Monitoring & Operations Guide for comprehensive monitoring setup including:

Backup & Disaster Recovery

Neo4j Backup

# Manual backup
neo4j-admin dump --database=neo4j --to=/backups/neo4j-backup.dump

# Automated daily backup script
#!/bin/bash
BACKUP_DIR="/backups/neo4j"
DATE=$(date +%Y%m%d)
docker exec neo4j neo4j-admin dump --database=neo4j \
  --to=/tmp/neo4j-${DATE}.dump
docker cp neo4j:/tmp/neo4j-${DATE}.dump ${BACKUP_DIR}/
# Upload to S3
aws s3 cp ${BACKUP_DIR}/neo4j-${DATE}.dump s3://backups/meshoptixiq/

PostgreSQL Backup

# Manual backup
pg_dump -h localhost -U postgres network_discovery > backup.sql

# Automated with retention
pg_dump network_discovery | gzip > /backups/meshoptix-$(date +%Y%m%d).sql.gz
find /backups -name "meshoptix-*.sql.gz" -mtime +30 -delete