TL;DR: Yes, You Can Build a Free Elastic Security SOC on a Single Homelab Machine
Elastic Security is free under the Basic license—detection rules, dashboards, timelines, and cases all included at zero cost. Pair it with Sysmon for rich Windows telemetry and Winlogbeat for shipping, and you have a functioning security operations center lab: real detections, real dashboards, real triage workflow. No vendor trial expirations, no crippled features.
Lab Architecture and Hardware Requirements
Before you install anything, size the environment honestly. Elastic is hungry, and under-provisioned labs are the number one reason people abandon the project.
Realistic minimum topology:
- Ubuntu 22.04 LTS VM (Elastic host): 8 GB RAM, 4 vCPUs, 100+ GB disk. This runs Elasticsearch and Kibana. 16 GB is the comfortable target once you add detection workloads and retention.
- Windows 10/11 VM (telemetry source): 4 GB RAM, 2 vCPUs. This runs Sysmon and Winlogbeat and serves as your attack surface.
- Hypervisor: VMware Workstation, VirtualBox, or Proxmox—whatever you already run.
So yes, a single 16 GB machine can host everything. Below 12 GB total, expect Elasticsearch to OOM-kill itself during index merges, and you’ll waste evenings debugging memory pressure instead of hunting threats. Set Elasticsearch’s JVM heap to 50% of available RAM, capped at ~4 GB in a lab—no more than ~31 GB even at scale, per Elastic’s own heap sizing guidance (Elastic documentation).
Installing Elasticsearch and Kibana with Security Enabled
The fastest path in a lab is Docker. The .deb/.msi routes work identically, but Docker gives you clean teardown.
Bring up Elasticsearch 8.x with security enabled (8.x enables it by default):
docker network create elastic
docker run -d --name elasticsearch --net elastic
-p 9200:9200
-e discovery.type=single-node
-e ES_JAVA_OPTS="-Xms2g -Xmx2g"
-e xpack.security.enabled=true
docker.elastic.co/elasticsearch/elasticsearch:8.15.0
Retrieve the generated elastic superuser password and enrollment token from the container logs (docker logs elasticsearch), or reset credentials explicitly:
docker exec elasticsearch /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
Note: elasticsearch-setup-passwords, which older tutorials reference, is deprecated as of 8.x in favor of elasticsearch-reset-password and the service tokens API—use the modern tooling.
Then Kibana:
docker run -d --name kibana --net elastic
-p 5601:5601
-e ELASTICSEARCH_HOSTS=http://elasticsearch:9200
-e ELASTICSEARCH_USERNAME=elastic
-e ELASTICSEARCH_PASSWORD=<your_password>
docker.elastic.co/kibana/kibana:8.15.0
For TLS, the lab shortcut: terminate HTTPS at a reverse proxy (nginx/Caddy) in front of Kibana, or generate self-signed certs with elasticsearch-certutil. Don’t disable security to “make it work”—a SOC that runs on an unsecured cluster is a bad habit formed early.
Installing Sysmon on the Windows Endpoint
Sysmon (Windows System Monitor) is Microsoft’s Sysinternals utility that captures detailed process, network, file, and registry telemetry to the Microsoft-Windows-Sysmon/Operational event channel. It’s the backbone of most Windows detection engineering.
Install it with a community-tuned config—SwiftOnSecurity’s sysmon-config is the de facto starting point (github.com/SwiftOnSecurity/sysmon-config):
# Admin PowerShell
Invoke-WebRequest https://download.sysinternals.com/files/Sysmon.zip -OutFile Sysmon.zip
Expand-Archive Sysmon.zip -DestinationPath C:Sysmon
Invoke-WebRequest https://raw.githubusercontent.com/SwiftOnSecurity/sysmon-config/master/sysmonconfig-export.xml -OutFile C:Sysmonsysmonconfig.xml
C:SysmonSysmon64.exe -accepteula -i C:Sysmonsysmonconfig.xml
Verify the channel is producing events:
wevtutil qe "Microsoft-Windows-Sysmon/Operational" /c:5 /f:text /rd:true
If you see Event ID 1 (process creation) entries, you’re collecting. If the channel is empty, launch something—Sysmon only logs on activity.
Shipping Logs with Winlogbeat
Winlogbeat reads Windows event channels and ships them to Elasticsearch with ECS-compatible field mapping out of the box. On the Windows VM:
Download and extract Winlogbeat 8.x, then edit winlogbeat.yml:
winlogbeat.event_logs:
- name: Microsoft-Windows-Sysmon/Operational
- name: Security
- name: System
output.elasticsearch:
hosts: ["https://elastic-host:9200"]
username: "elastic"
password: "<password>"
ssl.verification_mode: none # lab only — use real CA certs in production
setup.kibana:
host: "http://kibana-host:5601"
Install the index template and ingest pipelines, then run it as a service:
.winlogbeat.exe test config -e
.winlogbeat.exe setup -e
.winlogbeat.exe install-service
Start-Service winlogbeat
Confirm data landed, from Kibana Dev Tools:
GET winlogbeat-*/_count
GET winlogbeat-*/_search
{ "size": 1, "sort": [{ "@timestamp": "desc" }] }
A nonzero count and a recent document mean your pipeline works. No hits? Check Windows Event Log channel names—typos there are the most common failure.
Mapping Sysmon Events to Elastic Schema (ECS)
Winlogbeat’s strength is that it doesn’t dump raw winlog.event_data blobs at you—it normalizes into the Elastic Common Schema (ECS). Image becomes process.executable, SourceIp becomes source.ip, DestinationHostname becomes destination.domain. The raw fields still exist under winlog.event_data.* for anything the schema doesn’t cover.
One field deserves special attention: process.entity_id. Winlogbeat synthesizes this from the process GUID Sysmon assigns, making it unique across reboots. Detection lineage depends on it—when you pivot from a process creation event to its child processes and network connections, you’re joining on process.entity_id and process.parent.entity_id. Master that join and process-tree analysis becomes trivial; ignore it and every investigation becomes grepping timestamps.
The key Sysmon event IDs to internalize:
- 1 — process creation (the workhorse)
- 3 — network connection
- 7 — image loaded (DLL loads; think lsass access tooling)
- 10 — process access (cross-process handle injection—Mimikatz territory)
- 11 — file creation (drop locations)
- 22 — DNS query
Building Detection Rules
Elastic’s prebuilt rules are a solid baseline, but the point of a lab is writing your own. Rules are defined in TOML with EQL (Event Query Language) or Lucene/THREAT queries. Two starters:
Encoded PowerShell execution:
from tomllib import none # illustrative — actual rule TOML below
[rule]
name = "Suspicious Encoded PowerShell"
index = ["winlogbeat-*"]
language = "eql"
query = """
process where event.action == "Process Create (rule: ProcessCreate)"
and process.command_line : "*-enc*" and process.name : ("powershell.exe", "pwsh.exe")
"""
severity = "high"
type = "eql"
LOLBin: certutil downloading a file:
[rule]
name = "Certutil URL Download"
index = ["winlogbeat-*"]
language = "eql"
query = """
process where process.name : "certutil.exe"
and process.command_line : "*urlcache*"
"""
severity = "high"
type = "eql"
LSASS access (Mimikatz-style): a threshold or EQL rule matching Sysmon Event ID 10 where TargetImage ends in lsass.exe and GrantedAccess includes 0x1010 or similar permissive masks. Microsoft and Elastic both document this pattern extensively; Elastic’s prebuilt rule library is worth studying line by line (Elastic Security rules).
Import rules via the Kibana UI (Security → Rules → Import) using Elastic’s detection-rules repo TOML format (github.com/elastic/detection-rules).
Creating SOC Dashboards and Visualizations
With data flowing, build Lens dashboards—fast, drag-and-drop visualizations over the winlogbeat indices:
- Process creations over time: vertical bar chart on
@timestampfiltered toevent.code: "1", split byprocess.name. - Top parent-child process pairs: table of
process.parent.namevsprocess.name—instantly exposes anomalies likewinword.exe → powershell.exe. - Network connections:
source.iptodestination.ip/destination.portfiltered toevent.code: "3". - DNS queries: top
dns.question.namevalues from Event ID 22—your early-warning radar for C2 lookups.
Save associated searches too. A saved search filtered by process.entity_id is your investigation scratchpad—change the filter value, reuse the view for every alert.
Simulating Attacks to Generate Alerts
Detections you’ve never fired are hopes, not detections. Generate safe telemetry deliberately:
Manual, one-liners:
certutil.exe -urlcache -f https://example.com/file.txt C:Tempfile.txt
powershell.exe -enc dwByAGkAdABlAC0A…
Structured: Atomic Red Team provides mapped-to-MITRE ATT&CK test cases with documented cleanup (github.com/redcanaryco/atomic-red-team). Run tests like T1059.001 (PowerShell) on an isolated VM only—never on a host with access to real networks, and never replicate credential theft beyond your own throwaway accounts. CISA’s advisories on adversary simulation emphasize scoping and isolation; treat your lab the same way (cisa.gov).
Expected results: certutil fires your LOLBin rule, encoded PowerShell trips the encoding rule, and an LSASS access test (if you run one carefully) hits your process-access detection. If a rule doesn’t fire, that’s the most valuable finding of the day—debug the query against real telemetry in Dev Tools.
Triage Workflow: From Alert to Verdict
Elastic Security’s Cases feature gives you a lightweight ticketing system. The triage loop:
- Alert fires → open it from the Detections page. Read the rule, severity, and matched event.
- Pivot the process tree → use the Analyzer view in the alert details. Walk up from
process.parent.entity_id: what spawned this? Walk down: what did it do afterward? - Build a Timeline → drag the entity ID into a timeline and correlate events around it—file writes, DNS, network. Five minutes of timeline beats two hours of guesswork.
- Verdict and documentation → attach findings to a Case, mark true positive/false positive/benign positive, and note why. Future-you inherits a searchable record of decisions.
Tune aggressively: every false positive gets a rule exception or query refinement. A SOC that buries analysts in noise gets ignored—by analysts and attackers alike.
Hardening and Next Steps
- ILM policies: set hot/warm/delete phases (e.g., delete at 30–90 days) so your disk doesn’t fill silently.
- Snapshots: register a snapshot repository to a second disk or object storage and schedule daily backups.
- Sysmon tuning: as you learn, tighten the config—reduce noise, add hash capture, enable Event ID 8/9/26.
- Extend the estate: add Elastic Agent with the Fleet-managed Sysmon integration, or layer osquery on the Linux host for different telemetry.
Troubleshooting Common Issues
- Beat won’t connect: test with
.winlogbeat.exe test output -e. Nine times out of ten it’s a password typo or HTTPS verification against a self-signed cert. - No Sysmon events: confirm the channel name string matches exactly, and that the Sysmon service is running (
Get-Service Sysmon64). - Index template/pipeline errors: run
.winlogbeat.exe setup -eagain after upgrades; version mismatches between Beat and stack cause mapping conflicts. - Memory pressure: if Elasticsearch goes red with
circuit_breaking_exception, lower heap expectations or add RAM. A single-node lab will run yellow status by default—that’s normal, not broken.
Frequently Asked Questions
Is Elastic Security free to use?
Yes. The free Basic license includes the SIEM app’s core capabilities: detection rules (including prebuilt ones), dashboards, timelines, and case management. What’s reserved for paid tiers (Platinum/Enterprise) is things like ML-based anomaly detection, advanced alerting features, some threat-intelligence integrations, and cross-cluster search at scale. For a learning SOC, Basic is genuinely enough.
How much RAM do I need for an Elastic SOC homelab?
Realistic floor: 16 GB total—8 GB for Elasticsearch + Kibana, 4–6 GB for the Windows VM, headroom for the hypervisor. Below that, tune JVM heap to 2 GB and accept slower indexing. The heap should stay at roughly 50% of the container’s RAM, never more than ~31 GB even at scale.
Can I use Elastic Agent instead of Winlogbeat for Sysmon?
Yes. Elastic Agent with the Windows/Sysmon integration does the same job with Fleet-based central management and is where Elastic is investing going forward. Winlogbeat is more transparent, better documented in older tutorials, and lighter to reason about—ideal for learning what’s actually being shipped. Start with Winlogbeat to understand the mechanics, migrate to Elastic Agent when you want centralized policy management.
How do I test that my detection rules actually fire?
Run safe simulations: manual LOLBin commands (certutil downloads, encoded PowerShell) or Atomic Red Team test cases mapped to MITRE ATT&CK techniques. Confirm the alert appears in the Detections page within seconds to a few minutes, then verify the matched event is what you intended—firing for the wrong reason is as bad as not firing.
How long should I keep logs in a homelab SOC?
Use ILM: keep data in the hot phase for 7–30 days, delete at 30–90 days depending on disk, and snapshot before deletion if you want archival copies. Long retention without disk budget just degrades the whole cluster; searchable recent data beats dormant data that killed your node.
Related reading
- Testing JWT Security with jwt-cli and Caido: Alg Confusion, Weak Secrets, and Expired Claims
- Weekly Threat Intel: 30 September 2026 — npm Malware, Typosquat Waves and Autumn CVEs
