Log Simulator API in Node.js for testing a SIEM in ELK
194
This guide explains how to run the Log Simulator API from a Docker image using terminal commands.
Repository:
Docker image used in the examples:
archety/siem-log-simulator:latest
This document is written for users who only have access to the Docker image and want to start containers from the terminal.
Default service URL:
http://localhost:3000
Default API prefix:
/api/v1
Health endpoint:
/health
docker pull archety/siem-log-simulator:latest
Verify the image:
docker images johnnypax/siem-log-simulator
docker run --rm \
--name siem-log-simulator \
-p 3000:3000 \
archety/siem-log-simulator:latest
PowerShell:
docker run --rm `
--name siem-log-simulator `
-p 3000:3000 `
archety/siem-log-simulator:latest
Check health:
curl http://localhost:3000/health
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
archety/siem-log-simulator:latest
Follow container stdout/stderr:
docker logs -f siem-log-simulator
Stop and remove:
docker stop siem-log-simulator
docker rm siem-log-simulator
The application writes simulated logs inside the container at:
/var/log/logsim
Use a Docker volume or a bind mount to keep generated logs.
docker volume create logsim-data
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Inspect the volume:
docker volume inspect logsim-data
Remove the volume when no longer needed:
docker volume rm logsim-data
mkdir -p ./logs
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_DIRECTORY=/var/log/logsim \
-v "$(pwd)/logs:/var/log/logsim" \
archety/siem-log-simulator:latest
New-Item -ItemType Directory -Force -Path .\logs | Out-Null
docker run -d `
--name siem-log-simulator `
-p 3000:3000 `
-e LOG_DIRECTORY=/var/log/logsim `
-v "${PWD}\logs:/var/log/logsim" `
archety/siem-log-simulator:latest
Automatic generation is disabled. Use REST endpoints to generate logs.
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=false \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=true \
-e AUTO_INTERVAL_MS=1000 \
-e AUTO_EVENTS_PER_INTERVAL=5 \
-e AUTO_PROFILES=ssh,firewall,webserver,application,dns,vpn,endpoint,ids \
-e AUTO_PROFILE_WEIGHTS=ssh:25,firewall:20,webserver:20,application:10,dns:15,vpn:10,endpoint:15,ids:10 \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Useful for Elastic Common Schema ingestion tests.
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=true \
-e AUTO_FORMAT_MODE=per-profile \
-e LOG_FORMAT_SSH=ecs-json \
-e LOG_FORMAT_FIREWALL=ecs-json \
-e LOG_FORMAT_WEBSERVER=ecs-json \
-e LOG_FORMAT_APPLICATION=ecs-json \
-e LOG_FORMAT_DNS=ecs-json \
-e LOG_FORMAT_VPN=ecs-json \
-e LOG_FORMAT_ENDPOINT=ecs-json \
-e LOG_FORMAT_IDS=ecs-json \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=true \
-e AUTO_FORMAT_MODE=fixed \
-e LOG_DEFAULT_FORMAT=json \
-e LOG_FORMAT_SSH=json \
-e LOG_FORMAT_FIREWALL=json \
-e LOG_FORMAT_WEBSERVER=json \
-e LOG_FORMAT_APPLICATION=json \
-e LOG_FORMAT_DNS=json \
-e LOG_FORMAT_VPN=json \
-e LOG_FORMAT_ENDPOINT=json \
-e LOG_FORMAT_IDS=json \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=true \
-e AUTO_FORMAT_MODE=per-profile \
-e LOG_FORMAT_SSH=syslog-bsd \
-e LOG_FORMAT_FIREWALL=cef \
-e LOG_FORMAT_VPN=syslog-rfc5424 \
-e LOG_FORMAT_IDS=cef \
-e AUTO_PROFILES=ssh,firewall,vpn,ids \
-e AUTO_PROFILE_WEIGHTS=ssh:25,firewall:25,vpn:25,ids:25 \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=true \
-e AUTO_PROFILES=webserver \
-e AUTO_PROFILE_WEIGHTS=webserver:100 \
-e LOG_FORMAT_WEBSERVER=nginx-access \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e AUTO_ENABLED=true \
-e AUTO_PROFILES=ssh,firewall,dns,vpn,endpoint,ids \
-e AUTO_PROFILE_WEIGHTS=ssh:20,firewall:20,dns:15,vpn:15,endpoint:15,ids:15 \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e API_KEY_ENABLED=true \
-e API_KEY=change-me \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Requests to /api/v1/* must include:
X-API-Key: change-me
/health remains public.
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_ROTATE_MAX_SIZE=20m \
-e LOG_ROTATE_DAILY=true \
-e LOG_ROTATE_MAX_FILES=14 \
-e LOG_ROTATE_COMPRESS=true \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Example files:
ssh/syslog-bsd.log
ssh/syslog-bsd.2026-08-06.1.log.gz
ssh/syslog-bsd.2026-08-06.2.log.gz
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_ROTATE_MAX_SIZE=1k \
-e LOG_ROTATE_DAILY=true \
-e LOG_ROTATE_MAX_FILES=3 \
-e LOG_ROTATE_COMPRESS=false \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Then generate enough events:
curl -X POST http://localhost:3000/api/v1/events/application \
-H "Content-Type: application/json" \
-d '{
"eventType": "unhandled-exception",
"format": "application-text",
"count": 100
}'
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_LAYOUT=single-file \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Output:
/var/log/logsim/events.log
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_LAYOUT=per-profile \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Output:
/var/log/logsim/ssh.log
/var/log/logsim/firewall.log
/var/log/logsim/webserver.log
/var/log/logsim/application.log
/var/log/logsim/dns.log
/var/log/logsim/vpn.log
/var/log/logsim/endpoint.log
/var/log/logsim/ids.log
docker run -d \
--name siem-log-simulator \
-p 3000:3000 \
-e LOG_LAYOUT=per-profile-format \
-e LOG_DIRECTORY=/var/log/logsim \
-v logsim-data:/var/log/logsim \
archety/siem-log-simulator:latest
Output:
/var/log/logsim/ssh/syslog-bsd.log
/var/log/logsim/firewall/cef.log
/var/log/logsim/webserver/nginx-access.log
/var/log/logsim/application/ecs-json.json
/var/log/logsim/dns/ecs-json.json
/var/log/logsim/vpn/syslog-rfc5424.log
/var/log/logsim/endpoint/ecs-json.json
/var/log/logsim/ids/cef.log
curl http://localhost:3000/health
Example response:
{
"status": "UP",
"scheduler": "RUNNING",
"eventsGenerated": 15420,
"activeProfiles": ["ssh", "firewall", "webserver", "application", "dns", "vpn", "endpoint", "ids"]
}
docker inspect --format='{{json .State.Health}}' siem-log-simulator
PowerShell:
docker inspect --format="{{json .State.Health}}" siem-log-simulator
docker exec siem-log-simulator find /var/log/logsim -maxdepth 4 -type f
docker exec siem-log-simulator tail -n 20 /var/log/logsim/ssh/syslog-bsd.log
docker exec siem-log-simulator tail -n 20 /var/log/logsim/dns/ecs-json.json
docker exec siem-log-simulator tail -n 20 /var/log/logsim/ids/cef.log
docker cp siem-log-simulator:/var/log/logsim ./logsim-export
All examples assume the container is running on:
http://localhost:3000
curl http://localhost:3000/health
curl http://localhost:3000/api/v1/profiles
curl http://localhost:3000/api/v1/stats
curl http://localhost:3000/api/v1/scheduler
curl -X POST http://localhost:3000/api/v1/scheduler/start
curl -X POST http://localhost:3000/api/v1/scheduler/stop
curl http://localhost:3000/api/v1/config
curl -X PATCH http://localhost:3000/api/v1/config \
-H "Content-Type: application/json" \
-d '{
"auto": {
"enabled": true,
"eventsPerInterval": 10,
"profiles": ["ssh", "firewall", "dns", "ids"],
"profileWeights": {
"ssh": 25,
"firewall": 25,
"dns": 25,
"ids": 25
}
}
}'
curl -X POST http://localhost:3000/api/v1/events/ssh \
-H "Content-Type: application/json" \
-d '{
"eventType": "failed-password",
"format": "syslog-bsd",
"count": 5,
"sourceIp": "203.0.113.45",
"username": "admin",
"hostname": "bastion"
}'
curl -X POST http://localhost:3000/api/v1/events/firewall \
-H "Content-Type: application/json" \
-d '{
"eventType": "connection-denied",
"format": "cef",
"count": 5,
"sourceIp": "203.0.113.77",
"destinationIp": "10.10.0.10",
"destinationPort": 443
}'
curl -X POST http://localhost:3000/api/v1/events/webserver \
-H "Content-Type: application/json" \
-d '{
"eventType": "http-403",
"format": "nginx-access",
"count": 5,
"sourceIp": "203.0.113.88"
}'
curl -X POST http://localhost:3000/api/v1/events/application \
-H "Content-Type: application/json" \
-d '{
"eventType": "database-timeout",
"format": "ecs-json",
"count": 5,
"service": "orders-api"
}'
curl -X POST http://localhost:3000/api/v1/events/dns \
-H "Content-Type: application/json" \
-d '{
"eventType": "dns-tunneling-suspected",
"format": "ecs-json",
"count": 3,
"sourceIp": "203.0.113.10"
}'
curl -X POST http://localhost:3000/api/v1/events/vpn \
-H "Content-Type: application/json" \
-d '{
"eventType": "mfa-failed",
"format": "syslog-rfc5424",
"count": 3,
"sourceIp": "203.0.113.22",
"username": "admin"
}'
curl -X POST http://localhost:3000/api/v1/events/endpoint \
-H "Content-Type: application/json" \
-d '{
"eventType": "malware-detected",
"format": "json",
"count": 2,
"hostname": "win-hr-014",
"username": "alice"
}'
curl -X POST http://localhost:3000/api/v1/events/ids \
-H "Content-Type: application/json" \
-d '{
"eventType": "command-and-control-suspected",
"format": "cef",
"count": 3,
"sourceIp": "203.0.113.99",
"destinationIp": "10.10.0.20"
}'
Render-only calls return generated lines without writing files.
curl -X POST http://localhost:3000/api/v1/render \
-H "Content-Type: application/json" \
-d '{
"profile": "ssh",
"eventType": "failed-password",
"format": "cef",
"count": 3
}'
curl -X POST http://localhost:3000/api/v1/render \
-H "Content-Type: application/json" \
-d '{
"profile": "dns",
"eventType": "query-blocked",
"format": "ecs-json",
"count": 2,
"sourceIp": "203.0.113.10"
}'
curl -X POST http://localhost:3000/api/v1/render \
-H "Content-Type: application/json" \
-d '{
"profile": "ids",
"eventType": "exploit-attempt",
"format": "cef",
"count": 2
}'
curl -X POST http://localhost:3000/api/v1/scenarios/brute-force \
-H "Content-Type: application/json" \
-d '{
"durationSeconds": 20,
"eventsPerSecond": 5,
"sourceIp": "203.0.113.45",
"format": "ecs-json"
}'
curl -X POST http://localhost:3000/api/v1/scenarios/port-scan \
-H "Content-Type: application/json" \
-d '{
"durationSeconds": 15,
"eventsPerSecond": 10,
"sourceIp": "198.51.100.90",
"destinationIp": "10.10.0.20",
"format": "cef"
}'
curl -X POST http://localhost:3000/api/v1/scenarios/web-outage \
-H "Content-Type: application/json" \
-d '{
"durationSeconds": 30,
"eventsPerSecond": 8,
"format": "nginx-access"
}'
curl -X POST http://localhost:3000/api/v1/scenarios/database-failure \
-H "Content-Type: application/json" \
-d '{
"durationSeconds": 20,
"eventsPerSecond": 5,
"service": "orders-api",
"format": "ecs-json"
}'
| Profile | Supported formats |
|---|---|
ssh | syslog-bsd, syslog-rfc5424, json, ecs-json, cef |
firewall | syslog-bsd, syslog-rfc5424, json, ecs-json, cef |
webserver | nginx-access, nginx-error, json, ecs-json, cef |
application | application-text, json, ecs-json, cef |
dns | syslog-bsd, syslog-rfc5424, json, ecs-json, cef |
vpn | syslog-bsd, syslog-rfc5424, json, ecs-json, cef |
endpoint | syslog-bsd, syslog-rfc5424, json, ecs-json, cef |
ids | syslog-bsd, syslog-rfc5424, json, ecs-json, cef |
Unsupported combinations return 422 Unprocessable Entity.
Stop and remove the container:
docker stop siem-log-simulator
docker rm siem-log-simulator
Remove the named volume:
docker volume rm logsim-data
Remove exported logs:
rm -rf ./logsim-export
PowerShell:
Remove-Item -Recurse -Force .\logsim-export
docker pull archety/siem-log-simulator:latest
If the pull fails, check Docker Hub access, DNS, proxy settings, or registry authentication.
Check that the port was published:
docker ps
The container should show:
0.0.0.0:3000->3000/tcp
Check logs:
docker logs siem-log-simulator
Check whether you called /api/v1/render. Render-only mode does not write files.
Check generated files:
docker exec siem-log-simulator find /var/log/logsim -maxdepth 4 -type f
Check scheduler status:
curl http://localhost:3000/api/v1/scheduler
The container runs as a non-root Node user. If bind mounts fail, use a named volume first:
docker volume create logsim-data
If API_KEY_ENABLED=true, send:
curl http://localhost:3000/api/v1/profiles \
-H "X-API-Key: change-me"
docker pull archety/siem-log-simulator:latest
docker volume create logsim-data
docker run -d --name siem-log-simulator -p 3000:3000 -v logsim-data:/var/log/logsim archety/siem-log-simulator:latest
docker logs -f siem-log-simulator
docker exec siem-log-simulator find /var/log/logsim -maxdepth 4 -type f
curl http://localhost:3000/health
curl http://localhost:3000/api/v1/profiles
curl http://localhost:3000/api/v1/stats
docker stop siem-log-simulator
docker rm siem-log-simulator
MIT License
Copyright (c) 2026 Giovanni Pace
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
If this project helped you build something useful or learn something new, consider offering a coffee.
The best way to support my work is by subscribing to my YouTube channel:
Content type
Image
Digest
sha256:ab9451c02…
Size
57.5 MB
Last updated
about 1 month ago
docker pull archety/siem-log-simulator