← Back to list

SOC Lab Deployment Documentation: TheHive 5.2 + Cortex + MISP + Dependencies

This documentation describes the complete deployment of a Security Operations Center (SOC) lab environment using Docker Compose. The stack…

Md. Mahim Hossain · 2026-05-11 10:53 · 4 claps · 5.2 min read
#soc #docker #the-hive #cortex #misp
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud 🔒 · Cybersecurity

SOC Lab Deployment Documentation: TheHive 5.2 + Cortex + MISP + Dependencies

This documentation describes the complete deployment of a Security Operations Center (SOC) lab environment using Docker Compose. The stack includes:

Step-by-Step Deployment Process

Step 1: Create a project directory and necessary subdirectories/files:

mkdir -p ~/soc-lab/{cortex/logs,server-configs,logs,files,ssl}
cd ~/soc-lab

Place your docker-compose.yml in ~/soc-lab/.

~/soc-lab/
├── docker-compose.yml          # Main compose file
├── thehive.conf                # TheHive configuration (MISP integration)
├── cortex/
│   ├── logs/                   # Cortex log directory
│   └── application.conf        # Cortex configuration
├── server-configs/             # MISP configuration files
├── logs/                       # MISP logs
├── files/                      # MISP file storage
└── ssl/                        # SSL certificates

Step 2: Add User to Docker Group (Optional but Recommended)

sudo usermod -aG docker $USER
newgrp docker

Step 3: Create TheHive Configuration File

TheHive requires an application.conf file. Create ~/soc-lab/thehive.conf

nano ~/soc-lab/thehive.conf

Paste this content:

# ============================================
# TheHive 5.2 Configuration File
# ============================================

# MISP Module Enable
play.modules.enabled += org.thp.thehive.connector.misp.MispModule

# MISP Server Configuration
misp {
  interval: 1 hour
  servers: [
    {
      name = "MISP"
      url = "https://misp.local"           # MISP container name (Docker DNS)
      auth {
        type = key
        key = "Yl1M7biMolOcb1qk7HCgNih3OjpUyUJqesDXtazB"
      }
      tags = ["tag1", "tag2", "tag3"]
      caseTemplate = "misp"
      includedTheHiveOrganisations = ["Morgan Maxwell"]

      # SSL/TLS Settings (for self-signed certs)
      wsConfig.ssl.loose.acceptAnyCertificate = true
      wsConfig.ssl.loose.allowWeakCiphers = true
    }
  ]
}

Step 4: Create Cortex Configuration

Create ~/soc-lab/cortex/application.conf

nano ~/soc-lab/cortex/application.conf

Paste this content:

# ============================================
# Cortex Configuration File
# ============================================

# Application Secret (generate a strong one for production)
play.http.secret.key="changeme-please-generate-a-32-char-secret-key-here"

# Search Configuration (Elasticsearch)
search {
  index = cortex
  uri = "http://elasticsearch:9200"
}

# Analyzer Paths
analyzer {
  path = ["/opt/cortex/analyzers"]
}

# Job Directories
job {
  directory = "/tmp/cortex-jobs"
  dockerDirectory = "/tmp/cortex-jobs"
}

# Authentication
auth {
  method = [
    {
      name = local
      provider = local
    }
  ]
}

# Organization Settings
organization {
  name = "SOC-Lab"
}

Step 5: Create the Docker Compose File

nano ~/soc-lab/docker-compose.yml

Paste this COMPLETE configuration:

# ============================================
# SOC Lab Stack - Docker Compose
# TheHive 5.2 + Cortex + MISP + Dependencies
# ============================================

services:
  # ------------------------------------------
  # 1. CASSANDRA (TheHive Database)
  # ------------------------------------------
  cassandra:
    image: cassandra:4
    container_name: soc-cassandra
    restart: unless-stopped
    ports:
      - "9042:9042"
    environment:
      - CASSANDRA_CLUSTER_NAME=TheHive
      - CASSANDRA_NUM_TOKENS=256
      - CASSANDRA_START_RPC=true
    volumes:
      - cassandradata:/var/lib/cassandra
    networks:
      - SOC_NET
    healthcheck:
      test: ["CMD", "cqlsh", "-e", "describe keyspaces"]
      interval: 30s
      timeout: 10s
      retries: 5

  # ------------------------------------------
  # 2. ELASTICSEARCH (Search & Indexing)
  # ------------------------------------------
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.9
    container_name: soc-elasticsearch
    restart: unless-stopped
    mem_limit: 512m
    ports:
      - "9200:9200"
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - cluster.name=hive
      - http.host=0.0.0.0
      - "ES_JAVA_OPTS=-Xms256m -Xmx256m"
      - bootstrap.memory_lock=true
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - elasticsearchdata:/usr/share/elasticsearch/data
    networks:
      - SOC_NET
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9200/_cluster/health"]
      interval: 30s
      timeout: 10s
      retries: 5

  # ------------------------------------------
  # 3. MINIO (S3-Compatible Object Storage)
  # ------------------------------------------
  minio:
    image: quay.io/minio/minio:latest
    container_name: soc-minio
    restart: unless-stopped
    command: ["server", "/data", "--console-address", ":9002"]
    environment:
      - MINIO_ROOT_USER=minioadmin
      - MINIO_ROOT_PASSWORD=minioadmin
    ports:
      - "9002:9002"
    volumes:
      - miniodata:/data
    networks:
      - SOC_NET
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:9002/minio/health/live"]
      interval: 30s
      timeout: 10s
      retries: 3

  # ------------------------------------------
  # 4. CORTEX (Observable Analysis Engine)
  # ------------------------------------------
  cortex.local:
    image: thehiveproject/cortex:latest
    container_name: soc-cortex
    restart: unless-stopped
    environment:
      - job_directory=/tmp/cortex-jobs
      - docker_job_directory=/tmp/cortex-jobs
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /tmp/cortex-jobs:/tmp/cortex-jobs
      - ./cortex/logs:/var/log/cortex
      - ./cortex/application.conf:/cortex/application.conf:ro
    depends_on:
      elasticsearch:
        condition: service_healthy
    ports:
      - "9001:9001"
    networks:
      - SOC_NET

  # ------------------------------------------
  # 5. THEHIVE (Incident Response Platform)
  # ------------------------------------------
  thehive:
    image: strangebee/thehive:5.2
    container_name: soc-thehive
    restart: unless-stopped
    depends_on:
      cassandra:
        condition: service_healthy
      elasticsearch:
        condition: service_healthy
      minio:
        condition: service_healthy
      cortex.local:
        condition: service_started
    mem_limit: 1500m
    ports:
      - "9000:9000"
    environment:
      - JVM_OPTS="-Xms1024M -Xmx1024M"
    command:
      - --secret
      - "lab123456789"
      - "--cql-hostnames"
      - "cassandra"
      - "--index-backend"
      - "elasticsearch"
      - "--es-hostnames"
      - "elasticsearch"
      - "--s3-endpoint"
      - "http://minio:9002"
      - "--s3-access-key"
      - "minioadmin"
      - "--s3-secret-key"
      - "minioadmin"
      - "--s3-use-path-access-style"
    volumes:
      - ./thehive.conf:/etc/thehive/application.conf:ro    # FIXED: Bind mount for config
      - thehivedata:/etc/thehive/data                      # Data volume
    networks:
      - SOC_NET

  # ------------------------------------------
  # 6. MISP MYSQL (Database for MISP)
  # ------------------------------------------
  misp_mysql:
    image: mysql/mysql-server:5.7
    container_name: soc-misp-mysql
    restart: unless-stopped
    volumes:
      - mispsqldata:/var/lib/mysql
    environment:
      - MYSQL_DATABASE=mispdb
      - MYSQL_USER=mispuser
      - MYSQL_PASSWORD=misppass
      - MYSQL_ROOT_PASSWORD=mispass
    networks:
      - SOC_NET
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 30s
      timeout: 10s
      retries: 5

  # ------------------------------------------
  # 7. REDIS (Cache for MISP)
  # ------------------------------------------
  redis:
    image: redis:latest
    container_name: soc-redis
    restart: unless-stopped
    networks:
      - SOC_NET
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 3s
      retries: 5

  # ------------------------------------------
  # 8. MISP (Threat Intelligence Platform)
  # ------------------------------------------
  misp.local:
    image: coolacid/misp-docker:core-latest
    container_name: soc-misp
    restart: unless-stopped
    depends_on:
      misp_mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "./server-configs/:/var/www/MISP/app/Config/"
      - "./logs/:/var/www/MISP/app/tmp/logs/"
      - "./files/:/var/www/MISP/app/files"
      - "./ssl/:/etc/nginx/certs"
    environment:
      - MYSQL_HOST=misp_mysql
      - MYSQL_DATABASE=mispdb
      - MYSQL_USER=mispuser
      - MYSQL_PASSWORD=misppass
      - MYSQL_ROOT_PASSWORD=mispass
      - MISP_ADMIN_EMAIL=mispadmin@lab.local
      - MISP_ADMIN_PASSPHRASE=mispadminpass
      - MISP_BASEURL=https://192.168.0.107        # ← REPLACE WITH YOUR IP
      - TIMEZONE=Asia/Dhaka
      - INIT=true
      - CRON_USER_ID=1
      - REDIS_FQDN=redis
      - HOSTNAME=https://192.168.0.107            # ← REPLACE WITH YOUR IP
    networks:
      - SOC_NET

  # ------------------------------------------
  # 9. MISP MODULES (Enrichment Services)
  # ------------------------------------------
  misp-modules:
    image: coolacid/misp-docker:modules-latest
    container_name: soc-misp-modules
    restart: unless-stopped
    environment:
      - "REDIS_BACKEND=redis"
    depends_on:
      - redis
      - misp_mysql
    networks:
      - SOC_NET

# ============================================
# VOLUMES
# ============================================
volumes:
  miniodata:
  cassandradata:
  elasticsearchdata:
  thehivedata:
  mispsqldata:

# ============================================
# NETWORKS
# ============================================
networks:
  SOC_NET:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

Step 6: Fix MISP Configuration Issues

Your MISP container has placeholder <IP> values. Replace these with your actual server IP or domain:

# Get your server IP
ip addr show | grep "inet " | head -1
# Example: If your IP is 192.168.1.100, use:
# MISP_BASEURL=https://192.168.1.100
# HOSTNAME=https://192.168.1.100
environment:
  - MISP_BASEURL=https://192.168.1.100    # ← Replace with your IP
  - HOSTNAME=https://192.168.1.100        # ← Replace with your IP

Step 7: Deploy the Stack

cd ~/soc-lab

# Pull images first
docker-compose pull

# Start services (detached mode)
docker-compose up -d

# Check service status
docker-compose ps

Step 8: Access & Initial Setup

| Service           | URL                          | Purpose             |
| ----------------- | ---------------------------- | ------------------- |
| **TheHive**       | `http://YOUR_SERVER_IP:9000` | Incident Response   |
| **Cortex**        | `http://YOUR_SERVER_IP:9001` | Observable Analysis |
| **MISP**          | `https://YOUR_SERVER_IP`     | Threat Intelligence |
| **MinIO Console** | `http://YOUR_SERVER_IP:9002` | File Storage        |
| **Elasticsearch** | `http://YOUR_SERVER_IP:9200` | Search Index        |

Step 9: Enable Firewall

sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow necessary ports
sudo ufw allow 22/tcp      # SSH
sudo ufw allow 80/tcp      # MISP HTTP
sudo ufw allow 443/tcp     # MISP HTTPS
sudo ufw allow 9000/tcp    # TheHive
sudo ufw allow 9001/tcp    # Cortex
sudo ufw allow 9002/tcp    # MinIO Console

sudo ufw enable

Step 10: All Services — User & Password Table

# Generate strong passwords
openssl rand -base64 32
| # | Service     | URL                         | Username / Email      | Password              | Notes                                           |
| - | ----------- | --------------------------- | --------------------- | --------------------- | ----------------------------------------------- |
| 1 | **TheHive** | `http://192.168.0.107:9000` | `admin@thehive.local` | `secret`              | Change on first login                           |
| 2 | **Cortex**  | `http://192.168.0.107:9001` | Create on first setup | Create on first setup | Click "Update Database", then create superadmin |
| 3 | **MISP**    | `https://192.168.0.107`     | `mispadmin@lab.local` | `mispadmin            |     

Quick Commands Reference

# Start all services
docker-compose up -d
# Stop all services
docker-compose down
# Stop and remove volumes (WARNING: deletes data)
docker-compose down -v
# View logs
docker-compose logs -f [service_name]
# Restart specific service
docker-compose restart thehive
# Scale check (resource monitoring)
docker stats

Appendix: Network Diagram

┌─────────────────────────────────────────┐
│           Docker Network: SOC_NET       │
│         (Subnet: 172.20.0.0/16)         │
│                                         │
│  ┌──────────┐    ┌──────────────┐       │
│  │ TheHive  │◄──►│  Cassandra   │       │
│  │  :9000   │    │    :9042     │       │
│  └────┬─────┘    └──────────────┘       │
│       │                                 │
│       │         ┌──────────────┐        │
│       │         │Elasticsearch │        │
│       │         │    :9200     │        │
│       │         └──────────────┘        │
│       │                                 │
│       │         ┌──────────────┐        │
│       │         │    MinIO     │        │
│       │         │    :9002     │        │
│       │         └──────────────┘        │
│       │                                 │
│       └────────►┌──────────────┐        │
│                 │   Cortex     │        │
│                 │    :9001     │        │
│                 └──────────────┘        │
│                                         │
│  ┌──────────┐    ┌──────────────┐       │
│  │   MISP   │◄──►│  MISP MySQL  │       │
│  │  :80/443 │    │    :3306     │       │
│  └────┬─────┘    └──────────────┘       │
│       │                                 │
│       └────────►┌──────────────┐        │
│                 │    Redis     │        │
│                 │    :6379     │        │
│                 └──────────────┘        │
│                                         │
└─────────────────────────────────────────┘

메타데이터
post_id
c7f494d780ca
slug
soc-lab-deployment-documentation-thehive-5-2-cortex-misp-dependencies-c7f494d780ca
url
https://medium.com/@mahimsec/soc-lab-deployment-documentation-thehive-5-2-cortex-misp-dependencies-c7f494d780ca
canonical_url
https://medium.com/@mahimsec/soc-lab-deployment-documentation-thehive-5-2-cortex-misp-dependencies-c7f494d780ca
author_url
https://medium.com/@mahimsec
status
ok
fetched_at
2026-06-20 20:29:01