Minimum
- CPU: 2 vCPUs
- RAM: 4 GB
- Disk: 20 GB SSD
- OS: Linux (Ubuntu 22.04 LTS)
Deploy the MeshOptixIQ Network Discovery engine into your production environment.
The host running the discovery agent must have:
MeshOptixIQ supports both graph and relational backends. Configure the backend using the
GRAPH_BACKEND environment variable.
Best for deep graph traversal and visualization.
GRAPH_BACKEND=neo4j
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=secret
Best for operational stability and recursive CTE optimizations.
GRAPH_BACKEND=postgres
POSTGRES_DSN=postgresql://user:pass@localhost:5432/db
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
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
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:
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
For mission-critical deployments:
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
privilege level 15 (Cisco) but restricted to show commands via TACACS+/RADIUSDo NOT store credentials in plaintext. Use one of these approaches:
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_KEY environment variableCORS_ORIGINS to trusted domains onlySee the Monitoring & Operations Guide for comprehensive monitoring setup including:
# 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/
# 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