Splunk HEC
Ingest logs from Splunk forwarders, Cribl, and other HEC-compatible sources
Splunk HEC
nano accepts logs via the Splunk HTTP Event Collector (HEC) protocol on port 8088. This lets you forward data from Splunk Universal Forwarders, Splunk Heavy Forwarders, Cribl Stream, and any other tool that speaks HEC — without changing your existing log shipping infrastructure.
How It Works
Splunk HEC is a simple HTTP JSON protocol. Clients POST events to /services/collector/event (single event) or /services/collector (batch) with a token in the Authorization: Splunk <token> header.
nano's Vector pipeline listens on port 8088 and accepts HEC events natively. The Splunk sourcetype field is used for routing — nano maps it to source_type to select the correct parser.
Splunk compatibility: nano's query language also supports sourcetype as an alias for source_type. You can search with sourcetype="WinEventLog:Security" just like in Splunk.
Prerequisites
- A running nano instance with port 8088 accessible
- A Splunk forwarder, Cribl Stream, or any HEC-compatible client
Step 1: Get the HEC Token
nano uses a shared authentication token for HEC ingestion. This is the same token used for HTTP ingestion (VECTOR_AUTH_TOKEN).
For production deployments, this token is set via environment variable on the nano Vector service:
# Check current token (in docker-compose or k8s deployment)
echo $VECTOR_AUTH_TOKENUse a strong token in production. The default development token should be replaced with a randomly generated value: openssl rand -base64 32
Step 2: Configure Your HEC Client
Splunk Universal Forwarder
Configure the UF to send to nano instead of (or in addition to) a Splunk indexer.
Edit outputs.conf on the forwarder:
[httpout]
httpEventCollectorToken = your-nano-token
uri = https://your-nano-instance.com:8088/services/collector
[httpout:nano]
httpEventCollectorToken = your-nano-token
uri = https://your-nano-instance.com:8088/services/collectorOr use outputs.conf with the HEC output:
[tcpout]
defaultGroup = nano-hec
[tcpout:nano-hec]
server = your-nano-instance.com:8088
token = your-nano-token
useHTTP = trueSplunk Heavy Forwarder
Add a new output to forward to nano. In outputs.conf:
[httpout:nano]
httpEventCollectorToken = your-nano-token
uri = https://your-nano-instance.com:8088/services/collectorCribl Stream
Create a Splunk HEC destination in Cribl:
- Go to Destinations → Splunk HEC
- Configure:
| Field | Value |
|---|---|
| Endpoint | https://your-nano-instance.com:8088/services/collector |
| HEC Auth Token | Your nano token |
| Backpressure behavior | Block |
Fluent Bit
Fluent Bit has a native Splunk output plugin:
[OUTPUT]
Name splunk
Match *
Host your-nano-instance.com
Port 8088
Splunk_Token your-nano-token
TLS On
TLS.Verify Offcurl (Testing)
Send a test event to verify connectivity:
curl -X POST https://your-nano-instance.com:8088/services/collector/event \
-H "Authorization: Splunk your-nano-token" \
-d '{
"time": 1705312800,
"sourcetype": "test_app",
"source": "test",
"host": "myhost",
"event": {
"message": "Test event from curl",
"level": "INFO",
"user": "admin"
}
}'A successful response returns:
{"text": "Success", "code": 0}Batch Events
Send multiple events in a single request (no array wrapper — just concatenated JSON objects):
curl -X POST https://your-nano-instance.com:8088/services/collector \
-H "Authorization: Splunk your-nano-token" \
-d '{"time": 1705312800, "sourcetype": "test_app", "event": {"message": "Event 1"}}
{"time": 1705312801, "sourcetype": "test_app", "event": {"message": "Event 2"}}
{"time": 1705312802, "sourcetype": "test_app", "event": {"message": "Event 3"}}'Step 3: Understand sourcetype Routing
The sourcetype field in HEC events is the routing key. nano uses it to determine which parser processes the event — just like Splunk uses it to select the correct parsing pipeline.
How Routing Works
When a HEC event arrives with "sourcetype": "WinEventLog:Security":
- Vector extracts the
sourcetypefield from the HEC payload - A routing transform maps
sourcetypeto nano's internalsource_type - The event is forwarded to the matching parser
Common Splunk Sourcetypes
| Splunk sourcetype | nano source_type | Log Type |
|---|---|---|
WinEventLog:Security | windows_event | Windows Security Event Log |
WinEventLog:System | windows_system | Windows System Event Log |
XmlWinEventLog:Security | windows_event | Windows XML Event Log |
pan:traffic | palo_alto | Palo Alto Traffic |
pan:threat | palo_alto_threat | Palo Alto Threat |
cisco:asa | cisco_asa | Cisco ASA Firewall |
syslog | syslog | Generic Syslog |
linux_secure | linux_auth | Linux Auth Log |
access_combined | apache | Apache/Nginx Access |
Custom sourcetypes work too. If your Splunk deployment uses custom sourcetypes like myapp:access, create a matching log source in nano with that source type. The sourcetype value flows through as-is unless it matches a known alias.
Step 4: Create Log Sources in nano
For each sourcetype your forwarders send, create a log source with a matching parser:
- Navigate to Feeds → New Feed
- Select "Sample from existing data" if events are already flowing, or "I have sample logs" to paste examples
- Set the source type to match the
sourcetypeyour clients send - The AI generates a parser for the log format
- Publish to deploy
Windows Event Logs (Common HEC Use Case)
If you're forwarding Windows Event Logs via Splunk UF:
- Paste a sample Windows Security event (XML or rendered text, depending on your UF config)
- nano's parser will extract fields like
EventCode,Account_Name,Source_Network_Address, etc. - Set source type to
windows_event - Publish
Palo Alto via HEC
If Palo Alto logs flow through a Splunk forwarder with sourcetype=pan:traffic:
- Paste a sample Palo Alto CSV traffic log
- The parser extracts fields like
src_ip,dst_ip,action,rule,app - Set source type to
palo_alto - Publish
Step 5: Verify Ingestion
Search Your Data
Navigate to Search and query using either field name:
source_type="windows_event"Or the Splunk-compatible alias:
sourcetype="WinEventLog:Security"Both return the same results.
Check Feed Health
- Go to Feeds → select your log source
- On the Overview tab, verify:
- Status: Healthy
- Event Volume chart: Events arriving
- Last Event: Recent timestamp
Check for Errors
If events aren't appearing:
-
Test HEC connectivity:
curl -v -X POST https://your-nano-instance.com:8088/services/collector/event \ -H "Authorization: Splunk your-token" \ -d '{"sourcetype": "test", "event": "hello"}'200 OKwith{"text":"Success","code":0}— connection and auth working401— wrong token- Connection refused — port 8088 not exposed or firewall blocking
-
Check Vector logs:
docker logs nanosiem-vector 2>&1 | grep -i "splunk\|hec\|8088\|error" -
Check ingestion errors in nano at System → Ingestion Errors
Migrating from Splunk to nano
If you're migrating from Splunk, the HEC integration makes it straightforward to run both systems in parallel:
Dual-Forward Strategy
Configure your forwarders to send to both Splunk and nano simultaneously:
# outputs.conf on Splunk Universal Forwarder
[tcpout]
defaultGroup = splunk-indexers
[tcpout:splunk-indexers]
server = splunk-idx1:9997, splunk-idx2:9997
[httpout:nano]
httpEventCollectorToken = your-nano-token
uri = https://your-nano-instance.com:8088/services/collectorThis lets you:
- Build and validate nano parsers against real production data
- Compare search results between Splunk and nano
- Migrate detection rules gradually
- Cut over source by source when confident
Cribl as a Router
If you use Cribl Stream, it can route data to both Splunk and nano simultaneously:
Sources → Cribl Stream → Splunk HEC (nano)
→ Splunk IndexersThis is often the cleanest approach for parallel operation.
HEC Payload Reference
Single Event
{
"time": 1705312800,
"host": "webserver-01",
"source": "/var/log/nginx/access.log",
"sourcetype": "nginx:access",
"index": "main",
"event": {
"remote_addr": "203.0.113.50",
"request": "GET /api/users HTTP/1.1",
"status": 200,
"bytes": 1234
}
}| Field | Required | Description |
|---|---|---|
event | Yes | The log event (string or JSON object) |
sourcetype | Recommended | Maps to nano source_type for parser routing |
time | No | Unix epoch timestamp (seconds or milliseconds). If omitted, nano uses receipt time |
host | No | Hostname of the originating system |
source | No | Log file path or data source name |
index | No | Ignored by nano (included for Splunk compatibility) |
Raw Event
For plain-text logs, send the raw string as the event value:
{
"sourcetype": "syslog",
"event": "Jan 15 14:23:45 fw-01 %ASA-6-302013: Built outbound TCP connection 12345 for outside:203.0.113.50/443"
}Troubleshooting
"Invalid token" response
- Verify you're using
Authorization: Splunk <token>(notBearer) - Check the token matches the
VECTOR_AUTH_TOKENenvironment variable on the nano Vector service
Events received but wrong sourcetype
- Check that the
sourcetypefield is set correctly in your forwarder config (props.conforinputs.conf) - For Cribl, verify the sourcetype is preserved in the pipeline (check for transforms that modify it)
Timestamp issues
- HEC accepts Unix epoch in seconds (
1705312800) or milliseconds (1705312800000) — Vector handles both - If
timeis omitted, nano uses the receipt time - Ensure your forwarder is sending timestamps in UTC
Large events being dropped
- Vector's HEC source has a default max body size. For very large events (>1MB), check Vector logs for size-related errors
- Consider splitting large events or increasing the Vector buffer size
Next Steps
- Create detection rules for your HEC-sourced logs
- Configure enrichment to add GeoIP and threat intel
- Set up cloud integrations: AWS S3/SQS, GCP Pub/Sub
- Deploy a Vector Aggregator for sources that don't speak HEC