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

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:

CapabilityLinuxmacOSWindows
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.

  1. Install packages
    apt-get update
    apt-get install -y python3 python3-venv python3-pip openssl git
  2. 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
  3. 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
  4. 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/tcsiem
    Save the admin token. It's the only credential that issues agent certs and reaches admin endpoints. Lose it, regenerate and re-enroll every agent.
  5. 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)

  1. 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
  2. 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
  3. Write /etc/tcsiem/agent/agent.yaml
    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/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
  4. 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)

  1. 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
  2. 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
  3. 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
  4. 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
Note: YARA memory scanning is Linux-only (relies on /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.

  1. 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
  2. Unpack the cert bundle
    Copy agent-bundle.json to C:\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"
  3. 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"
  4. 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 TCSIEMAgent

    The service runs as LocalSystem by default — which is what you want, since Windows Event Log access requires SYSTEM privileges.

  5. Verify
    Get-Service TCSIEMAgent
    Get-Content "C:\ProgramData\tcsiem\agent\logs\agent.log" -Tail 20 -Wait
Works with Sysmon: If Sysmon is installed, add 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.
YARA memory scanning and systemd journal don't run on Windows. Everything else — syslog/Event Log tailing, FIM, process monitor, mTLS transport, heartbeat — works identically to Linux.

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:

CategoryExample rules
AuthSSH brute-force · Windows 4625 failure spike · sudo misuse · new local admin added
ProcessShell spawned by web daemon · reverse-shell patterns · PowerShell -EncodedCommand
NetworkUnusual outbound · C2 IOC match (from ThreatChain feed) · DNS tunneling heuristic
File integrityChange to sshd_config · new file in /etc/cron.* or Windows Run keys · binary replaced
Web / appSQLi 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

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

Tune before prod. Default rules alert on every new root/SYSTEM process, including normal kworker / cron / Windows service spawns. Edit /etc/tcsiem/rules/process-new-privileged.yaml to exclude legitimate processes before rolling to more than a handful of hosts.

Troubleshooting

SymptomCheckFix
Agent can't connect — TLS handshake failedServer cert SAN includes the hostname/IP agent usesRe-issue server cert with proper subjectAltName and restart
Linux agent up but no eventsFile perms on /var/log/*Default service runs as root — confirm systemd unit wasn't changed to a non-privileged user
macOS agent — launchctl load refusesSystem Integrity ProtectionEnsure the plist is under /Library/LaunchDaemons/ not /System/...; plist permissions must be root:wheel 644
Windows — service fails to startnssm event viewer: Event Viewer → Applications and Services Logs → nssmUsually python.exe path incorrect or pywin32 missing — re-run pip install pywin32
Windows — Access denied on Event LogService accountNSSM default LocalSystem has required privileges; if you changed to a custom user, add it to Event Log Readers group
High CPU on agentFIM scanning large dirsNarrow watch_paths — don't watch entire filesystem roots
Alert spam for normal activityOffending rule's match countAdd 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.