Most organizations think a Security Operations Center (SOC) requires a million-dollar budget and a dedicated team of 20 analysts. The reality in 2026 is different: with open source tools, a modest server, and the right architecture, you can build a fully functional SOC that detects real threats, correlates logs, generates alerts, and supports incident response. This guide takes you from zero — bare hardware or a cloud VM — to a production-capable SOC stack.
What a SOC Actually Does
A SOC has three core functions: collect (aggregate logs and telemetry from all systems), detect (identify suspicious patterns using rules and analytics), and respond (investigate alerts and contain incidents). Your open source stack needs to cover all three. Here is what we will build:
- Wazuh — SIEM + host-based IDS + vulnerability detection (replaces Splunk/ArcSight)
- Suricata — Network IDS/IPS (replaces Cisco Firepower)
- TheHive + Cortex — Incident response case management + automated enrichment
- MISP — Threat intelligence platform for sharing and consuming IOCs
- Velociraptor — Endpoint forensics and threat hunting
- Grafana + Elasticsearch — Dashboards and data visualization
Hardware and Infrastructure Requirements
For a small organization (up to 100 endpoints), you can run the entire stack on:
- 1 x SOC Server: 16 CPU cores, 64GB RAM, 2TB SSD (Elasticsearch is RAM-hungry)
- 1 x Network TAP or SPAN port on your core switch for Suricata
- Wazuh agents installed on all monitored endpoints (Linux, Windows, macOS)
- Ubuntu 22.04 LTS for all servers (best community support for these tools)
Step 1: Deploy Wazuh (SIEM Core)
Wazuh is the foundation of your open source SOC. It collects logs from agents on every endpoint, runs detection rules, checks file integrity, and integrates with Elasticsearch for storage and Kibana for visualization.
# Install Wazuh all-in-one (manager + indexer + dashboard) on Ubuntu
curl -sO https://packages.wazuh.com/4.7/wazuh-install.sh
curl -sO https://packages.wazuh.com/4.7/config.yml
# Edit config.yml — set your node IPs/hostnames
nano config.yml
# Run installer (takes 10-15 minutes)
sudo bash wazuh-install.sh -a
# Save the admin credentials printed at the end!
# Access dashboard at: https://your-server-ip:443
# Install Wazuh agent on Linux endpoints
curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | gpg --no-default-keyring --keyring gnupg-ring:/usr/share/keyrings/wazuh.gpg --import
echo "deb [signed-by=/usr/share/keyrings/wazuh.gpg] https://packages.wazuh.com/4.x/apt/ stable main" | sudo tee /etc/apt/sources.list.d/wazuh.list
sudo apt-get update && sudo apt-get install wazuh-agent
# Configure agent to point to manager
sudo sed -i 's/MANAGER_IP/10.0.0.10/' /var/ossec/etc/ossec.conf
sudo systemctl start wazuh-agent && sudo systemctl enable wazuh-agent
# Install Wazuh agent on Windows (run as Administrator in PowerShell)
Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.7.0-1.msi -OutFile wazuh-agent.msi
Start-Process msiexec.exe -ArgumentList '/i wazuh-agent.msi WAZUH_MANAGER=10.0.0.10 /q' -Wait
NET START WazuhSvc
Configure Key Wazuh Detection Rules
# Custom rules go in /var/ossec/etc/rules/local_rules.xml
# Example: Alert on failed sudo attempts
<group name="linux,sudo,">
<rule id="100001" level="10">
<if_sid>5401</if_sid>
<match>incorrect password attempt</match>
<description>Failed sudo attempt - possible privilege escalation</description>
<mitre>
<id>T1548.003</id>
</mitre>
</rule>
</group>
Step 2: Deploy Suricata (Network IDS)
Suricata monitors your network traffic in real time, matching packets against thousands of detection signatures. It runs on the server connected to your SPAN port or network TAP.
# Install Suricata on Ubuntu
sudo add-apt-repository ppa:oisf/suricata-stable
sudo apt-get update && sudo apt-get install suricata
# Configure network interface to monitor
sudo nano /etc/suricata/suricata.yaml
# Change: af-packet: interface: eth0 (your SPAN interface)
# Download latest Emerging Threats rules (free)
sudo suricata-update
# Start Suricata
sudo systemctl start suricata && sudo systemctl enable suricata
# Watch alerts in real time
sudo tail -f /var/log/suricata/fast.log
# Test Suricata is working (this triggers a test alert)
curl http://testmynids.org/uid/index.html
# Check the alert appeared:
sudo tail -5 /var/log/suricata/fast.log
# Should show: [**] [1:2100498:7] GPL ATTACK_RESPONSE id check returned root [**]
# Send Suricata logs to Wazuh for correlation
# Add to /var/ossec/etc/ossec.conf:
# <localfile>
# <log_format>json</log_format>
# <location>/var/log/suricata/eve.json</location>
# </localfile>
Step 3: Deploy TheHive (Incident Response)
TheHive is your incident case management platform. When Wazuh fires an alert, an automated workflow creates a case in TheHive, enriches the indicators with Cortex, and assigns it to an analyst.
# Install TheHive 5 using Docker Compose (easiest method)
sudo apt-get install docker.io docker-compose
mkdir thehive && cd thehive
# Download official docker-compose.yml from TheHive documentation
wget https://raw.githubusercontent.com/StrangeBee/TheHive/main/docker/thehive5/docker-compose.yml
# Start the stack
docker-compose up -d
# Access at: http://your-server:9000
# Default credentials: admin@thehive.local / secret
# Wazuh → TheHive integration
# Install wazuh-thehive connector script
pip install thehive4py
# Create integration script /var/ossec/integrations/custom-thehive
cat > /var/ossec/integrations/custom-thehive <<'EOF'
#!/usr/bin/env python3
import sys, json, requests
alert_file = open(sys.argv[1])
alert = json.load(alert_file)
thehive_url = "http://10.0.0.10:9000"
api_key = "YOUR_THEHIVE_API_KEY"
case_data = {
"title": f"Wazuh Alert: {alert['rule']['description']}",
"description": f"Rule: {alert['rule']['id']}
Level: {alert['rule']['level']}",
"severity": 2,
"tags": ["wazuh", f"rule-{alert['rule']['id']}"]
}
requests.post(f"{thehive_url}/api/case", json=case_data,
headers={"Authorization": f"Bearer {api_key}"})
EOF
chmod +x /var/ossec/integrations/custom-thehive
Step 4: Set Up MISP for Threat Intelligence
# Install MISP using official installer
sudo apt-get install -y git
git clone https://github.com/MISP/MISP.git /var/www/MISP
# Run automated installer
cd /var/www/MISP
sudo bash INSTALL/INSTALL.sh -c # core install
# After install, configure automatic feed sync
# Log in to MISP → Administration → Feeds
# Enable: CIRCL OSINT Feed, Abuse.ch URLhaus, etc.
# Scheduled sync (add to crontab):
# */30 * * * * /var/www/MISP/app/Console/cake Server fetchFeed ALL
Step 5: Deploy Velociraptor for Threat Hunting
Velociraptor lets you query every endpoint in your environment simultaneously using a SQL-like language called VQL. Need to find which machines have a specific file, process, or registry key? Ask Velociraptor.
# Download Velociraptor server binary
wget https://github.com/Velocidex/velociraptor/releases/latest/download/velociraptor-linux-amd64
chmod +x velociraptor-linux-amd64
# Generate server config
./velociraptor-linux-amd64 config generate -i
# Start server
./velociraptor-linux-amd64 --config server.config.yaml frontend
# Access GUI at: https://your-server:8889
# Example VQL hunt: find all running processes that have no parent (potential malware)
SELECT Pid, Name, CommandLine, CreateTime
FROM pslist()
WHERE Ppid = 0 AND Name != "System"
# Hunt: find files created in last 24h in temp directories (across ALL endpoints)
SELECT FullPath, Mtime, Size
FROM glob(globs=["/tmp/**", "/var/tmp/**"])
WHERE Mtime > now() - 86400
# Hunt: find persistence in Linux cron jobs
SELECT FullPath, Content
FROM glob(globs=["/etc/cron*", "/var/spool/cron/**"])
WHERE Content =~ "base64|curl|wget|nc "
Step 6: Dashboards with Grafana
# Install Grafana
sudo apt-get install -y apt-transport-https software-properties-common
wget -q -O - https://packages.grafana.com/gpg.key | sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" | sudo tee /etc/apt/sources.list.d/grafana.list
sudo apt-get update && sudo apt-get install grafana
# Start Grafana
sudo systemctl start grafana-server && sudo systemctl enable grafana-server
# Access at: http://your-server:3000 (admin/admin)
# Add Elasticsearch as data source → point to Wazuh's indexer
# Import Wazuh community dashboards from grafana.com (search "Wazuh")
SOC Playbooks: Responding to Common Alerts
Playbook: Brute Force Attack
- Wazuh fires alert (rule 5712 — Multiple failed SSH logins)
- TheHive case auto-created: “Brute Force from IP X.X.X.X”
- Cortex runs: GeoIP lookup, VirusTotal IP check, Shodan lookup on attacker IP
- If IP is known malicious: block at firewall, add to MISP blacklist
- Check if any successful login followed the failures:
grep "Accepted" /var/log/auth.log | grep IP - If successful login found: escalate to Active Incident, trigger full forensics with Velociraptor
Playbook: Malware Detected on Endpoint
- Wazuh FIM (File Integrity Monitoring) fires: new file dropped in /tmp with executable bit
- Velociraptor: collect process list, network connections, file hashes from affected host
- Hash the suspicious file:
md5sum /tmp/suspicious_file - Check hash in VirusTotal via Cortex enrichment
- If positive match: isolate endpoint (block network in firewall/switch), preserve forensic image
- Search for same hash across all other endpoints using Velociraptor hunt
Cost Comparison: Open Source SOC vs. Commercial
A commercial SOC stack (Splunk Enterprise + CrowdStrike + FireEye) for 100 endpoints typically runs $150,000–$300,000 per year in licensing alone. The open source stack described here costs $0 in licensing — just hardware, electricity, and analyst time. Wazuh, Suricata, TheHive, MISP, and Velociraptor are all production-grade tools used by government agencies, financial institutions, and MSSPs worldwide. The trade-off is setup complexity and the time investment to maintain and tune the rules. For organizations willing to invest that time, the savings are substantial and the capabilities are genuinely comparable.