Skip to content

Instantly share code, notes, and snippets.

@MaxySpark
Last active March 2, 2026 09:45
Show Gist options
  • Select an option

  • Save MaxySpark/79196ff9b39a84c9dff1198ea142fa9d to your computer and use it in GitHub Desktop.

Select an option

Save MaxySpark/79196ff9b39a84c9dff1198ea142fa9d to your computer and use it in GitHub Desktop.
ClamAV 1.5.1 - Developer Workstation Setup (Linux x86_64)
[Unit]
Description=ClamAV Antivirus Daemon
Documentation=man:clamd(8)
After=network-online.target
Wants=network-online.target
After=clamav-freshclam.service
[Service]
Type=forking
ExecStartPre=/bin/mkdir -p /run/clamav
ExecStartPre=/bin/chown clamav:clamav /run/clamav
ExecStart=/usr/local/sbin/clamd
PIDFile=/run/clamav/clamd.pid
Restart=on-failure
RestartSec=10
Nice=19
IOSchedulingClass=idle
IOSchedulingPriority=7
CPUSchedulingPolicy=idle
MemoryMax=1G
[Install]
WantedBy=multi-user.target
[Unit]
Description=ClamAV Virus Database Updater
Documentation=man:freshclam(1)
After=network-online.target
Wants=network-online.target
[Service]
Type=forking
ExecStartPre=/bin/mkdir -p /run/clamav
ExecStartPre=/bin/chown clamav:clamav /run/clamav
ExecStart=/usr/local/bin/freshclam --daemon
PIDFile=/run/clamav/freshclam.pid
Restart=on-failure
RestartSec=30
Nice=19
IOSchedulingClass=idle
IOSchedulingPriority=7
[Install]
WantedBy=multi-user.target
# clamd.conf - ClamAV daemon config (developer workstation optimized)
# --- Logging ---
LogFile /var/log/clamav/clamd.log
LogFileMaxSize 5M
LogTime yes
LogRotate yes
ExtendedDetectionInfo yes
# --- Identity ---
PidFile /run/clamav/clamd.pid
DatabaseDirectory /var/lib/clamav
User clamav
Foreground no
# --- Socket (local only, no TCP exposure) ---
LocalSocket /run/clamav/clamd.sock
LocalSocketMode 666
FixStaleSocket yes
# --- Performance (tuned for dev workstation - stay quiet) ---
# Keep threads low so clamd doesn't compete with your IDE/compiler
MaxThreads 4
MaxConnectionQueueLength 30
ReadTimeout 120
CommandReadTimeout 30
IdleTimeout 60
MaxQueue 50
# Non-blocking DB reload so scans aren't interrupted
ConcurrentDatabaseReload yes
# Check DB freshness every 10 min
SelfCheck 600
# --- Scan targets ---
ScanPE yes
ScanELF yes
ScanOLE2 yes
ScanPDF yes
ScanSWF yes
ScanXMLDOCS yes
ScanHWP3 yes
ScanOneNote yes
ScanMail yes
ScanHTML yes
ScanArchive yes
ScanImage yes
ScanImageFuzzyHash yes
Bytecode yes
BytecodeSecurity TrustSigned
# --- Detection ---
HeuristicAlerts yes
HeuristicScanPrecedence yes
PhishingSignatures yes
PhishingScanURLs yes
# --- Limits (reasonable for workstation) ---
MaxScanTime 120000
MaxScanSize 200M
MaxFileSize 100M
MaxRecursion 17
MaxFiles 10000
# --- Exclude developer directories (major perf win) ---
# VCS
ExcludePath ^/home/.*/\.git/
ExcludePath ^/home/.*/\.svn/
ExcludePath ^/home/.*/\.hg/
# Package managers / dependencies
ExcludePath ^/home/.*/node_modules/
ExcludePath ^/home/.*/\.npm/
ExcludePath ^/home/.*/\.yarn/
ExcludePath ^/home/.*/\.pnpm-store/
ExcludePath ^/home/.*/vendor/
ExcludePath ^/home/.*/\.cargo/registry/
ExcludePath ^/home/.*/\.rustup/
ExcludePath ^/home/.*/\.gradle/
ExcludePath ^/home/.*/\.m2/
ExcludePath ^/home/.*/go/pkg/
ExcludePath ^/home/.*/\.cache/pip/
ExcludePath ^/home/.*/\.local/lib/
# Python virtualenvs
ExcludePath ^/home/.*/\.venv/
ExcludePath ^/home/.*/venv/
ExcludePath ^/home/.*/env/
ExcludePath ^/home/.*/__pycache__/
ExcludePath ^/home/.*/\.pyenv/
ExcludePath ^/home/.*/\.conda/
# Build artifacts
ExcludePath ^/home/.*/target/
ExcludePath ^/home/.*/dist/
ExcludePath ^/home/.*/build/
ExcludePath ^/home/.*/\.next/
ExcludePath ^/home/.*/\.nuxt/
# Containers & VMs
ExcludePath ^/home/.*/\.docker/
ExcludePath ^/home/.*/\.vagrant/
# IDE / Editor
ExcludePath ^/home/.*/\.vscode/
ExcludePath ^/home/.*/\.idea/
ExcludePath ^/home/.*/\.cursor/
# System virtual filesystems
ExcludePath ^/proc/
ExcludePath ^/sys/
ExcludePath ^/dev/
ExcludePath ^/run/
ExcludePath ^/snap/
# --- NO on-access scanning (kills dev performance) ---
# Use on-demand scans instead
#!/bin/bash
# On-demand scan of home directory using clamd daemon (fast)
# Usage: clamscan-home [path] (defaults to $HOME)
TARGET="${1:-$HOME}"
if ! pgrep -x clamd > /dev/null 2>&1; then
echo "clamd is not running. Starting it..."
sudo systemctl start clamav-daemon
sleep 3
fi
echo "Scanning: $TARGET"
echo "Using clamd daemon (fast mode). Results logged to /var/log/clamav/scan-$(date +%Y%m%d).log"
echo "---"
clamdscan --multiscan --fdpass "$TARGET" 2>&1 | tee "/var/log/clamav/scan-$(date +%Y%m%d).log"
# freshclam.conf - ClamAV database updater config
DatabaseDirectory /var/lib/clamav
UpdateLogFile /var/log/clamav/freshclam.log
LogFileMaxSize 5M
LogTime yes
LogRotate yes
PidFile /run/clamav/freshclam.pid
DatabaseOwner clamav
DatabaseMirror database.clamav.net
# 6 checks/day (every 4 hours) - enough for a dev workstation
Checks 6
ConnectTimeout 30
ReceiveTimeout 300
TestDatabases yes
Bytecode yes
CompressLocalDatabase no
ScriptedUpdates yes
MaxAttempts 3
# Notify clamd to reload after update
NotifyClamd /usr/local/etc/clamd.conf
#!/bin/bash
# =============================================================================
# ClamAV 1.5.1 - Install & Configure for Developer Workstations (Linux x86_64)
# =============================================================================
#
# INSTALL (one-liner):
# curl -fsSL https://gist.githubusercontent.com/raw/79196ff9b39a84c9dff1198ea142fa9d/setup-clamav.sh | sudo bash
#
# WHAT THIS DOES:
# 1. Downloads & installs ClamAV 1.5.1 .deb from clamav.net
# 2. Creates clamav system user/group and required directories
# 3. Pulls config files from this gist (clamd, freshclam, systemd units)
# 4. Downloads virus signature databases via freshclam
# 5. Enables & starts clamd + freshclam systemd services
# 6. Installs 'clamscan-home' helper script to /usr/local/bin
#
# REQUIREMENTS:
# - Debian/Ubuntu-based Linux (x86_64)
# - Root/sudo access
# - curl
#
# AFTER INSTALL - SCANNING:
# clamdscan <file> Scan a single file (uses clamd daemon, fast)
# clamdscan -m <directory> Scan a directory with multithreading
# clamscan-home Scan entire $HOME (skips dev dirs)
# clamscan-home /path/to/dir Scan a specific directory
#
# AFTER INSTALL - SERVICE MANAGEMENT:
# sudo systemctl status clamav-daemon Check clamd status
# sudo systemctl status clamav-freshclam Check db updater status
# sudo systemctl restart clamav-daemon Restart the scan daemon
# sudo systemctl stop clamav-daemon Stop the scan daemon
#
# AFTER INSTALL - LOGS:
# /var/log/clamav/clamd.log Daemon log
# /var/log/clamav/freshclam.log DB update log
#
# AFTER INSTALL - CONFIGS (edit to customize):
# /usr/local/etc/clamd.conf Daemon config (threads, limits, excludes)
# /usr/local/etc/freshclam.conf DB updater config (mirrors, frequency)
#
# DEVELOPER OPTIMIZATIONS:
# - clamd runs at idle CPU/IO priority (Nice=19, CPUSchedulingPolicy=idle)
# - Memory hard-capped at 1GB via systemd MemoryMax
# - Only 4 scan threads (won't starve builds/IDE on multi-core machines)
# - NO on-access scanning (all scans are on-demand only)
# - DB updates every 4 hours (not the default 2)
# - Excludes: node_modules, .git, .svn, venv, __pycache__, .cargo,
# .rustup, .gradle, .m2, go/pkg, target/, dist/, build/, .next/,
# .nuxt/, .docker, .vagrant, .vscode, .idea, .cursor, /proc, /sys
#
# UNINSTALL:
# sudo systemctl stop clamav-daemon clamav-freshclam
# sudo systemctl disable clamav-daemon clamav-freshclam
# sudo rm /etc/systemd/system/clamav-daemon.service
# sudo rm /etc/systemd/system/clamav-freshclam.service
# sudo rm /usr/local/etc/clamd.conf /usr/local/etc/freshclam.conf
# sudo rm /usr/local/bin/clamscan-home
# sudo rm -rf /var/lib/clamav /var/log/clamav /run/clamav
# sudo dpkg -r clamav # or: sudo dpkg -P clamav
# sudo userdel clamav && sudo groupdel clamav
# sudo systemctl daemon-reload
#
# =============================================================================
set -euo pipefail
CLAMAV_VERSION="1.5.1"
DEB_URL="https://www.clamav.net/downloads/production/clamav-${CLAMAV_VERSION}.linux.x86_64.deb"
GIST_ID="79196ff9b39a84c9dff1198ea142fa9d"
GIST_RAW="https://gist.githubusercontent.com/raw/${GIST_ID}"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[!!]${NC} $1"; }
fail() { echo -e "${RED}[FAIL]${NC} $1"; exit 1; }
step() { echo -e "\n${YELLOW}==>${NC} $1"; }
if [[ $EUID -ne 0 ]]; then
fail "This script must be run as root (use sudo)"
fi
echo ""
echo "==========================================="
echo " ClamAV ${CLAMAV_VERSION} Developer Setup"
echo "==========================================="
echo ""
# --- Step 1: Download & install the .deb ---
step "Installing ClamAV ${CLAMAV_VERSION}..."
if command -v clamscan &>/dev/null; then
INSTALLED_VER=$(clamscan --version 2>/dev/null | head -1 | grep -oP '[\d.]+' | head -1)
if [[ "$INSTALLED_VER" == "$CLAMAV_VERSION" ]]; then
info "ClamAV ${CLAMAV_VERSION} already installed, skipping download"
else
warn "ClamAV ${INSTALLED_VER} found, upgrading to ${CLAMAV_VERSION}"
DEB_FILE="/tmp/clamav-${CLAMAV_VERSION}.deb"
curl -fSL -o "$DEB_FILE" "$DEB_URL"
dpkg -i "$DEB_FILE" || apt-get install -f -y
rm -f "$DEB_FILE"
info "ClamAV ${CLAMAV_VERSION} installed"
fi
else
DEB_FILE="/tmp/clamav-${CLAMAV_VERSION}.deb"
curl -fSL -o "$DEB_FILE" "$DEB_URL"
dpkg -i "$DEB_FILE" || apt-get install -f -y
rm -f "$DEB_FILE"
info "ClamAV ${CLAMAV_VERSION} installed"
fi
# --- Step 2: Create clamav user/group ---
step "Setting up clamav user and directories..."
if ! id clamav &>/dev/null; then
groupadd -r clamav 2>/dev/null || true
useradd -r -g clamav -s /usr/sbin/nologin -d /var/lib/clamav -c "ClamAV" clamav
info "Created clamav user"
else
info "clamav user already exists"
fi
mkdir -p /var/lib/clamav /var/log/clamav /run/clamav
chown clamav:clamav /var/lib/clamav /var/log/clamav /run/clamav
chmod 750 /var/lib/clamav /var/log/clamav
info "Directories ready"
# --- Step 3: Download config files from gist ---
step "Downloading config files..."
download_gist_file() {
local filename="$1"
local dest="$2"
local url="${GIST_RAW}/${filename}"
if curl -fsSL -o "$dest" "$url"; then
info "Installed ${filename} -> ${dest}"
else
fail "Failed to download ${filename} from gist"
fi
}
download_gist_file "clamd.conf" /usr/local/etc/clamd.conf
download_gist_file "freshclam.conf" /usr/local/etc/freshclam.conf
download_gist_file "clamav-daemon.service" /etc/systemd/system/clamav-daemon.service
download_gist_file "clamav-freshclam.service" /etc/systemd/system/clamav-freshclam.service
download_gist_file "clamscan-home" /usr/local/bin/clamscan-home
chmod +x /usr/local/bin/clamscan-home
# --- Step 4: Download virus databases ---
step "Downloading virus databases (this takes a few minutes)..."
if [[ -f /var/lib/clamav/main.cvd || -f /var/lib/clamav/main.cld ]]; then
info "Virus databases already present, running update"
fi
freshclam --config-file=/usr/local/etc/freshclam.conf && \
info "Virus databases ready" || \
warn "freshclam had warnings (may still work - check /var/log/clamav/freshclam.log)"
# --- Step 5: Enable & start services ---
step "Configuring systemd services..."
systemctl daemon-reload
systemctl stop clamav-daemon 2>/dev/null || true
systemctl stop clamav-freshclam 2>/dev/null || true
systemctl enable clamav-freshclam.service
systemctl enable clamav-daemon.service
systemctl start clamav-freshclam.service
info "freshclam daemon started"
sleep 2
systemctl start clamav-daemon.service
info "clamd daemon started"
# --- Step 6: Verify ---
step "Verifying installation..."
sleep 3
if systemctl is-active --quiet clamav-daemon; then
info "clamd is running"
else
warn "clamd may still be loading databases (can take ~30s on first boot)"
warn "Check with: systemctl status clamav-daemon"
fi
if systemctl is-active --quiet clamav-freshclam; then
info "freshclam is running"
else
warn "freshclam status unknown - check: systemctl status clamav-freshclam"
fi
echo ""
echo "==========================================="
echo " Setup Complete!"
echo "==========================================="
echo ""
echo " Quick commands:"
echo " clamdscan <file> Scan a file (fast, uses daemon)"
echo " clamdscan -m <dir> Scan directory (multithreaded)"
echo " clamscan-home Full home directory scan"
echo " clamscan-home /path Scan specific path"
echo ""
echo " Service management:"
echo " sudo systemctl status clamav-daemon"
echo " sudo systemctl status clamav-freshclam"
echo " sudo systemctl restart clamav-daemon"
echo ""
echo " Logs:"
echo " /var/log/clamav/clamd.log"
echo " /var/log/clamav/freshclam.log"
echo ""
echo " Config files:"
echo " /usr/local/etc/clamd.conf"
echo " /usr/local/etc/freshclam.conf"
echo ""
echo " Performance: idle priority, 4 threads, 1GB cap, no on-access scan"
echo " Excluded: node_modules, .git, venvs, build/, dist/, cargo, etc."
echo ""
@MaxySpark
Copy link
Author

MaxySpark commented Mar 2, 2026

ClamAV 1.5.1 — Developer Workstation Setup (Linux x86_64)

Quick Install

curl -fsSL https://gist.githubusercontent.com/raw/79196ff9b39a84c9dff1198ea142fa9d/setup-clamav.sh | sudo bash

What It Does

Step Action
1 Downloads & installs ClamAV 1.5.1 .deb from clamav.net
2 Creates clamav system user/group and directories
3 Pulls all config files from this gist
4 Downloads virus signature databases via freshclam
5 Enables & starts clamd + freshclam systemd services
6 Installs clamscan-home helper to /usr/local/bin

Requirements

  • Debian/Ubuntu-based Linux (x86_64)
  • Root / sudo access
  • curl

Usage

Scanning:

clamdscan # Scan a single file (fast, uses daemon)
clamdscan -m # Scan a directory (multithreaded)
clamscan-home # Scan entire $HOME (skips dev dirs)
clamscan-home /path/to/dir # Scan a specific directory

Service management:

sudo systemctl status clamav-daemon # Check daemon status
sudo systemctl status clamav-freshclam # Check db updater status
sudo systemctl restart clamav-daemon # Restart daemon
sudo systemctl stop clamav-daemon # Stop daemon

Files Installed

File Location
Daemon config /usr/local/etc/clamd.conf
Updater config /usr/local/etc/freshclam.conf
Daemon service /etc/systemd/system/clamav-daemon.service
Updater service /etc/systemd/system/clamav-freshclam.service
Scan helper /usr/local/bin/clamscan-home
Virus databases /var/lib/clamav/
Daemon log /var/log/clamav/clamd.log
Updater log /var/log/clamav/freshclam.log

Developer Optimizations

  • Idle CPU/IO priorityNice=19, CPUSchedulingPolicy=idle, IOSchedulingClass=idle
  • Memory capped at 1GB — via systemd MemoryMax
  • 4 scan threads only — won't starve builds, IDE, or compilers
  • No on-access scanning — all scans are on-demand only
  • DB updates every 4 hours — instead of default every 2 hours

Excluded Directories

These are skipped during scans to avoid wasting time on dependencies, build artifacts, and toolchains.
| Category | Paths |
|----------|-------|
| VCS | .git/, .svn/, .hg/ |
| JS/Node | node_modules/, .npm/, .yarn/, .pnpm-store/ |
| Python | .venv/, venv/, env/, __pycache__/, .pyenv/, .conda/, .cache/pip/ |
| Rust | .cargo/registry/, .rustup/ |
| Java/JVM | .gradle/, .m2/ |
| Go | go/pkg/ |
| PHP | vendor/ |
| Build output | target/, dist/, build/, .next/, .nuxt/ |
| Containers | .docker/, .vagrant/ |
| IDEs | .vscode/, .idea/, .cursor/ |
| System | /proc/, /sys/, /dev/, /run/, /snap/ |

Uninstall

sudo systemctl stop clamav-daemon clamav-freshclam
sudo systemctl disable clamav-daemon clamav-freshclam
sudo rm /etc/systemd/system/clamav-daemon.service
sudo rm /etc/systemd/system/clamav-freshclam.service
sudo rm /usr/local/etc/clamd.conf /usr/local/etc/freshclam.conf
sudo rm /usr/local/bin/clamscan-home
sudo rm -rf /var/lib/clamav /var/log/clamav /run/clamav
sudo dpkg -r clamav
sudo userdel clamav && sudo groupdel clamav
sudo systemctl daemon-reload

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment