Malware Scanning with Maldet and ClamAV
Install and configure Linux Malware Detect (maldet) with ClamAV on your VPS. Covers scanning, quarantine, real-time monitoring, and automated daily scans.
6 min read
Linux Malware Detect (maldet) finds PHP backdoors, web shells, spam injectors, and other malware that targets web-facing servers. It was built for shared hosting but works the same way on a VPS. ClamAV adds signature-based scanning on top of maldet’s pattern matching, so install both.
On GoZen Host shared or WordPress hosting, server-level malware scanning (Imunify360 or cPGuard, depending on the server) runs automatically. This guide is for VPS and cloud server customers who manage their own security stack.
Prerequisites
- A GoZen Host VPS or cloud server with root access
- Ubuntu 22.04/24.04, Debian 12, Rocky Linux 9, or AlmaLinux 9
- Basic familiarity with the command line (Essential Linux Commands)
Install ClamAV
Install ClamAV first. Maldet uses it as a scanning engine when available. Without ClamAV, scans are slower and catch less.
Update the virus definitions:
sudo systemctl stop clamav-freshclam # stop the daemon so we can update manually
sudo freshclam # download latest signatures
sudo systemctl start clamav-freshclam # restart automatic updates
Verify ClamAV is working:
clamscan --version
# Expected: ClamAV 1.x.x/27xxx/...
Install Maldet
Maldet installs from source. There’s no distro package.
cd /tmp
wget https://www.rfxn.com/downloads/maldetect-current.tar.gz
tar -xzf maldetect-current.tar.gz
cd maldetect-*
sudo sh install.sh
The installer:
- Puts maldet at
/usr/local/maldetect/ - Creates a symlink at
/usr/local/sbin/maldet - Adds a daily cron job at
/etc/cron.daily/maldet - On systemd servers, installs and enables
maldet.servicefor real-time monitoring
Verify the install:
maldet --version
Configure Maldet
Edit the main configuration file:
sudo nano /usr/local/maldetect/conf.maldet
Change these from the defaults:
# Email alerts when malware is found
email_alert="1"
email_addr="[email protected]"
# Quarantine malware hits automatically
quarantine_hits="1"
# Try to clean detected malware (remove injected code)
quarantine_clean="1"
# Suspend the cPanel user who owns the infected file
# Set to 0 unless you're running a shared hosting server
quarantine_suspend_user="0"
Older guides use quar_hits, quar_clean and quar_susp. Current maldet ignores those names, so use the quarantine_ ones above.
Check that these defaults are still set:
# Use ClamAV as the scan engine (much faster than maldet's built-in scanner)
scan_clamscan="1"
# Scan files up to 2MB (increase if your app has larger PHP files)
scan_max_filesize="2048k"
Save and close.
Update Malware Signatures
Always update before your first scan:
sudo maldet -u # update malware signatures
sudo maldet -d # check for maldet software updates
Set up a cron job to update signatures daily. The installer creates one at /etc/cron.daily/maldet, but verify it exists:
ls -la /etc/cron.daily/maldet
Scan Your Server
Full Directory Scan
Scan your web root or any directory:
# Scan all web files
sudo maldet -a /home/
# Scan a specific user's site
sudo maldet -a /home/username/public_html/
Scan Recently Modified Files
Only scan files changed in the last 7 days. Much faster than a full scan:
sudo maldet -r /home/ 7
Background Scan
For large directories, run the scan in the background:
sudo maldet -b -a /home/
Check progress:
ps aux | grep maldet
Read Scan Reports
After a scan completes, maldet shows a scan ID. Use it to view the full report:
# List all scan reports
sudo maldet --report list
# View a specific report
sudo maldet --report SCAN-ID
A report shows:
- Total files scanned
- Total hits (malware found)
- File paths of infected files
- Malware signatures matched
- Quarantine status
Manage Quarantined Files
When quarantine_hits="1" is set, infected files are moved to /usr/local/maldetect/quarantine/. They can’t run from there.
View Quarantined Files
ls -la /usr/local/maldetect/quarantine/
Restore a False Positive
If maldet quarantined a legitimate file:
sudo maldet --restore FILENAME
Or restore all hits from a specific scan:
sudo maldet --restore SCAN-ID
Investigate before restoring. Open the file in a text editor and check for obfuscated code, base64-encoded strings, or eval() calls you didn’t write. If you’re not sure, contact support and our team will review it.
Manually Quarantine a Scan’s Hits
If you ran a scan without auto-quarantine:
sudo maldet -q SCAN-ID
Real-Time Monitoring with inotify
Maldet can watch directories in real time using inotify. Any file that’s created or modified gets scanned on the spot.
Start Monitoring
sudo maldet -m /home/
This runs as a background process. Check that it’s active:
ps aux | grep inotifywait
Stop Monitoring
sudo maldet -k
Start on Boot
The installer already adds and enables maldet.service, which starts the monitor using the default_monitor_mode setting in conf.maldet (default users, which watches users’ web folders). To watch specific paths instead, list them in /usr/local/maldetect/monitor_paths (one per line, for example /home) and set:
default_monitor_mode="/usr/local/maldetect/monitor_paths"
Then restart the service:
sudo systemctl restart maldet
sudo systemctl status maldet
Don’t create a second systemd unit for the monitor. Two monitors would fight over the same PID file.
inotify has a watch limit. If you have thousands of directories, you may need to increase it:
echo "fs.inotify.max_user_watches=524288" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Maldet vs cPGuard
GoZen shared hosting servers run Imunify360 or cPGuard. This is how maldet compares with cPGuard:
| Feature | Maldet + ClamAV | cPGuard |
|---|---|---|
| Designed for | VPS / dedicated servers | Shared hosting (cPanel) |
| Installation | Manual | Pre-installed on GoZen plans |
| Web Application Firewall | No | Yes |
| Malware scanning | Yes (signatures + heuristic) | Yes (signatures) |
| Real-time file monitoring | Yes (inotify) | Yes (on upload/modify) |
| Brute force protection | No | Yes |
| Quarantine + restore | Yes | Yes (via cPanel UI) |
| Automatic cleaning | Yes (injectable code) | Limited |
| Cost | Free / open source | Included with GoZen hosting |
On a VPS, maldet + ClamAV covers file-level malware detection. You still need Fail2Ban for brute-force blocking and a firewall for network-level filtering.
Troubleshooting
| Problem | Fix |
|---|---|
maldet: command not found | The symlink wasn’t created. Run: sudo ln -s /usr/local/maldetect/maldet /usr/local/sbin/maldet |
| Scans are extremely slow | ClamAV isn’t installed or isn’t detected. Install it and set scan_clamscan="1" in conf.maldet. |
freshclam fails with “database is locked” | Another freshclam process is running. Stop it: sudo systemctl stop clamav-freshclam, then update manually. |
| Email alerts not sending | Check that a mail service is running (postfix, exim). Verify email_alert="1" and email_addr is set in conf.maldet. |
| inotify monitoring stops after reboot | Make sure the bundled service is enabled: sudo systemctl enable --now maldet. |
| False positives on WordPress plugins | Some plugins use obfuscated code. Review the file, and if it’s legitimate, restore it with maldet --restore and consider excluding the path. |
| “inotify watch limit reached” | Increase the limit: `echo “fs.inotify.max_user_watches=524288” |
What to Do Next
- Server Hardening Basics: Fail2Ban, sysctl, and SSH hardening alongside maldet
- How to Set Up a Firewall (UFW and CSF): network-level protection
- VPS Security Checklist: the full first-boot security walkthrough
- Using cPGuard: if you’re on shared hosting, cPGuard already handles this
- Securing WordPress: application-level hardening for WordPress sites
Last updated 21 Oct 2026, 00:00 +0300.