RedPatch
Headlines refreshed Sun Oct 11, 11:45 AM ET (1 h ago) ยท content checked against vendor docs

๐Ÿง Linux security

Linux, locked down.

Linux is secure by design, but defaults differ by distro and most compromises come from things that were never turned on: patching, key-only SSH, a firewall, and logging. This guide works through those in order, starting with tips anyone can follow and ending with audit tools for sysadmins. Every check command only reads the system. Every change command is labeled separately so you can review it before running it.

44 tips ยท 16 tools ยท every one sourced

Latest Linux advisories

  1. perl-GD-SecurityImage-1.75-22.fc43Fedora security updates (Bodhi) ยท Oct 11
  2. perl-GD-SecurityImage-1.75-23.fc44Fedora security updates (Bodhi) ยท Oct 11
  3. Why TLP should not replace your internal information classification, (Sat, Oct 10th)SANS Internet Storm Center ยท Oct 10
  4. DSA-6550-1 ghostscript - security updateDebian Security Advisories (DSA) ยท Oct 9
  5. RHSA-2026:79786: Important: kernel security updateRed Hat Security Advisories (RHSA) ยท Oct 9
  6. USN-8911-1: Linux kernel (OEM) vulnerabilitiesUbuntu Security Notices (USN) ยท Oct 9

All Linux headlines โ†’

1. Patching and updates

Turn on automatic security updates (Debian/Ubuntu)

everyone

Most real-world break-ins use bugs that already had a fix. unattended-upgrades installs security fixes for you, without waiting for you to remember. Ubuntu Server ships it by default. Debian may not.

Install unattended-upgrades and enable it. By default it only pulls from the release and -security pockets. Third-party repos are ignored unless you add them to Allowed-Origins in /etc/apt/apt.conf.d/50unattended-upgrades. Results are logged under /var/log/unattended-upgrades/.

Check โ€” read-only
cat /etc/apt/apt.conf.d/20auto-upgrades; systemctl list-timers 'apt-daily*'
Changes your system
sudo apt install unattended-upgrades && sudo dpkg-reconfigure -plow unattended-upgrades

Source: Ubuntu Server docs: Automatic updates; Debian Wiki: UnattendedUpgrades

Turn on automatic updates (Fedora/RHEL with dnf5-automatic or dnf-automatic)

everyone

This does the same job as unattended-upgrades. Fedora 41+ uses DNF5, so the timer is now dnf5-automatic.timer. RHEL 9 and older Fedora still use dnf-automatic.timer.

Install the plugin. Set apply_updates = yes in /etc/dnf/automatic.conf. Set upgrade_type = security if you only want security fixes. Then enable the timer. The default only downloads updates. It does not install them.

Check โ€” read-only
systemctl list-timers '*dnf*automatic*'; grep -E '^(apply_updates|upgrade_type)' /etc/dnf/automatic.conf
Changes your system
sudo dnf install dnf5-plugin-automatic && sudo systemctl enable --now dnf5-automatic.timer   # RHEL 9: dnf install dnf-automatic && systemctl enable --now dnf-automatic.timer

Source: DNF5 docs: automatic command (dnf5-automatic.8)

See which security fixes are waiting

power user

Seeing what is pending, and how serious it is, tells you whether to patch now or at the next maintenance window.

On RHEL/Fedora, list pending security advisories and their severity. On DNF5, 'updateinfo' is an alias for 'advisory'. On Debian/Ubuntu, list upgradable packages after the daily apt refresh. Ubuntu also has 'pro security-status'.

Check โ€” read-only
dnf updateinfo list --security   # Debian/Ubuntu: apt list --upgradable; Ubuntu: pro security-status
Changes your system
sudo dnf upgrade --security   # Debian/Ubuntu: sudo apt update && sudo apt upgrade

Source: Red Hat: Identifying security updates (RHEL 9); DNF5 docs: advisory command

Restart what the update patched

admin

A patched library does nothing until the processes using it restart. A new kernel does nothing until you reboot. Servers often run old code for months after an 'update'.

On RHEL/Fedora, ask dnf whether a reboot or service restart is needed. On Debian/Ubuntu, check for /var/run/reboot-required and use needrestart (since Ubuntu 24.04 it restarts affected services automatically by default). Schedule reboots. On Ubuntu, Livepatch through Ubuntu Pro (free for personal use on up to 5 machines) can apply critical kernel fixes without a reboot.

Check โ€” read-only
dnf needs-restarting -r   # Debian/Ubuntu: cat /var/run/reboot-required 2>/dev/null; sudo needrestart -r l
Changes your system
sudo systemctl reboot

Source: Ubuntu: Livepatch; DNF5 docs: needs-restarting(8)

Update firmware with fwupd

power user

BIOS/UEFI, SSD, and Thunderbolt firmware get security fixes too. fwupd pulls signed vendor firmware from the Linux Vendor Firmware Service (LVFS).

List your devices and any pending firmware updates. GNOME Software and KDE Discover also show these. Plug laptops into power first.

Check โ€” read-only
fwupdmgr get-devices; fwupdmgr get-updates
Changes your system
fwupdmgr refresh && fwupdmgr update

Source: fwupd / LVFS project

Patch actively exploited bugs first

admin

CISA's Known Exploited Vulnerabilities (KEV) catalog lists CVEs that attackers are using right now. Linux kernel, sudo, OpenSSH, and glibc entries show up there regularly.

Compare your pending advisories against the KEV list. Anything on KEV gets patched first, outside the normal cycle.

Source: CISA Known Exploited Vulnerabilities Catalog

2. SSH: the front door

Use SSH keys and turn off password logins

everyone

Password logins are the target of nonstop internet-wide guessing. A key cannot be guessed.

Generate an ed25519 key on your client and copy it to the server with ssh-copy-id. Test a key login in a second session. Then set PasswordAuthentication no and KbdInteractiveAuthentication no. Keep your current session open until the new settings are confirmed working.

Check โ€” read-only
sudo sshd -T | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication)'
Changes your system
ssh-keygen -t ed25519 && ssh-copy-id user@server   # then on the server: echo -e 'PasswordAuthentication no\nKbdInteractiveAuthentication no' | sudo tee /etc/ssh/sshd_config.d/10-hardening.conf

Source: OpenBSD manual: sshd_config(5)

Block direct root login

everyone

Every attacker knows the username 'root'. Logging in as yourself and then using sudo leaves an audit trail with a name on it.

Set PermitRootLogin no. If automation truly needs root, use 'prohibit-password', which allows keys only. Make sure your own account has sudo before you apply this.

Check โ€” read-only
sudo sshd -T | grep -i '^permitrootlogin'
Changes your system
echo 'PermitRootLogin no' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf

Source: OpenBSD manual: sshd_config(5)

Check the settings sshd actually uses with sshd -T

power user

Ubuntu, Debian, and Fedora read drop-in files in /etc/ssh/sshd_config.d/ first, and sshd keeps the first value it reads for most settings. A line you edit in sshd_config can be silently overridden. sshd -T prints the effective configuration.

Put your changes in a drop-in file with a low number, such as 10-hardening.conf. Validate with 'sshd -t', which prints nothing when the config is OK. Confirm with 'sshd -T'. Reload the service only after both pass.

Check โ€” read-only
sudo sshd -t && sudo sshd -T | less
Changes your system
sudo systemctl reload ssh   # RHEL/Fedora: sudo systemctl reload sshd

Source: Ubuntu Server docs: OpenSSH server

Limit who can log in over SSH

admin

Service accounts and old users should never have a shell over the network. An allow-list is easier to audit than a block-list.

Create an 'sshusers' group, add the real humans to it, and set AllowGroups sshusers. Also consider MaxAuthTries 3 and LoginGraceTime 30.

Check โ€” read-only
sudo sshd -T | grep -Ei '^(allowusers|allowgroups|maxauthtries|logingracetime)'
Changes your system
sudo groupadd sshusers && sudo usermod -aG sshusers $USER && echo 'AllowGroups sshusers' | sudo tee -a /etc/ssh/sshd_config.d/10-hardening.conf

Source: OpenBSD manual: sshd_config(5)

Know that Ubuntu starts SSH through a socket

admin

Since Ubuntu 22.10, sshd starts on demand through ssh.socket. Port and ListenAddress changes in sshd_config only apply after a systemd daemon-reload and a socket restart. People 'move the port' and nothing changes.

After changing Port or ListenAddress, reload systemd and restart ssh.socket. Confirm the listener with ss.

Check โ€” read-only
systemctl status ssh.socket --no-pager; ss -tlnp | grep -i ssh
Changes your system
sudo systemctl daemon-reload && sudo systemctl restart ssh.socket

Source: Ubuntu Discourse (Canonical): sshd now uses socket-based activation

3. Network exposure and firewalls

See what is listening with ss -tulpn

everyone

Every listening port is attack surface. Most people are surprised by at least one entry.

List TCP and UDP listeners with the owning process. Anything bound to 0.0.0.0 or [::] is reachable from every network the machine is on. Stop or rebind anything you don't need. Use lsof to see which files and sockets a process holds.

Check โ€” read-only
sudo ss -tulpn; sudo lsof -i -P -n | grep LISTEN

Source: Debian manpages: ss(8) (iproute2)

Ubuntu/Debian: turn on ufw with default-deny inbound

everyone

ufw (Uncomplicated Firewall) is a simple front end to the kernel firewall. It is installed on Ubuntu but disabled by default.

Allow SSH first so you don't lock yourself out. Then enable ufw. Its defaults are deny incoming and allow outgoing. Add only the ports you serve.

Check โ€” read-only
sudo ufw status verbose
Changes your system
sudo ufw allow OpenSSH && sudo ufw enable

Source: Ubuntu Server docs: Firewalls

RHEL/Fedora: check firewalld zones

power user

firewalld is on by default on RHEL and Fedora. Services are opened per zone, and the wrong zone on an interface can expose more than you think.

Check which zone each interface is in and what that zone allows. Remove services you don't use. Use --permanent and then --reload so changes survive a reboot.

Check โ€” read-only
sudo firewall-cmd --get-active-zones; sudo firewall-cmd --list-all
Changes your system
sudo firewall-cmd --permanent --remove-service=cockpit && sudo firewall-cmd --reload

Source: firewalld documentation

Read the real ruleset with nftables

admin

ufw, firewalld, and Docker all write nftables (or iptables-nft) rules underneath. 'nft list ruleset' shows what the kernel actually enforces, including Docker rules that bypass ufw.

Dump the ruleset and look for accept rules you didn't create. On hand-built servers, a single /etc/nftables.conf with a default-drop input chain is clean and auditable.

Check โ€” read-only
sudo nft list ruleset
Changes your system
sudo systemctl enable --now nftables   # after writing /etc/nftables.conf

Source: nftables wiki (netfilter project)

Block repeat offenders with fail2ban

power user

Even with key-only SSH, brute-force traffic fills logs and wastes resources. fail2ban watches logs and temporarily bans IPs that keep failing.

Install fail2ban. Create /etc/fail2ban/jail.local (never edit jail.conf) and enable the sshd jail. On systemd hosts, set backend = systemd so it reads the journal.

Check โ€” read-only
sudo fail2ban-client status; sudo fail2ban-client status sshd
Changes your system
sudo apt install fail2ban   # RHEL/Fedora: sudo dnf install fail2ban (EPEL on RHEL); then sudo systemctl enable --now fail2ban

Source: fail2ban project (GitHub)

Or use CrowdSec for shared blocklists

admin

CrowdSec does what fail2ban does and adds a community blocklist of IPs seen attacking other servers. Detection (the agent) is separate from blocking (the bouncers).

Install the agent from the official repo. Install a firewall bouncer, which actually blocks traffic. Check that collections for sshd and your web server are loaded.

Check โ€” read-only
sudo cscli metrics; sudo cscli collections list; sudo cscli decisions list
Changes your system
sudo apt install crowdsec crowdsec-firewall-bouncer-nftables   # after adding the CrowdSec repo per docs

Source: CrowdSec documentation

4. Accounts and sudo hygiene

Review who can use sudo

everyone

Every sudo-capable account is a root account with extra steps. Old admin accounts and NOPASSWD rules pile up over time.

List members of the sudo (Debian/Ubuntu) or wheel (RHEL/Fedora) group. Read every file in /etc/sudoers.d. Remove NOPASSWD unless a specific automation truly needs it.

Check โ€” read-only
getent group sudo wheel; sudo grep -rE 'NOPASSWD|ALL' /etc/sudoers /etc/sudoers.d/; sudo -l
Changes your system
sudo gpasswd -d olduser sudo

Source: sudo project: sudoers(5) manual

Always edit sudoers with visudo

power user

A syntax error in sudoers can lock every admin out of sudo. visudo checks syntax before saving.

Use 'visudo -f /etc/sudoers.d/<name>' for drop-ins. Run 'visudo -c' to validate everything. Grant specific commands, not ALL, wherever you can.

Check โ€” read-only
sudo visudo -c
Changes your system
sudo visudo -f /etc/sudoers.d/90-local

Source: sudo project: visudo(8) manual

Ubuntu 25.10+ and 26.04 use sudo-rs

admin

Ubuntu now ships sudo-rs, a memory-safe Rust rewrite, as the default sudo. The original is still available as sudo.ws. Most sudoers files work unchanged, but some rarely used options and plugins are not implemented.

Check which sudo you are running. Run 'visudo -c' after upgrading to 26.04. Test any complex rules, especially wildcards in command arguments.

Check โ€” read-only
sudo --version; update-alternatives --display sudo

Source: Ubuntu Discourse (Canonical): Adopting sudo-rs by default in Ubuntu 25.10

Lock accounts nobody uses

admin

Dormant accounts with passwords are free entry points that nobody is watching.

List accounts with a login shell and check their last login. Newer distros (Fedora 40+, Debian 13) replaced lastlog with lastlog2. Lock the password with -L and set the expiry to day 1 so the whole account is disabled, not just password logins. Ask before deleting, because files and cron jobs may still belong to them.

Check โ€” read-only
getent passwd | awk -F: '$7 !~ /(nologin|false)$/ {print $1, $7}'; (lastlog2 2>/dev/null || lastlog) | grep -v 'Never'
Changes your system
sudo usermod -L -e 1 olduser

Source: Debian manpages: usermod(8)

Lock out repeated failed passwords with pam_faillock

admin

Local and console password guessing does not go through fail2ban. pam_faillock locks an account after several failed attempts.

On RHEL/Fedora, turn it on with the authselect with-faillock feature. Tune deny and unlock_time in /etc/security/faillock.conf. Use faillock to see and reset counters.

Check โ€” read-only
sudo faillock; authselect current
Changes your system
sudo authselect enable-feature with-faillock

Source: Red Hat: Configuring user authentication using authselect (RHEL 9)

5. Confinement: AppArmor, SELinux and systemd sandboxing

Keep SELinux enforcing (RHEL/Fedora)

power user

SELinux confines services so a hacked web server can't read your SSH keys or home directories. Turning it off is the most common 'fix' found online, and the worst one.

Confirm the mode is Enforcing. When something is blocked, read the denial with ausearch or sealert, then fix the file label (semanage fcontext + restorecon) or the boolean. Red Hat notes most denials are misconfiguration. If you switch to permissive with setenforce 0 to diagnose, switch back to enforcing right after, and never disable SELinux.

Check โ€” read-only
getenforce; sestatus; sudo ausearch -m AVC -ts recent
Changes your system
sudo restorecon -Rv /path/to/content

Source: Red Hat: Troubleshooting problems related to SELinux (RHEL 9)

Keep AppArmor profiles enforcing (Debian/Ubuntu)

power user

AppArmor is the Debian/Ubuntu counterpart to SELinux. Profiles limit what each program can touch. It is on by default, and some profiles ship in complain mode, which only logs.

Check which profiles are enforcing and which are complaining. Install apparmor-profiles and apparmor-utils for more coverage. Use aa-enforce to move a tested profile to enforce mode.

Check โ€” read-only
sudo aa-status
Changes your system
sudo apt install apparmor-utils apparmor-profiles && sudo aa-enforce /etc/apparmor.d/usr.sbin.<service>

Source: Ubuntu Server docs: AppArmor

Score your services with systemd-analyze security

admin

systemd can sandbox any service with no code changes: private /tmp, read-only system dirs, no new privileges, limited syscalls. This command rates every service's exposure from 0 (locked down) to 10 (UNSAFE).

Run it with no argument for a ranked list. Run it with a unit name to see each setting it checks. Start with your network-facing services.

Check โ€” read-only
systemd-analyze security; systemd-analyze security nginx.service

Source: systemd: systemd-analyze(1)

Harden a service with a drop-in override

admin

A few lines can stop a compromised daemon from writing to /usr, gaining privileges, or loading kernel modules. The package file stays untouched, so updates won't overwrite your changes.

Use 'systemctl edit' to create an override with settings like NoNewPrivileges=yes, ProtectSystem=strict, ProtectHome=yes, PrivateTmp=yes, ProtectKernelModules=yes, and ReadWritePaths= for the dirs the service needs. Restart it, test it, and re-score it.

Check โ€” read-only
systemctl cat myapp.service
Changes your system
sudo systemctl edit myapp.service && sudo systemctl restart myapp.service

Source: systemd: systemd.exec(5)

Run each service as its own unprivileged user

admin

If every daemon runs as root, one bug owns the whole box. DynamicUser= or a dedicated User= limits the damage to that service.

Set User= or DynamicUser=yes in the unit. Grant only the capabilities needed with AmbientCapabilities= (for example CAP_NET_BIND_SERVICE for port 80) instead of running as root.

Check โ€” read-only
ps -eo user,comm --sort=user | sort -u | grep '^root'

Source: systemd: systemd.exec(5) User=, DynamicUser=

6. Kernel, boot and disk encryption

Encrypt disks with LUKS

everyone

A stolen laptop or a decommissioned server disk without encryption is a data breach. LUKS is the standard Linux full-disk encryption.

The easiest way is to choose 'Encrypt' in the installer. Ubuntu, Fedora, Debian, and RHEL all offer it. For existing data disks, use cryptsetup luksFormat (this erases the disk). Store a recovery passphrase offline.

Check โ€” read-only
lsblk -f; sudo cryptsetup status <mapping-name>
Changes your system
sudo cryptsetup luksFormat /dev/sdX   # ERASES the device

Source: Red Hat: Encrypting block devices using LUKS (RHEL 9 Security hardening)

Unlock LUKS with the TPM (optional)

admin

Binding LUKS to the TPM gives unattended boot on servers while the data stays encrypted if the disk is removed. Keep the passphrase as a fallback.

Use systemd-cryptenroll to add a TPM2 key slot tied to Secure Boot state (PCR 7). Then add tpm2-device=auto to /etc/crypttab. On RHEL, Clevis is the supported route.

Check โ€” read-only
sudo systemd-cryptenroll /dev/nvme0n1p3
Changes your system
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=7 /dev/nvme0n1p3

Source: systemd: systemd-cryptenroll(1)

Keep UEFI Secure Boot on

everyone

Secure Boot stops unsigned bootloaders and kernels, so bootkits can't load before Linux. Major distros ship signed shim and kernels. On many distros it also turns on kernel lockdown.

Confirm it is enabled. If you need out-of-tree drivers (NVIDIA, VirtualBox), enroll a Machine Owner Key (MOK) with mokutil instead of disabling Secure Boot.

Check โ€” read-only
mokutil --sb-state; cat /sys/kernel/security/lockdown
Changes your system
sudo mokutil --import /path/to/MOK.der

Source: Debian Wiki: SecureBoot

Harden kernel settings with sysctl

admin

A few kernel settings close common footholds: kernel pointer leaks, unprivileged eBPF, ptrace snooping between processes, and ICMP redirects.

Create /etc/sysctl.d/90-hardening.conf with settings like kernel.kptr_restrict=2, kernel.dmesg_restrict=1, kernel.unprivileged_bpf_disabled=1, kernel.yama.ptrace_scope=1 (or 2 on servers), net.ipv4.conf.all.accept_redirects=0, net.ipv4.conf.all.send_redirects=0, and net.ipv4.conf.all.rp_filter=1. Apply it, then test your apps.

Check โ€” read-only
sysctl kernel.kptr_restrict kernel.dmesg_restrict kernel.unprivileged_bpf_disabled kernel.yama.ptrace_scope net.ipv4.conf.all.accept_redirects
Changes your system
sudo sysctl --system   # after writing /etc/sysctl.d/90-hardening.conf

Source: Linux kernel docs: /proc/sys/kernel/ (sysctl) documentation

Compare against the Kernel Self Protection Project list

admin

KSPP, an upstream kernel project, keeps the reference list of recommended kernel build options, boot parameters, and sysctls, with the reason for each.

Use it to review your sysctl file and boot command line. Not everything fits every workload. Some boot options cost performance.

Check โ€” read-only
cat /proc/cmdline

Source: Kernel Self Protection Project: Recommended Settings

7. Logging, auditing and file integrity

Make the journal persistent

power user

On some installs journald keeps logs only in memory, so they disappear at reboot, along with the evidence of what happened before the crash or break-in.

Set Storage=persistent in a journald.conf drop-in, or create /var/log/journal. Cap the size with SystemMaxUse=. Send logs off-box (rsyslog or a SIEM) so an attacker can't erase them.

Check โ€” read-only
journalctl --disk-usage; journalctl --list-boots | head
Changes your system
sudo mkdir -p /var/log/journal && sudo systemctl restart systemd-journald

Source: systemd: journald.conf(5)

Read failed logins and sudo use from the journal

everyone

Most incidents show up in auth logs first. Knowing the two or three queries that matter saves time when it counts.

Filter by SSH unit and by priority. Look for bursts of failures followed by a success.

Check โ€” read-only
journalctl -u ssh -u sshd --since today | grep -Ei 'failed|accepted'; journalctl _COMM=sudo --since today

Source: systemd: journalctl(1)

Turn on auditd and watch sensitive files

admin

auditd records who changed what at the kernel level: edits to sudoers or passwd, use of privileged commands, and module loads. It is what compliance frameworks expect.

Install and enable auditd. Add watch rules in /etc/audit/rules.d/ (for example '-w /etc/sudoers -p wa -k sudoers'), then load them with augenrules. Search events by key with ausearch, or get a summary with aureport.

Check โ€” read-only
sudo auditctl -s; sudo auditctl -l; sudo aureport --summary
Changes your system
sudo apt install auditd   # RHEL/Fedora: usually preinstalled (sudo dnf install audit if not); then sudo systemctl enable --now auditd && sudo augenrules --load

Source: Red Hat: Auditing the system (RHEL 9 Security hardening)

Detect file tampering with AIDE

admin

AIDE takes a fingerprint of system binaries and configs, then reports anything that changed. It catches replaced binaries and quiet config edits.

Install AIDE and build the baseline database on a known-clean system. Run checks on a schedule. After planned updates, review the changes and then update the baseline. Keep a copy of the database off-box.

Check โ€” read-only
sudo aide --check
Changes your system
sudo aide --init && sudo mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz   # Debian: sudo aideinit

Source: Red Hat: Checking integrity with AIDE (RHEL 9 Security hardening)

Verify installed packages against the package database

power user

The package manager already knows the correct checksum of every file it installed. This is a free integrity check with nothing to set up.

On RHEL/Fedora, rpm -Va lists files whose size, checksum, or permissions differ from the package. Config files changing is normal. Changed binaries are not. On Debian/Ubuntu, use debsums.

Check โ€” read-only
sudo rpm -Va | grep -v ' c '   # Debian/Ubuntu: sudo debsums -s

Source: RPM project: rpm(8) verify options

8. Containers

Prefer rootless containers

power user

A container escape from a root daemon gives the attacker root on the host. Rootless Podman, or Docker in rootless mode, maps container root to an unprivileged user.

On Fedora/RHEL, Podman runs rootless by default for normal users. For Docker, follow the rootless-mode guide. Avoid adding users to the 'docker' group, which is root-equivalent.

Check โ€” read-only
podman info --format '{{.Host.Security.Rootless}}'; getent group docker

Source: Docker docs: Rootless mode

Know that Docker published ports bypass ufw

admin

Docker writes its own firewall rules. A '-p 8080:80' container is reachable from the internet even when ufw says 8080 is closed.

Bind published ports to 127.0.0.1 ('-p 127.0.0.1:8080:80') and put a reverse proxy in front. Or filter in the DOCKER-USER chain. Check the real exposure with ss and nft.

Check โ€” read-only
docker ps --format '{{.Names}} {{.Ports}}'; sudo nft list ruleset | grep -i docker

Source: Docker docs: Packet filtering and firewalls

Drop privileges inside containers

admin

Most images don't need root, extra capabilities, or a writable root filesystem. Removing them limits what a compromised app can do.

Run with --user, --cap-drop=ALL (add back only what's needed), --read-only, and --security-opt no-new-privileges. Never use --privileged or mount the Docker socket into an app container. Follow NIST SP 800-190 for the full picture.

Check โ€” read-only
docker inspect --format '{{.Name}} priv={{.HostConfig.Privileged}} user={{.Config.User}} caps={{.HostConfig.CapAdd}}' $(docker ps -q)

Source: NIST SP 800-190: Application Container Security Guide

9. Audit and compliance scanning

Run a Lynis audit

power user

Lynis is a free, agentless scanner that checks hundreds of settings and gives you a hardening index and a prioritized list of suggestions. It is the fastest way to find gaps.

Install it from your distro or from CISOfy's repo (the repo is newer). Run a system audit as root and work through the Warnings, then the Suggestions. Re-run it after changes to see the index move.

Check โ€” read-only
sudo lynis audit system
Changes your system
sudo apt install lynis   # RHEL/Fedora: sudo dnf install lynis (EPEL on RHEL)

Source: CISOfy: Lynis

Scan against a real benchmark with OpenSCAP

admin

OpenSCAP and the SCAP Security Guide (ComplianceAsCode) check a system against CIS, DISA STIG, and other profiles. They produce an HTML report and can generate a remediation script.

Install openscap-scanner and scap-security-guide. List the profiles in the datastream for your OS, then run an evaluation and open the report. Review any remediation before applying it. Some rules can break SSH or applications.

Check โ€” read-only
sudo oscap xccdf eval --profile xccdf_org.ssgproject.content_profile_cis_server_l1 --report /tmp/oscap-report.html /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
Changes your system
sudo dnf install openscap-scanner scap-security-guide

Source: OpenSCAP project; ComplianceAsCode (SCAP Security Guide)

Use the CIS Benchmarks as your baseline

admin

CIS Benchmarks are consensus hardening guides for each distro version. Level 1 is safe for most systems. Level 2 is stricter.

Download the PDF for your exact distro version, free with registration. Use it with OpenSCAP or Lynis to measure. Write down any rule you deliberately skip and why.

Source: Center for Internet Security: CIS Benchmarks

Check for rootkits with chkrootkit

admin

chkrootkit looks for known rootkit signs, hidden processes, and suspicious changes to key binaries. It is a quick second opinion, not proof the system is clean.

Install chkrootkit from your distro and run it on a schedule. Expect some false positives and investigate each one. A system you truly suspect should be rebuilt, not trusted. (rkhunter, often paired with it, has had no upstream release since 2018.)

Check โ€” read-only
sudo chkrootkit -q
Changes your system
sudo apt install chkrootkit

Source: chkrootkit project

Tools worth knowing

Lynisfree + paid

Agentless hardening and compliance auditor that scores the system and lists fixes.

When: First scan of any box, and after every hardening pass.

OpenSCAPfree

SCAP scanner that evaluates a system against standard profiles and writes HTML reports and remediation scripts.

When: When you need a formal CIS or STIG compliance check.

SCAP Security Guide (ComplianceAsCode)free

The content OpenSCAP scans with: CIS, STIG, PCI-DSS, and other profiles for RHEL, Fedora, Ubuntu, and Debian.

When: Together with OpenSCAP, to pick a benchmark profile.

CIS Benchmarksfree + paid

Consensus hardening guides for each distro version.

When: Setting a written baseline for servers.

ssbuilt-in

Lists sockets and listening ports with the owning process (iproute2).

When: Any time you want to know what is exposed: ss -tulpn.

lsoffree

Lists open files and network connections per process.

When: Tracing which process holds a port or file.

systemd-analyze securitybuilt-in

Rates every service's sandboxing from 0 to 10 and lists missing protections.

When: Before and after hardening a network-facing service.

fail2banfree

Bans IPs that keep failing logins, based on log patterns.

When: Any internet-facing SSH, mail, or web server.

CrowdSecfree + paid

Log-based intrusion detection with community-shared blocklists and separate blocking 'bouncers'.

When: When you want fail2ban-style protection plus crowd-sourced threat intel.

auditdbuilt-in

Kernel-level audit logging of file access, privileged commands, and syscalls.

When: Servers that need a who-did-what trail or must meet compliance.

AIDEfree

File integrity checker that compares the system against a trusted baseline.

When: Detecting unauthorized changes to binaries and configs.

chkrootkitfree

Lightweight scanner for known rootkit signs.

When: Scheduled second-opinion scans on servers.

osqueryfree

Lets you query the OS like a database (processes, ports, users, packages) with SQL.

When: Fleet visibility and threat hunting across many machines.

Wazuhfree + paid

Open-source SIEM/XDR: log collection, file integrity monitoring, vulnerability detection, and CIS checks across a fleet.

When: Central monitoring for more than a handful of servers.

ClamAVfree

Open-source antivirus engine with freshclam signature updates.

When: Scanning file uploads, mail, and shares that Windows clients touch.

fwupd / LVFSfree

Vendor firmware updates (UEFI, SSD, docks) for Linux.

When: Keeping laptop and server firmware patched.

Other platforms

Go deeper

networks.jelia.nycHow the internet actually moves your data โ€” packets, DNS, routing, TLS. waves.jelia.nycElectromagnetism explained โ€” Wi-Fi, 2.4 GHz, Bluetooth and why RF leaks. lib.jelia.nycThe library โ€” security, Linux, assembly and networking books on the shelf. blog.redpatch.usRedPatch field notes.