Deploy Velociraptor on Linux: Real-Time Endpoint DFIR and Threat Hunting Guide

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Quick start (5 min)

Velociraptor lets you interrogate thousands of Linux endpoints in seconds. Instead of streaming gigabytes of raw logs to an expensive SIEM, you run targeted queries directly on target hosts. Here is how to stand up a test server and agent on a single Ubuntu 22.04 or Debian 12 machine in about five minutes.

1. Download the static binary

Velociraptor ships as a standalone Go binary with zero external shared library dependencies. Grab the latest stable release from GitHub and make it executable:

# Pull the latest release tag and download the AMD64 binary
VER=$(curl -s https://api.github.com/repos/velocidex/velociraptor/releases/latest | grep tag_name | cut -d '"' -f 4)
wget -O velociraptor "https://github.com/velocidex/velociraptor/releases/download/${VER}/velociraptor-${VER}-linux-amd64"
chmod +x velociraptor
sudo mv velociraptor /usr/local/bin/
velociraptor version

2. Generate server and client configurations

Velociraptor authenticates every component using mutual TLS and embedded cryptographic keys. Generate your configuration files with the interactive wizard:

sudo mkdir -p /etc/velociraptor
cd /etc/velociraptor
sudo velociraptor config generate -i

The wizard asks several configuration questions. Use these values for a quick local setup:

  • Operating System: Linux
  • Path for datastore: /var/lib/velociraptor (reserve at least 15 GB of disk space for artifact triage storage)
  • Frontend URL: https://127.0.0.1:8000/ (in production, supply your server’s static IP or DNS record such as https://velociraptor.internal.corp:8000/)
  • GUI Bind Port: 8889
  • GUI Username: admin

The wizard generates two files in your current directory. Keep server.config.yaml protected on the server because it holds the private CA key. Distribute client.config.yaml to every endpoint you want to monitor.

3. Create an administrator user and start the server

Create a local administrator account before spinning up the daemon:

sudo velociraptor --config /etc/velociraptor/server.config.yaml user add admin --role administrator

Enter a strong password when prompted (at least 16 characters). Next, start the frontend service in verbose mode:

sudo velociraptor --config /etc/velociraptor/server.config.yaml frontend -v

Open https://127.0.0.1:8889 in your browser. Accept the self-signed certificate warning, then sign in with your admin credentials.

4. Connect your first client endpoint

Open a second terminal window on the same machine to simulate an endpoint. Launch the agent process:

sudo velociraptor --config /etc/velociraptor/client.config.yaml client -v

Switch back to the web console and click the magnifying glass icon under Host Search. Type * into the search box. Your host appears immediately, reporting green telemetry with an active 60-second heartbeat check-in.

Deep dive

Traditional EDR platforms forward massive telemetry streams to central cloud buckets, racking up bandwidth bills. Velociraptor flips that model. It shifts computation out to the endpoint using Velociraptor Query Language (VQL). The central server dispatches compact query strings. The endpoint evaluates the request in memory, filters out noise locally, and streams back only matching records.

Architecture overview

The platform relies on three core building blocks:

  • The Frontend Server: Handles mTLS connections from agents over port 8000, manages artifact libraries, and serves the Web GUI on port 8889. A single 4-core, 8 GB RAM server can easily handle 10,000 concurrent endpoints.
  • The Client Agent: A lean background daemon. While idling, it consumes roughly 15 to 25 MB of RAM and negligible CPU. When an active hunt fires, it executes the compiled VQL query in an isolated goroutine and uploads findings.
  • Velociraptor Query Language (VQL): An expressive SQL dialect enriched with DFIR-focused plugins. VQL plugins can parse ELF headers, walk /proc, unpack raw ext4 inodes, parse journald logs, and scan process memory using YARA rules.

Querying live endpoints with VQL

You do not need the web console to run queries. The CLI lets you execute VQL directly against a live system for instant local triage. Here is how to list active listening ports alongside their parent processes:

sudo velociraptor --config /etc/velociraptor/client.config.yaml query \
  'SELECT Pid, Name, CommandLine, Laddr.IP AS LocalIP, Laddr.Port AS LocalPort FROM netstat() WHERE Status = "LISTEN"'

Velociraptor bypasses standard userland binaries like ss or lsof. Instead, the netstat() plugin reads directly from kernel pseudo-files in /proc/net/tcp and maps open sockets to active file descriptors in /proc/[pid]/fd/. If an attacker replaces /bin/netstat with a rootkit to hide a reverse shell on port 4444, Velociraptor still spots it.

Inspecting user shell activity across sessions

Attackers frequently run bash one-liners immediately after gaining an initial foothold. Rather than manually hunting through /home/*/.bash_history files across dozens of user profiles, execute the built-in Linux.Bash.History artifact:

sudo velociraptor --config /etc/velociraptor/client.config.yaml query \
  'SELECT * FROM Artifact.Linux.Bash.History()'

This query reads /etc/passwd, discovers every user’s home folder, and parses their command history with line numbers and epoch timestamps into a structured table.

Advanced usage

Once your first few agents check in reliably, you can move from ad-hoc queries to production-grade deployments and automated hunting.

Deploying persistent systemd services

Interactive shells terminate when SSH sessions drop. Production deployments require robust systemd service units.

On your server host, create /etc/systemd/system/velociraptor-server.service:

[Unit]
Description=Velociraptor DFIR Server
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/velociraptor --config /etc/velociraptor/server.config.yaml frontend
Restart=always
RestartSec=5s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target

On client endpoints, install /etc/systemd/system/velociraptor-client.service. Add cgroup resource constraints to guarantee the agent never starves production workloads during intensive scans:

[Unit]
Description=Velociraptor Endpoint Client
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/local/bin/velociraptor --config /etc/velociraptor/client.config.yaml client
Restart=always
RestartSec=10s
CPUQuota=15%
MemoryMax=300M

[Install]
WantedBy=multi-user.target

The CPUQuota=15% and MemoryMax=300M directives keep endpoint scans predictable. If a heavy regex query accidentally spikes CPU, systemd throttles it. If memory breaches 300 MB, the kernel OOM killer resets the agent safely.

sudo systemctl daemon-reload
sudo systemctl enable --now velociraptor-client.service

Writing a custom VQL artifact for persistence hunting

Linux malware routinely establishes persistence through cron schedules. Attackers drop reverse shell scripts into /etc/cron.d/ or modify user crontabs in /var/spool/cron/crontabs/.

Here is a custom artifact that scans cron files for common outbound network tools and staging scripts. Save it as /etc/velociraptor/custom_artifacts/cron_hunt.yaml:

name: Custom.Linux.CronIntegrity
description: Searches cron directories for suspicious reverse shells, downloaders, and staging commands.

sources:
  - query: |
      LET TargetFiles = SELECT OSPath, Size, Mtime
                        FROM glob(globs=["/etc/cron*/**", "/etc/crontab", "/var/spool/cron/crontabs/*"])
                        WHERE NOT IsDir AND Size < 1000000

      SELECT OSPath,
             Size,
             Mtime,
             upload(file=OSPath) AS UploadRef
      FROM TargetFiles
      WHERE read_file(filename=OSPath) =~ "(?i)(curl\s|wget\s|python3?\s+-c|bash\s+-i|sh\s+-i|nc\s+-e|/dev/tcp/)"

Notice the WHERE read_file(...) condition. It inspects the actual file body for suspicious command patterns like /dev/tcp/ or curl. When an endpoint matches, upload(file=OSPath) automatically pushes a copy of the suspicious cron file back to your server’s forensic vault.

Load your new artifact into the server:

sudo velociraptor --config /etc/velociraptor/server.config.yaml artifacts load /etc/velociraptor/custom_artifacts/cron_hunt.yaml

Running a fleet-wide threat hunt

Deploying a hunt takes four clicks. From the Web GUI, navigate to Hunt Manager and click the + (New Hunt) button. Select Custom.Linux.CronIntegrity from the artifact list. Set a client rate limit (for example, 50 hosts per second) and an expiry window of 24 hours, then click Launch.

Velociraptor fans out the task over persistent gRPC channels. Across a fleet of 5,000 servers, initial results usually arrive in under 30 seconds. Matched files appear in the server vault ready for hash lookup or reverse engineering.

Practical tips

Hardening your forensic pipeline is essential. Because Velociraptor agents execute code as root, your server is a high-value target for attackers looking to pivot.

1. Lock down the management console

The Web GUI operates on port 8889. Leaving this port exposed to the open internet invites credential brute-force attacks. Keep GUI.bind_address set to 127.0.0.1 inside server.config.yaml. Access the dashboard through an encrypted SSH tunnel from your workstation:

# Forward remote port 8889 to your local machine
ssh -N -L 8889:127.0.0.1:8889 [email protected]

Open https://127.0.0.1:8889 in your local browser. External port scans will show port 8889 as closed or filtered.

2. Configure Let’s Encrypt certificates for the frontend

While self-signed certificates work for initial testing, production agents communicate much more reliably with trusted certificates. Velociraptor includes a built-in ACME client. Point your public DNS A-record to your server, open TCP port 80 temporarily for HTTP-01 challenges, and edit /etc/velociraptor/server.config.yaml:

Frontend:
  hostname: velociraptor.security.example.com
  certificate_provider: letsencrypt
  acme_email: [email protected]

3. Throttle network bandwidth during large collections

Capturing live memory images with LiME or pulling disk partition timelines creates sudden network spikes. If 40 servers simultaneously upload 16 GB RAM dumps, you will saturate 1 Gbps uplinks and disrupt business traffic. Throttle uploads directly in your VQL collection arguments:

# Limit data transfer rate to 5 MB/s (5,000,000 bytes/sec) per host
sudo velociraptor --config /etc/velociraptor/client.config.yaml collect Linux.Memory.Lime \
  --args max_bandwidth=5000000

4. Build proactive baseline hunts

Never wait for a high-severity alert to run your first queries. Schedule recurring weekly baseline hunts to capture fleet snapshots during quiet hours:

  • SUID and SGID binaries: Run Linux.Search.Suid to detect rogue root-owned binaries with the setuid bit enabled (chmod u+s).
  • Kernel modules: Run Linux.Sys.KernelModules to identify untracked rootkits or hidden drivers.
  • Listening network services: Compare active TCP/UDP ports against your CMDB inventory to spot unauthorized shadow services.

Having baseline data from last Tuesday turns a chaotic three-day incident triage into a five-minute diff analysis.

Share: