Linux Server Security Tooling

Harden your server.
In minutes, not hours.

linux-security is an open-source toolkit of bash scripts for hardening Ubuntu and Debian servers. Two profiles: baseline (any server) and web-server (Apache addendum). One config file, one command — from bare server to verified security baseline.

⚠️ Test before you deploy. These scripts modify firewall rules, SSH configuration, kernel parameters, and other system-level settings. Always validate in a staging or development environment before applying to production servers. Review each script and understand what it does before running it as root. Every script supports --dry-run — use it first.
System-wide install (recommended)
curl -fsSL https://raw.githubusercontent.com/davidwhittington/linux-security/main/install.sh | bash
nano /etc/linux-security/config.env
linux-security-bootstrap --profile baseline
Installs to /opt/linux-security/ · config in /etc/linux-security/ · Run as root
Ubuntu 22.04/24.04 LTS · Debian 12 · Every script supports --dry-run

What it hardens

Run bash bootstrap.sh and get a fully hardened server covering every major security control area.

🔥

Firewall

UFW default-deny ingress, SSH/HTTP/HTTPS allowlist, connection rate limiting on ports 80 and 443.

🔑

SSH Hardening

Password auth off, modern ciphers only (AES-GCM, ChaCha20), HMAC-SHA2/ETM MACs, Curve25519 key exchange. MaxAuthTries 3.

🚫

Fail2ban

SSH + Apache jails: apache-auth, apache-badbots (1-strike, 24h ban), apache-noscript. Configurable via config.env.

🌐

Apache Hardening

ServerTokens Prod, HSTS, CSP, X-Content-Type-Options, Referrer-Policy. TRACE off, mod_status off, .git access blocked.

📊

Monitoring

Logwatch daily HTML email digest. GoAccess daily traffic report. Monthly apt upgrade + disk + fail2ban report via msmtp.

🔏

Certificate Alerts

Weekly certbot expiry monitor, independent of the monthly report. Fires when any cert is within 30 days of expiry.

🛡️

Malware Defense

ClamAV weekly web-root scan with quarantine. rkhunter rootkit scanner with clean baseline. ModSecurity + OWASP CRS.

⚙️

Kernel Hardening

sysctl: ICMP redirects off, martian logging, IP forwarding off, TCP SYN cookies, reverse path filtering enabled.

🔍

Audit Tools

9 read-only posture scripts with color-coded PASS/WARN/FAIL. Ports, SSH config, headers, AppArmor, SUID drift, and more.

↩️

Rollback

Every script backs up files before modifying. rollback.sh restores .bak files per-script or all at once.

Scripts

Scripts are split into two layers. All support --dry-run.

scripts/core/hardening/ — baseline profile (any server)
01-immediate-hardening.sh UFW firewall, fail2ban SSH jail, SSH hardening, sysctl kernel params
02-setup-admin-user.sh Promote existing user to sudo, propagate SSH keys from root
03-monthly-updates-setup.sh msmtp relay, monthly apt upgrade report and cron job
04-rkhunter-setup.sh Rootkit scanner with clean-system property baseline
05-auditd-setup.sh CIS Benchmark-aligned kernel audit ruleset via auditd
06-fail2ban-recidive.sh Recidive jail: 1-week ban after 5 bans in 12h; SSH login email alerts
07-aide-setup.sh AIDE file integrity monitoring on critical system paths; weekly scan with email alert
08-disk-alert-setup.sh Daily disk and inode usage check; emails on threshold breach (default 80%)
scripts/web/hardening/ — web-server profile addendum (Apache)
01-apache-hardening.sh Security headers, ServerTokens Prod, disable TRACE and mod_status, block .git access
02-log-monitoring-setup.sh Logwatch daily digest, GoAccess traffic report (password-protected)
03-cert-monitor-setup.sh Weekly TLS certificate expiry alerts — configurable threshold (default 30 days)
04-clamav-setup.sh ClamAV weekly web-root scan with quarantine and email alert on detection
05-modsecurity-setup.sh ModSecurity + OWASP CRS in DetectionOnly mode by default
06-vhost-hardener.sh Options -Indexes, AllowOverride None, deny dotfiles and env files across all web roots
07-apache-tls-hardening.sh TLS 1.2+ only, ECDHE/DHE ciphers, OCSP stapling, no session tickets
08-apache-dos-mitigation.sh mod_reqtimeout (Slowloris) + mod_evasive (HTTP flood) with tuned defaults
09-php-hardening.sh PHP security baseline: expose_php=Off, disable dangerous functions, secure session cookies
10-mysql-hardening.sh Remove anonymous users, restrict remote root, bind 127.0.0.1, local-infile=0
scripts/audit/ — profile-aware dispatcher + standalone checks
audit.sh --profile baseline Firewall, SSH, fail2ban, system updates — color-coded PASS/WARN/FAIL; --json and --report html available
audit.sh --profile web-server Full posture audit including Apache headers, TLS certificate expiry (default)
core/audit/ssh-audit.sh sshd configuration — flags weak ciphers, MACs, KexAlgorithms
core/audit/suid-check.sh SUID/SGID binary baseline and filesystem drift detection
web/audit/headers-check.sh Security header validator across all active Apache vhosts
web/audit/web-root-perms.sh Web root permission scanner — world-writable, unexpected ownership, webshell patterns

Quick start

From a fresh Ubuntu 24.04 or Debian 12 server to a verified security baseline.

Option A — system-wide install

# 1. Install on the server (run as root)
curl -fsSL https://raw.githubusercontent.com/davidwhittington/linux-security/main/install.sh | bash

# 2. Fill in your config — email, SSH port, SMTP relay
nano /etc/linux-security/config.env

# 3. Run bootstrap (baseline = any server; web-server = +Apache/PHP/MySQL)
linux-security-bootstrap --profile baseline --dry-run   # preview first
linux-security-bootstrap --profile baseline              # apply

# 4. Run the full posture audit
linux-security-audit --profile baseline

Option B — clone and run

# 1. Clone the repo
git clone https://github.com/davidwhittington/linux-security.git
cd linux-security

# 2. Fill in your config
cp config.env.example config.env
nano config.env

# 3. Bootstrap and audit
bash bootstrap.sh --profile baseline --dry-run
bash bootstrap.sh --profile baseline
bash scripts/audit/audit.sh --profile baseline

Pass --dry-run to preview every change before anything touches the system.

Docs

Reference documentation for configuration, operations, and architecture.

Customization Guide

Every config.env variable explained. SMTP provider table, CSP examples, per-server config.env.local override pattern.

Runbook

Operational playbook — cert renewal, SSH key rotation, fail2ban unbanning, disk alerts, rollback, and adding domains.

Architecture

Config discovery chain, script execution order, bootstrap orchestration, audit exit codes, and the public/private submodule split.

Security Baseline

Minimum security requirements, fail2ban config blocks, verification commands, and recommended audit cadence.

Changelog

Full version history following Keep a Changelog v1.0.0. Every script addition, change, and fix documented.

Private data, public tools

Audit reports, server inventories, and per-server config files contain real IPs and hostnames that shouldn't live in a public repo. linux-security uses a git submodule pattern to keep the tooling public and the server data private:

# Public repo — hardening scripts, audit tools, docs
linux-security/
  scripts/core/hardening/
  scripts/web/hardening/
  scripts/core/audit/
  scripts/web/audit/
  profiles/
  bootstrap.sh
  config.env

# Private submodule — your own private repo
linux-security/private/
  servers/server1.example.com/
    config.env.local
    AUDIT_REPORT.md
  servers/inventory.yml

Clone the repo, initialize the private submodule pointing at your own private GitHub repo, and your server inventory and audit history stay yours.