Setting Up OpenCTI: A Beginner's Guide
Introduction
When I first set out to stand up OpenCTI in my home lab, I figured getting it configured and adding connectors would be plug-and-play. I was wrong — but the process taught me a lot about container management, environment variables, and the subtle ways OpenCTI expects things to be structured. If you're working on a home lab or just starting out with OpenCTI, this guide should help you skip some of the stumbling blocks I hit along the way.
This post is for folks like me — those trying to learn threat intelligence tooling by doing. We'll walk through my environment, the setup process, where things went wrong, and how I eventually got the VirusTotal and AlienVault OTX connectors fully functional.
Environment Overview
Here’s what I’m working with in the lab:
Hypervisor: Proxmox VE
Host Hardware: Dell PowerEdge R640
OpenCTI Version:
6.7.3
Deployment Method: Official
opencti-docker
GitHub repoOpenCTI URL: Internal LAN IP —
http://10.0.0.61:8080
Connectors Deployed:
File import/export (STIX, TXT, CSV)
Document import
VirusTotal (finally working after some troubleshooting)
AlienVault OTX (successfully integrated and pulling threat intel)
I installed OpenCTI using Docker Compose, with everything — Elasticsearch, MinIO, RabbitMQ, Redis, Neo4j — running in containers. All configuration was managed through the .env
file and docker-compose.yml
. I’m also using Docker Desktop on my daily driver to check container logs and test configs when needed.
Networking-wise, this lab is isolated but reachable from my main workstation. I’m not exposing OpenCTI outside of my internal network.
Troubleshooting the VirusTotal Connector
I initially added the VirusTotal connector thinking it would be a simple case of copy, paste, and deploy. That wasn’t the case.
The biggest hurdle? Setting the correct CONNECTOR_TYPE
. At first, I set it to EXTERNAL_ENRICHMENT
because that seemed to make sense. Turns out, INTERNAL_ENRICHMENT
is the only accepted value.
- CONNECTOR_TYPE=INTERNAL_ENRICHMENT
The container kept throwing logs like:
'EXTERNAL_ENRICHMENT' is not a valid ConnectorType
Once I corrected the connector type, it spun up cleanly. From there, I confirmed that the container was running using:
docker compose ps | grep virustotal
And checked logs with:
docker logs opencti-docker-connector-virustotal-1 --tail=50
This gave me confidence the integration was live, even if I didn’t have observables yet.
Testing and Integration
At this point, I had the VirusTotal connector working — but I didn’t have any data to enrich. I hadn’t integrated OpenCTI with a SIEM or log source, and I wasn’t feeding it indicators from anywhere else.
So I pivoted. If I wasn’t going to push observables in, I needed something to pull them in. That’s when I set up the AlienVault OTX connector.
Adding the AlienVault connector was straightforward. I grabbed my OTX API key, added the configuration block from the official OpenCTI GitHub repo into my docker-compose.yml
, and set some sane defaults:
Collection interval: every 30 minutes
Confidence scores for different observable types
Auto-create indicators
After a docker compose up -d --profile connectors
, it came alive.
First Signs of Life
I checked the Observables and Dashboards tab in the UI... and data was there. It felt like flipping a switch. Suddenly I had:
350+ indicators
Reports attributed to known actors like RastaFarEye and Chinese state actors
Active malware listings like PikaBot and BitRAT
Geographic targeting visuals
Populating OpenCTI with Observables from AlienVault OTX
Once the AlienVault connector was running, the payoff was nearly instant. I opened the Observables tab and finally saw real data streaming in — hashes, indicators, and labels tied to ransomware families like Phobos and actors linked to AlienVault pulses.
Here’s what that looks like:
Each observable was attributed to a report, tagged with context-rich labels like ransomware
, phobos
, and cyber
. Even better, these were all marked TLP:CLEAR
, which makes them perfect for lab and educational use.
This kind of automatic ingestion gives you an excellent jumpstart if you don’t already have a live feed from a SIEM, SOAR, or third-party system. It transforms OpenCTI from a slick-looking empty shell into an active CTI environment ready for exploration, analysis, and learning.
Outro
Getting to this point wasn’t quick — but it was absolutely worth the effort. I now have a functional OpenCTI environment that pulls in timely, relevant threat data from AlienVault OTX and is ready for enrichment via VirusTotal.
This setup has not only made OpenCTI feel useful but has also given me hands-on experience managing Docker containers, debugging connector issues, and learning what makes CTI tools tick.
Next steps? I'll likely explore adding MISP or Abuse.ch connectors, try manually uploading STIX files, and maybe even start testing correlation rules.
If you’re setting up your own OpenCTI instance, I hope this guide helps you skip the headache and get to the good part: diving into the data.