Skip to content
Mounteyes
All guides

Server hardening checklist for small businesses

11 min readUpdated: Servers, Sites & Networks

Hardening has a reputation for being a hundred-item audit nobody finishes. In practice, on a small business's single web server, about a dozen changes account for most of the risk reduction — and half of them take an afternoon.

The short version

  • Close what you are not using. Every listening service is an entry point you have to defend forever.
  • Key-based SSH with no root login and no password authentication removes most automated attacks in one change.
  • Patch the application layer, not just the OS — most breaches arrive through a plugin, not a kernel.
  • Turn logging on before you need it. You cannot investigate a period you did not record.
  • A backup you have never restored is not a backup.

Start with an inventory, not a checklist

You cannot harden what you have not listed. Before changing anything, write down what is actually running: which services listen on which ports, which of them are reachable from outside, who has accounts, which of those accounts are still people who work here, and what the machine is allowed to connect out to.

That document is worth an hour on its own, because it is also the known-good baseline you will want during an incident. "Is this process meant to be here" is unanswerable without it, and that is the question you will be asking at the worst possible moment.

Two findings are near-universal in this exercise: a service nobody remembers enabling, and an account belonging to someone who left.

Access: SSH, accounts and privilege

Move SSH to key-based authentication and disable password authentication entirely. This single change eliminates the overwhelming majority of automated intrusion attempts, because the credential-guessing that fills your auth log stops being able to succeed at all.

Disable direct root login and work through a named account with sudo, so that actions are attributable to a person. Give every human their own account — a shared administrative login means an incident can never be traced and offboarding is impossible.

Remove accounts as people leave, on the day they leave. Review `authorized_keys` for every account, including service accounts, because a key added two years ago for a contractor's laptop is still a valid credential today.

Changing the SSH port reduces log noise but is not a security control; do it if the quieter logs help you, and do not count it as hardening.

Surface: ports, services and the firewall

Default-deny inbound, then allow only what has a reason. In practice that is usually 443, sometimes 80 to redirect to it, and SSH restricted to known addresses or reachable only through a VPN.

Nothing administrative belongs on the public internet: no database port, no phpMyAdmin, no admin panel, no Redis, no Elasticsearch, no container API. Those services are frequently installed with no authentication by default, on the assumption that they sit on a private network.

Uninstall rather than stop. A stopped service comes back after a package update or a reboot, and a service that is not installed cannot.

Restrict outbound traffic too, if you can. A web server that can only reach the two destinations it actually needs is dramatically less useful to somebody who gets code onto it.

Transport: TLS done properly

Force HTTPS for everything and redirect HTTP to it. Enable HSTS once you are confident every subdomain is served over TLS, and understand that it is deliberately hard to undo — that is the point of it.

Disable the protocol versions and cipher suites that only exist for clients you do not have. TLS 1.2 and 1.3 with modern ciphers is the sane baseline.

Automate certificate renewal and alert on the failure of the renewal, not on the expiry of the certificate. An expiry notice is the alarm you get after the outage has already been decided.

Updates and the dependency layer

Enable unattended security updates for the operating system. The risk of an unexpected restart is real and is smaller than the risk of a month-old kernel or library vulnerability on an internet-facing host.

The layer that actually gets breached, though, is above the OS. Your CMS plugins, your framework, your language runtime and your application dependencies are where the exploited vulnerability usually lives, and none of them are covered by the OS updater.

So keep an inventory of application dependencies, subscribe to advisories for the ones that matter, and remove what you are not using. An unused plugin is fully as exploitable as a used one, and it has nobody watching it.

Logging and monitoring

Turn on authentication logging, web access and error logging, and a shell audit trail, and set retention long enough to investigate something you discover late — a month is thin, three months is workable.

Ship logs off the machine. Logs that exist only on the host are logs an intruder can edit, and the difference between an edited log and a missing one is the difference between a false sense of safety and a finding.

Then alert on the handful of things that mean something: a successful login from an unfamiliar location, a new privileged account, a change inside the web root, a service starting that should not be running, and a log source going silent.

Backups you have actually restored

Automate them, keep at least one copy where the server cannot reach or delete it, and encrypt them at rest. A backup reachable with the credentials on the box is a backup ransomware encrypts along with everything else.

Then restore one. Not theoretically — actually restore to a scratch environment and confirm the site comes up and the data is complete. Untested backups fail at roughly the rate you would expect of anything nobody has ever run, and you find out on the worst day of the year.

Write down your recovery point and recovery time from that test. Those two numbers are what a real incident is measured against.

What hardening does not cover

Hardening reduces the ways in. It does nothing about the time between an intrusion and somebody noticing, and that interval is usually what decides the cost.

It also does not address application logic. A perfectly hardened server will happily serve an endpoint that returns another customer's invoice because the authorisation check was missing, and no firewall rule detects that.

So treat this checklist as the floor rather than the finish. Above it sit monitoring, application-level testing, and a plan for the day something gets through anyway.

Nothing on this site will ever ask for your password, OTP or recovery codes.

Related guides

Want this handled for you?

Our engineers do this work for businesses every day, on monitoring platforms built to catch it earlier. Describe your situation and we will tell you what would actually help.

Talk to Our Security Team