Linux Server Hardening: Checklist for Web Servers
Is your website running on your own VPS with no dedicated sysadmin? This checklist covers the hardening steps we apply to every inherited server, including common pitfalls that can lock you out.
by Cleverson Gouvêa

Linux server hardening is the process of minimizing everything an internet-exposed server offers an attacker: open ports, unnecessary services, excessive users, outdated versions, and superfluous permissions. If your company runs a website, e-commerce site, or system on its own VPS and no one on your team is a dedicated sysadmin, this checklist shows you what to do, in what order, what not to do, and the ongoing costs.
TL;DR
- In 2026, vulnerability exploitation became the leading entry point in data breaches: 31% of initial access attempts in the Verizon DBIR 2026, up from 20% the previous year. Outdated servers are the easiest targets.
- The effective order: inventory and backup → SSH → firewall → updates → PHP and web server → database → logs and monitoring.
- Several popular versions have reached end-of-life: PHP 8.1 (12/31/2025), MySQL 8.0 (April 2026), Debian 11 (08/31/2026). PHP 8.2 only receives security fixes until 12/31/2026.
- The costliest pitfalls are silent: Docker ignores UFW, fail2ban behind Cloudflare bans Cloudflare itself, and on Ubuntu 24.04, changing the port in sshd_config does nothing.
- Linux server hardening isn't a one-time task: it's a monthly routine. If no one in your company will perform this routine, hire someone to do it.
I write as a full-stack developer and founder of Agathas Web, a company that has operated Linux servers since 2008. I support Moodle environments for educational institutions, client websites and systems on managed hosting, and the infrastructure for Voyia, our customer service platform built on the official WhatsApp API. The Linux server hardening checklist below is the same one we apply when inheriting a server.
What is Linux Server Hardening and Why It Became Urgent in 2026
A newly created server in any cloud comes configured to function, not to resist attacks. It accepts password logins, leaves services listening on all interfaces, and assumes someone will apply updates. Linux server hardening is the process of turning off what's unnecessary and strengthening what remains.
The reason for the urgency lies in the numbers. According to the Verizon Data Breach Investigations Report 2026, vulnerability exploitation accounted for 31% of initial access attempts in breaches, surpassing phishing and stolen credentials. The same report shows that organizations take a median of 43 days to patch a vulnerability that is already being exploited, and only 26% are fully remediated.
Translating this to the reality of a business with a web server: without Linux server hardening and a patching routine, an attacker doesn't need to specifically target you. They scan the internet for a vulnerable version and gain entry wherever they find an open door.
The case that best illustrates this is regreSSHion (CVE-2024-6387). In July 2024, Qualys disclosed a flaw in OpenSSH that allowed remote unauthenticated code execution as root on Linux systems with glibc. It affected versions 8.5p1 to 9.7p1, and the company estimated over 14 million potentially vulnerable instances exposed. Those with an update routine patched it in days. Those without remained exposed for months.
That's why Linux server hardening isn't a project with a beginning, middle, and end. It's a well-executed initial configuration combined with an ongoing routine. In our managed hosting, the contractual goal is to apply critical patches within 72 hours of CVE publication — and it's this routine, not the first day's setup, that separates a secure server from one that was secure only for a day.
Before You Start: Inventory, Backup, and Emergency Access
The most common mistake for those doing Linux server hardening for the first time is starting with SSH and locking themselves out. Before changing anything, ensure these three things.
1. A Way Back
- Provider's emergency console (KVM, web console, "rescue mode"). Test it beforehand. If you mess up the firewall rules, that's your way in.
- Disk snapshot taken immediately before changes. On a VPS, it costs cents and undoes an error in minutes.
- A second SSH session open while changing access configurations. Only close it after testing login in a third.
2. An Honest Inventory
Run ss -tulpn and note every listening service. On inherited servers, the most common pattern we find is a database listening on 0.0.0.0, a forgotten admin panel, and a test service no one remembers installing. Each item on this list needs an owner and a reason to exist.
3. When NOT to Apply Hardening Now
- Without a tested backup. Hardening a server without guaranteed restoration exchanges one risk for another.
- On the eve of a launch, enrollment period, or Black Friday. Security changes require a window, just like deployments.
- With a ready-made script from the internet run blindly. Benchmarks like the CIS are an excellent reference, but applying all items at once can break applications. Apply in blocks and test in between.
- On an unsupported operating system. If the server runs Ubuntu 20.04 or Debian 11, the correct hardening is to migrate to a supported version, not patch the old one.
SSH and Users: Who Gets In and How
SSH opens the door to Linux server hardening because it's the front door. It's also the first thing bots test, minutes after a new IP appears on the internet.
The Mandatory Minimum
- Key-only login.
PasswordAuthentication noandKbdInteractiveAuthentication noinsshd_config. Use ed25519 keys, one per person, never shared. - No direct root login.
PermitRootLogin no. Each person uses their own user and escalates privileges withsudo, which leaves a trail of who did what. - Only those who need it.
AllowUsersorAllowGroupslimits who can log in, even if another account exists on the system. - fail2ban to block IPs that repeatedly fail. It doesn't replace keys but reduces log noise and thwarts brute-force attacks on other services.
- Disable accounts of departed personnel. Former vendors with keys still authorized in
authorized_keysare more common than they seem.
Pitfall: Changing the SSH Port on Ubuntu 24.04
Changing port 22 to another reduces log noise but isn't real protection — a scanner finds the new port in seconds. And there's a detail that trips up many: since Ubuntu 22.10, SSH uses systemd socket activation. On Ubuntu 24.04, altering Port in sshd_config passes validation but is simply ignored because ssh.socket listens on the port. You need to adjust the socket and run systemctl daemon-reload. If the firewall has already been closed for the old port, this is where you lose access.
System Users and Permissions
The rule is least privilege. The web server process (www-data, nginx, or apache) cannot own the application files: if it does, any code vulnerability allows rewriting the code itself. Keep the code under a deploy user and grant the web server write access only to folders that require it, such as uploads and cache. In Moodle, for example, moodledata should be outside the public folder, with write access only for the PHP process.
Firewall: Close Everything, Open Only What's Necessary
The firewall in Linux server hardening follows a simple policy: deny everything by default and allow only what the business requires. Generally, this means ports 80 and 443 to the world, and SSH only for known IPs or via VPN.
On Ubuntu, UFW works well: ufw default deny incoming, ufw allow 443/tcp, ufw allow from <your-ip> to any port 22. Databases, Redis, and internal panels do not appear on this list. They listen on 127.0.0.1 or a private network.
Pitfall 1: Docker Bypasses UFW
If you run containers, be aware that when publishing a port with -p 8080:80, Docker writes its own iptables rules, which traffic traverses before UFW rules. Result: a ufw deny 8080 blocks nothing. The official Docker documentation explains this behavior. The simplest fix is to publish only to localhost (-p 127.0.0.1:8080:80) and let the reverse proxy communicate with the container.
Pitfall 2: fail2ban Behind Cloudflare
With a proxy like Cloudflare in front, the server sees Cloudflare's IP, not the visitor's. A fail2ban reading the Nginx log without configuring the real IP will ban Cloudflare's own addresses — and take down legitimate clients along with the attacker. Configure the real IP module with Cloudflare's official IP ranges before enabling any log-based blocking rules.
What Can't Be Closed by the Firewall
Some integrations require a public endpoint. The official WhatsApp API webhook is an example we operate daily at Voyia: Meta needs to reach your server. Here, protection shifts from the firewall to the application: validate the X-Hub-Signature-256 signature of each request, apply rate limiting, and reject unsigned requests. With Cloudflare's WAF in front, you can still block bots and traffic spikes before they reach the server.
Updates: Operating System, PHP, and Database
This is the highest return on investment and most neglected item in Linux server hardening for companies without a sysadmin. The table below shows why the version matters as much as the configuration.
| Component | Status in September 2026 | What to do |
|---|---|---|
| Ubuntu 20.04 LTS | Standard support ended 05/31/2025 (paid ESM only) | Migrate to 24.04 LTS |
| Ubuntu 22.04 LTS | Standard support until April 2027 | Plan migration for 2027 |
| Debian 11 | LTS ended 08/31/2026 | Migrate now |
| Debian 12 | In LTS until 06/30/2028 | Supported, plan for Debian 13 |
| PHP 8.1 | End-of-life on 12/31/2025 | Update the application |
| PHP 8.2 | Security fixes only, until 12/31/2026 | Migrate before year-end |
| MySQL 8.0 | End-of-life in April 2026 | Migrate to 8.4 LTS |
Sources: Ubuntu release cycle, Debian 11 LTS end-of-life announcement, and supported PHP versions.
Automatic Updates: Enable, But Understand the Limits
On Ubuntu, unattended-upgrades is active and applies only security updates once a day. This is a good baseline. The limitation: it doesn't reboot the server by default. Kernel and library fixes, such as for glibc and OpenSSL, only take effect after a reboot or service restart. Check the /var/run/reboot-required file and schedule reboots during an agreed-upon maintenance window.
When NOT to Update Automatically
In Linux server hardening, a rule applies: major version upgrades — PHP 8.1 to 8.3, MySQL 8.0 to 8.4, Ubuntu 22.04 to 24.04 — should never be automatic. Plugins, extensions, or old code can break. The safe approach is to spin up a new server in parallel, validate in staging, and then switch over, as we describe in the guide for migrating Moodle from one server to another without data loss. This applies to any system, not just Moodle.
PHP and Web Server: What the Application Exposes
Most intrusions on PHP sites don't come through the operating system; they come through the code, an outdated plugin, or a poorly validated upload. Linux server hardening doesn't fix bad code, but it limits the damage.
Always-Applicable PHP Configurations
expose_php = Offanddisplay_errors = Offin production. Error messages on screen reveal file paths, versions, and sometimes credentials.allow_url_include = Off. There's no modern reason to include code via URL.- One PHP-FPM pool per application, each with its own user. If one site goes down, its neighbor doesn't go down with it.
- Block PHP execution in the uploads folder. This is how a
.phpfile disguised as an image can get in. open_basedirrestricting PHP to the application's own folders.
Beware of disable_functions Copied from the Internet
Ready-made lists that disable exec, shell_exec, and proc_open appear in every tutorial. They work for simple institutional websites but break real features: Moodle, for example, calls external binaries for tasks like document conversion and disk usage calculation. Adjust the list to the application, not the other way around. The requirements, costs, and common errors of Moodle hosting show how the stack for this type of system demands specific configuration.
On the Web Server
Remove the version signature (server_tokens off in Nginx), enforce HTTPS with HSTS, disable directory listing, and block access to sensitive files like .env, .git, and .sql backups forgotten in the root directory. SSL certificates automatically renewed by Let's Encrypt eliminate the shock of a "not secure" website on a Monday morning.
Database: Off the Internet, Always
There's no reason for a MySQL, MariaDB, or PostgreSQL database for a website or business system to accept internet connections. Even so, an exposed database is one of the most frequent findings when we perform Linux server hardening on inherited environments.
The Database Checklist
- Listen only on 127.0.0.1 or the private network (
bind-addressin MySQL/MariaDB,listen_addressesin PostgreSQL). - One user per application, with permissions only on its own database. The application does not use the database root user.
- Strong passwords and outside versioned code. Credentials in a Git repository are leaked credentials.
- Administrative access via SSH tunnel, never by opening port 3306 "just for a day."
- Remove anonymous users and test databases that some installations create.
- Database backup separate from file backup, with a consistent dump and off-server copy.
Redis and Similar Systems
Redis without a password listening on a public interface is an invitation. It was designed for trusted networks. Keep it on localhost, enable authentication, and disable dangerous commands the application doesn't use.
Logs, Monitoring, and Backup: Hardening That Proves It Worked
A hardened server without monitoring is one where you only discover problems from the client. This step closes the Linux server hardening cycle and shows if the others worked.
- Centralized and retained logs. Authentication (
/var/log/auth.logorjournalctl), web server, and application. If the server is compromised, local-only logs can be erased. - Alerts that reach someone. External uptime, disk usage above 85%, stuck CPU, series of 500 errors, SSH login from a new IP. An alert that goes to an email no one reads isn't an alert.
- 3-2-1 backup, encrypted and tested. Three copies, two different media, one off-site. And the part almost no one does: actually restore, every month, in a test environment. A backup that has never been restored is just a hypothesis.
Summary Checklist and Estimated Effort
| Step | Initial Effort | Routine |
|---|---|---|
| Inventory, snapshot, and emergency access | 1-2 hrs | With each major change |
| SSH and users | 1 hr | Quarterly key review |
| Firewall and WAF | 1-3 hrs | With each new service |
| Updates and reboots | 1 hr setup | Weekly, with window |
| PHP and web server | 2-4 hrs | With each new application |
| Database | 1-2 hrs | Quarterly review |
| Logs, alerts, and tested backup | 3-6 hrs | Monthly (restore test) |
The hours above are our estimate for Linux server hardening for a typical web server with one or two applications, performed by someone familiar with the process. For those learning, multiply by three. And the real cost isn't the day of configuration: it's the routine that needs to happen every week, for years, without anyone forgetting.
This is where the math changes for those without a sysadmin. Hiring a full-time senior professional to manage one or two servers rarely pays off. Leaving the routine to the application developer usually works until the first busy month. We compare the cost of operating alone versus outsourcing, with figures, in Moodle on AWS vs. Managed Hosting — the reasoning applies to any system.
How Agathas Web Solves This
Everything on this Linux server hardening checklist is part of the standard for our managed hosting. It's not an extra package: it's the starting point for every environment we take on.
What's Included
- Operating system hardening upon delivery, with fail2ban, mandatory MFA, and log auditing.
- Cloudflare WAF with custom rules, DDoS mitigation, and bot blocking.
- Updates for system, runtime (PHP, Node, Python), database, and critical plugins, tested in staging and applied during an agreed-upon window. Critical patches within 72 hours of public CVE, as per contract.
- Daily and incremental backup, off-site and encrypted with AES-256, with monthly tested restores.
- 24/7 Monitoring with Grafana, Prometheus, Sentry, and UptimeRobot, and alerts to the technical team's WhatsApp.
- Let's Encrypt SSL automatically renewed for all domains.
- Contractual SLA: 99.9% uptime, response within 15 minutes for critical incidents, and resolution within 2 hours.
How It Works in Practice
We start with a free diagnostic of your current infrastructure: within 3 business days, we identify risks, unsupported versions, and optimized costs. If it makes sense to proceed, we migrate your website, database, emails, and DNS within 7 business days, with staging validation before the switchover and the old environment maintained for 30 days as a rollback plan. The engineer who configured your server is the same one who answers your call.
Pricing and How to Engage
Institutional websites and blogs typically range from $250 to $500 per month; e-commerce and SaaS, between $600 and $2,500 per month. Initial setup ranges from $800 to $3,500, depending on complexity. The contract is monthly, with no long-term commitment, requiring 30 days' notice for cancellation. If your company also needs someone to decide on IT architecture and priorities, our consulting services, acting as a CTO as a Service, complement the operation.
Conclusion: The Checklist Only Works If Someone Runs It Every Month
Linux server hardening starts with a day of configuration and continues with years of discipline. Keys instead of passwords, firewall denying by default, database off the internet, supported versions, logs, and tested backups. None of this is secret. What most companies lack is someone with the time and responsibility to maintain the routine.
If you have the server but not that someone, the next step is simple: request a free diagnostic from Agathas Web's managed hosting. You'll receive a snapshot of your server's current risks and can decide, with figures in hand, whether it's worth doing it yourself or leaving it to those who do it every day.
Related posts

How Much Does iOS & Android App Development Cost in 2026?
Real-world pricing, factors that increase app costs, new Apple and Google policies for 2026, and annual maintenance budget.

Protecting Your Web Server from Attacks: WAF, fail2ban, and Rate Limiting
94% of logins on the Cloudflare network are bots. Learn how WAF, rate limiting, and fail2ban block attacks before they take down your site.

Native, Hybrid, or PWA: Choosing the Best App for Your Business in 2026
Cost, performance, app stores, iPhone push notifications, and offline capabilities: a comparison to help you avoid overspending on your next app.