ThreatChain SIEM
Install the agent on Linux, macOS, or Windows, stand up a server (on-prem or on a single VPS), point the agents at it over mTLS, and get real-time alerts on process, file, log, and Windows Event Log activity.
Architecture
- Agent — a Python daemon on every monitored host. Tails syslog / Windows Event Log / macOS unified log, hashes critical files (FIM), watches processes, and sends events over mTLS to the server.
- Server — a FastAPI service ingesting agent events, running detection rules, storing alerts, serving a dashboard, and fanning out to alert channels (Discord, Telegram, email, webhook).
- PKI — a local CA signs both the server cert and every agent cert. No cert, no events.
No cloud dependency. No SaaS egress. Runs on your hardware.
Platform support
The agent is a pure-Python program and runs on any system with Python 3.10 or newer. Capabilities vary by platform:
| Capability | Linux | macOS | Windows |
|---|---|---|---|
| Syslog / log tailing | ✅ /var/log/syslog, auth.log, secure | ✅ /var/log/system.log, install.log + any app log | ✅ Windows Event Log (Security / System / Application / PowerShell / Sysmon) |
| File Integrity Monitoring | ✅ | ✅ | ✅ |
| Process monitor | ✅ | ✅ | ✅ |
| systemd journal | ✅ (if present) | — (skipped silently) | — (skipped silently) |
| Windows Event Log | — | — | ✅ via pywin32 |
| YARA memory scanning | ✅ | ❌ (Linux-only feature) | ❌ (Linux-only feature) |
| mTLS to server | ✅ | ✅ | ✅ |
Server runs on Linux (Ubuntu 22.04+ / Debian 12+). Windows and macOS aren't supported as server hosts.
Server install
Run on one Linux host — a $5/mo VPS or an on-prem box is plenty. All commands assume root or sudo.
-
Install packages
apt-get update apt-get install -y python3 python3-venv python3-pip openssl git -
Clone and install
mkdir -p /opt/tcsiem cd /opt/tcsiem git clone https://github.com/threatchain/threatchain-siem.git app python3 -m venv venv ./venv/bin/pip install -r app/requirements.txt -
Generate PKI
mkdir -p /etc/tcsiem/pki cd /etc/tcsiem/pki openssl genrsa -out ca.key 4096 openssl req -x509 -new -key ca.key -days 3650 \ -subj "/CN=ThreatChain SIEM CA" -out ca.crt # Replace <server-host> with the DNS name or IP agents will use openssl genrsa -out server.key 2048 openssl req -new -key server.key -subj "/CN=<server-host>" -out server.csr openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -days 825 -out server.crt \ -extfile <(printf "subjectAltName=DNS:<server-host>,IP:<server-ip>") chmod 600 *.key -
Configure
cat > /etc/tcsiem/server.env <<EOF SIEM_HMAC_SECRET=$(openssl rand -hex 32) TCSIEM_ADMIN_TOKEN=$(openssl rand -hex 24) TCSIEM_PKI_DIR=/etc/tcsiem/pki SIEM_RULES_DIR=/etc/tcsiem/rules EOF chmod 600 /etc/tcsiem/server.env mkdir -p /etc/tcsiem/rules /var/lib/tcsiem /var/log/tcsiem useradd -r -s /sbin/nologin tcsiem chown -R tcsiem: /var/lib/tcsiem /var/log/tcsiemSave the admin token. It's the only credential that issues agent certs and reaches admin endpoints. Lose it, regenerate and re-enroll every agent. -
Systemd + start
cat > /etc/systemd/system/tcsiem-server.service <<EOF [Unit] Description=ThreatChain SIEM Server After=network-online.target [Service] Type=simple User=tcsiem Group=tcsiem EnvironmentFile=/etc/tcsiem/server.env WorkingDirectory=/opt/tcsiem/app ExecStart=/opt/tcsiem/venv/bin/uvicorn server.api.app:app \\ --host 0.0.0.0 --port 8403 --workers 4 \\ --ssl-keyfile /etc/tcsiem/pki/server.key \\ --ssl-certfile /etc/tcsiem/pki/server.crt \\ --ssl-ca-certs /etc/tcsiem/pki/ca.crt Restart=always [Install] WantedBy=multi-user.target EOF systemctl daemon-reload && systemctl enable --now tcsiem-server ufw allow 8403/tcp
Agent install
Pick your OS. The agent software and agent.yaml schema are identical across platforms — only the install commands and service wrapper differ.
Before any OS-specific steps, issue a cert for this agent from the server host:
# Run on the SERVER host — produces a JSON bundle with the agent's cert + key
AGENT_ID=$(uuidgen)
curl -sS -X POST https://<server-host>:8403/admin/enroll \
-H "X-Admin-Token: $TCSIEM_ADMIN_TOKEN" \
-d "{\"agent_id\":\"$AGENT_ID\"}" \
--cacert /etc/tcsiem/pki/ca.crt \
-o agent-bundle-$AGENT_ID.json
echo "AGENT_ID=$AGENT_ID"
# Copy agent-bundle-$AGENT_ID.json securely to the target host
Linux (Ubuntu / Debian / RHEL / Amazon Linux)
-
Install agent code
apt-get install -y python3 python3-venv python3-pip openssl mkdir -p /opt/tcsiem /etc/tcsiem/agent/pki cd /opt/tcsiem git clone --branch agent-only https://github.com/threatchain/threatchain-siem.git app python3 -m venv venv ./venv/bin/pip install -r app/requirements-agent.txt -
Unpack the cert bundle
cd /etc/tcsiem/agent/pki python3 -c "import json; d=json.load(open('/tmp/agent-bundle.json')); [open(f,'w').write(d[f]) for f in ['agent.crt','agent.key','ca.crt']]" chmod 600 agent.key -
Write
/etc/tcsiem/agent/agent.yamlcat > /etc/tcsiem/agent/agent.yaml <<EOF agent_id: "$AGENT_ID" server_url: "https://<server-host>:8403" cert_path: /etc/tcsiem/agent/pki/agent.crt key_path: /etc/tcsiem/agent/pki/agent.key ca_cert_path: /etc/tcsiem/agent/pki/ca.crt syslog_paths: - /var/log/auth.log - /var/log/syslog - /var/log/nginx/access.log watch_paths: - /etc/ssh/sshd_config - /etc/sudoers baseline_file: /etc/tcsiem/agent/fim_baseline.json collect_interval: 30 fim_interval: 300 heartbeat_interval: 60 EOF -
Systemd unit + start
cat > /etc/systemd/system/tcsiem-agent.service <<EOF [Unit] Description=ThreatChain SIEM Agent After=network-online.target [Service] Type=simple User=root ExecStart=/opt/tcsiem/venv/bin/python3 /opt/tcsiem/app/run_agent.py Restart=always RestartSec=10 [Install] WantedBy=multi-user.target EOF systemctl daemon-reload && systemctl enable --now tcsiem-agent
macOS (Intel or Apple Silicon)
-
Install Python + agent
# Python 3.11+ from python.org or Homebrew brew install [email protected] openssl sudo mkdir -p /usr/local/tcsiem /etc/tcsiem/agent/pki sudo chown -R $(whoami) /usr/local/tcsiem /etc/tcsiem cd /usr/local/tcsiem git clone --branch agent-only https://github.com/threatchain/threatchain-siem.git app python3 -m venv venv ./venv/bin/pip install -r app/requirements-agent.txt -
Unpack the cert bundle
cd /etc/tcsiem/agent/pki python3 -c "import json; d=json.load(open('/tmp/agent-bundle.json')); [open(f,'w').write(d[f]) for f in ['agent.crt','agent.key','ca.crt']]" chmod 600 agent.key -
Write
/etc/tcsiem/agent/agent.yaml
Same schema as Linux, but use macOS log paths:cat > /etc/tcsiem/agent/agent.yaml <<EOF agent_id: "$AGENT_ID" server_url: "https://<server-host>:8403" cert_path: /etc/tcsiem/agent/pki/agent.crt key_path: /etc/tcsiem/agent/pki/agent.key ca_cert_path: /etc/tcsiem/agent/pki/ca.crt syslog_paths: - /var/log/system.log - /var/log/install.log watch_paths: - /etc/sudoers - /Library/LaunchDaemons/ baseline_file: /etc/tcsiem/agent/fim_baseline.json collect_interval: 30 fim_interval: 300 heartbeat_interval: 60 EOF -
launchd plist + load
sudo tee /Library/LaunchDaemons/io.threatchain.siem-agent.plist >/dev/null <<EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key><string>io.threatchain.siem-agent</string> <key>ProgramArguments</key> <array> <string>/usr/local/tcsiem/venv/bin/python3</string> <string>/usr/local/tcsiem/app/run_agent.py</string> </array> <key>EnvironmentVariables</key> <dict> <key>TCSIEM_CONFIG</key><string>/etc/tcsiem/agent/agent.yaml</string> </dict> <key>RunAtLoad</key><true/> <key>KeepAlive</key><true/> <key>StandardOutPath</key><string>/var/log/tcsiem-agent.log</string> <key>StandardErrorPath</key><string>/var/log/tcsiem-agent.err</string> </dict></plist> EOF sudo launchctl load /Library/LaunchDaemons/io.threatchain.siem-agent.plist sudo launchctl list | grep threatchain
/proc/<pid>/maps). Every other agent feature runs on macOS.Windows (10 / 11 / Server 2019+)
Runs as a Windows Service. Requires Python 3.11+ (from python.org or Microsoft Store) and the pywin32 package for Windows Event Log access. Open PowerShell as Administrator for every step below.
-
Install Python + agent
# If you don't have Python, grab 3.11+ from python.org with "Add to PATH" checked New-Item -ItemType Directory -Force "C:\ProgramData\tcsiem\agent", "C:\ProgramData\tcsiem\agent\pki", "C:\ProgramData\tcsiem\agent\logs" cd "C:\Program Files" git clone --branch agent-only https://github.com/threatchain/threatchain-siem.git tcsiem cd tcsiem py -3.11 -m venv venv .\venv\Scripts\pip install -r requirements-agent.txt .\venv\Scripts\pip install pywin32 -
Unpack the cert bundle
Copyagent-bundle.jsontoC:\ProgramData\tcsiem\agent\then:cd "C:\ProgramData\tcsiem\agent\pki" python -c "import json; d=json.load(open(r'C:\ProgramData\tcsiem\agent\agent-bundle.json')); [open(f,'w').write(d[f]) for f in ['agent.crt','agent.key','ca.crt']]" icacls agent.key /inheritance:r /grant:r "NT AUTHORITY\SYSTEM:F" /grant:r "BUILTIN\Administrators:F" -
Write
C:\ProgramData\tcsiem\agent\agent.yaml@" agent_id: "$env:AGENT_ID" server_url: "https://<server-host>:8403" cert_path: C:\ProgramData\tcsiem\agent\pki\agent.crt key_path: C:\ProgramData\tcsiem\agent\pki\agent.key ca_cert_path: C:\ProgramData\tcsiem\agent\pki\ca.crt windows_event_logs: - Security - System - Application - Microsoft-Windows-PowerShell/Operational - Microsoft-Windows-Sysmon/Operational watch_paths: - C:\Windows\System32\drivers\etc\hosts - C:\inetpub\wwwroot\web.config baseline_file: C:\ProgramData\tcsiem\agent\fim_baseline.json collect_interval: 30 fim_interval: 300 heartbeat_interval: 60 "@ | Set-Content -Encoding UTF8 "C:\ProgramData\tcsiem\agent\agent.yaml" -
Install as a Windows Service with NSSM
# Install NSSM (the "Non-Sucking Service Manager") via Chocolatey or download from nssm.cc choco install nssm -y nssm install TCSIEMAgent "C:\Program Files\tcsiem\venv\Scripts\python.exe" "C:\Program Files\tcsiem\run_agent.py" nssm set TCSIEMAgent AppEnvironmentExtra "TCSIEM_CONFIG=C:\ProgramData\tcsiem\agent\agent.yaml" nssm set TCSIEMAgent AppStdout "C:\ProgramData\tcsiem\agent\logs\agent.log" nssm set TCSIEMAgent AppStderr "C:\ProgramData\tcsiem\agent\logs\agent.err" nssm set TCSIEMAgent Start SERVICE_AUTO_START nssm start TCSIEMAgentThe service runs as
LocalSystemby default — which is what you want, since Windows Event Log access requires SYSTEM privileges. -
Verify
Get-Service TCSIEMAgent Get-Content "C:\ProgramData\tcsiem\agent\logs\agent.log" -Tail 20 -Wait
Microsoft-Windows-Sysmon/Operational to the windows_event_logs list in agent.yaml. The agent will stream every Sysmon event (process create, network connect, file hash, etc.) into the SIEM server where your detection rules run.Verify the connection
On the server, tail the ingest log. Each enrolled agent heartbeats within 60 seconds regardless of OS:
journalctl -u tcsiem-server -f | grep heartbeat
Or query the admin API:
curl -sS https://<server-host>:8403/admin/agents \
-H "X-Admin-Token: $TCSIEM_ADMIN_TOKEN" \
--cacert /etc/tcsiem/pki/ca.crt | jq
Every enrolled agent shows up with its platform field set to linux, darwin, or win32 along with last-seen timestamp.
Detection rules
Rules live in /etc/tcsiem/rules/*.yaml on the server. Ships with 52 built-in rules across five categories:
| Category | Example rules |
|---|---|
| Auth | SSH brute-force · Windows 4625 failure spike · sudo misuse · new local admin added |
| Process | Shell spawned by web daemon · reverse-shell patterns · PowerShell -EncodedCommand |
| Network | Unusual outbound · C2 IOC match (from ThreatChain feed) · DNS tunneling heuristic |
| File integrity | Change to sshd_config · new file in /etc/cron.* or Windows Run keys · binary replaced |
| Web / app | SQLi signatures · 500-rate anomaly · admin-panel hit from unknown IP |
Rules match against normalized events — the server treats a Windows 4625 (failed logon) and a Linux authentication failure as equivalent for cross-platform rules like "5+ auth failures in 60s".
Write a custom rule — put this in /etc/tcsiem/rules/my-rule.yaml on the server:
id: CUSTOM-001
name: auth failure spike
source: auth
match:
any:
- pattern: "authentication failure" # Linux / macOS syslog
- windows_event_id: 4625 # Windows failed logon
threshold:
count: 5
window_s: 60
severity: high
alert: "5+ auth failures in 60s on {host} ({platform})"
Reload without restart:
curl -X POST https://<server-host>:8403/admin/reload-rules \
-H "X-Admin-Token: $TCSIEM_ADMIN_TOKEN" --cacert /etc/tcsiem/pki/ca.crt
Dashboard
Hit https://<server-host>:8403/ in a browser. Three tabs:
- Alerts — timeline of triggered rules, sortable by severity/host/platform. Click for the raw event.
- Agents — health grid with OS icons (penguin / apple / windows), last-seen time, event-rate sparkline.
- Search — full-text search across the last 30 days of events.
Alerts
Each rule forwards to any combination of channels. Add to /etc/tcsiem/server.env:
ALERT_DISCORD_WEBHOOK=https://discord.com/api/webhooks/...
ALERT_TELEGRAM_BOT_TOKEN=123456:ABC...
ALERT_TELEGRAM_CHAT_ID=@your_channel
ALERT_WEBHOOK_URL=https://hooks.example.com/siem
[email protected]
ALERT_SMTP_PASS=app-password
[email protected]
Restart the server to pick up new channel config.
Day-2 operations
- Upgrade a Linux/macOS agent:
cd /opt/tcsiem/app && git pull && pip install -r requirements-agent.txt && systemctl restart tcsiem-agent(orlaunchctl kickstarton macOS) - Upgrade a Windows agent:
nssm stop TCSIEMAgent; cd "C:\Program Files\tcsiem"; git pull; .\venv\Scripts\pip install -r requirements-agent.txt; nssm start TCSIEMAgent - Rotate agent cert — re-run enroll with the same
agent_id. The old cert is revoked immediately. - Backup — nightly snapshot of
/var/lib/tcsiem/(SQLite DB) +/etc/tcsiem/pki/(CA). Without the CA you cannot issue new agent certs. - Log rotation — systemd handles it on Linux; on macOS use
newsyslog.d; on Windows NSSM supports rotation flags (nssm set TCSIEMAgent AppRotateFiles 1).
/etc/tcsiem/rules/process-new-privileged.yaml to exclude legitimate processes before rolling to more than a handful of hosts.Troubleshooting
| Symptom | Check | Fix |
|---|---|---|
| Agent can't connect — TLS handshake failed | Server cert SAN includes the hostname/IP agent uses | Re-issue server cert with proper subjectAltName and restart |
| Linux agent up but no events | File perms on /var/log/* | Default service runs as root — confirm systemd unit wasn't changed to a non-privileged user |
macOS agent — launchctl load refuses | System Integrity Protection | Ensure the plist is under /Library/LaunchDaemons/ not /System/...; plist permissions must be root:wheel 644 |
| Windows — service fails to start | nssm event viewer: Event Viewer → Applications and Services Logs → nssm | Usually python.exe path incorrect or pywin32 missing — re-run pip install pywin32 |
| Windows — Access denied on Event Log | Service account | NSSM default LocalSystem has required privileges; if you changed to a custom user, add it to Event Log Readers group |
| High CPU on agent | FIM scanning large dirs | Narrow watch_paths — don't watch entire filesystem roots |
| Alert spam for normal activity | Offending rule's match count | Add exclusions to the rule's except: block |
Still stuck? Contact support with relevant logs attached — journalctl -u tcsiem-server -n 200 on Linux, C:\ProgramData\tcsiem\agent\logs\agent.err on Windows, /var/log/tcsiem-agent.err on macOS.