A website that works well is not necessarily a website with nothing left to improve. Pages load, forms work, visitors go about their business, and from the outside everything appears to be running smoothly. Behind the website, however, there is an entire ecosystem: the web server, PHP, the database, administration services, access rules, backups, and many other components that can be improved as technology and security requirements evolve.

We recently took over the management of a server hosting a single WordPress website. The website was functional and stable, but the server configuration had been put in place some time ago. It was therefore a good candidate for a complete review.

Our goal was simple: keep what was working, reduce the attack surface, and make better use of the available resources.

We Started with Security.

Our first step wasn’t installing a caching plugin or trying to shave a few milliseconds off page load times. We started with something more important: who could reach the server and which services were exposed to the Internet.

The WordPress login page and /wp-admin area were publicly accessible. This is the standard configuration for many WordPress websites, but in this particular case there was no need for the entire Internet to be able to reach them.

So we changed that.

We Restricted Access to WordPress Administration.

We restricted access to /wp-admin and /wp-login.php to a list of trusted IP addresses, directly in nginx.

Any other address receives a 403 Forbidden response before the request ever reaches WordPress or PHP.

The list includes the fixed IP addresses used for administration, but there was one more interesting scenario: one of the authorised connections uses a dynamic IP address that can change over time.

For this, we use a Dynamic DNS (DDNS) hostname. In simple terms, DDNS allows a hostname to continuously point to the current IP address of an Internet connection, even when the provider periodically changes that address.

A script runs automatically at regular intervals, checks the IP address associated with the DDNS hostname, and updates both the nginx access list and firewall rules whenever it changes.

This means access remains available from the authorised location without requiring us to manually update the configuration every time the public IP changes.

The security benefit is significant: even if someone obtained a WordPress administrator’s username and password, they still wouldn’t be able to reach the login page unless the request came from an authorised location.

Automated brute-force attacks are therefore stopped before they ever reach WordPress.

We Reduced the WordPress Attack Surface.

The next step was reviewing the WordPress functionality exposed to the public Internet.

We disabled xmlrpc.php because the website did not require it. XML-RPC can be useful in certain scenarios, but when it isn’t being used there is little reason to leave it publicly accessible.

We also disabled user enumeration through the REST API, preventing unauthenticated visitors from retrieving information about WordPress accounts.

In addition, we removed unnecessary software version information from server responses.

None of these measures is a magic security solution on its own. Together, however, they reduce both the amount of information and the number of potential entry points available to an attacker.

The principle is simple: if a feature isn’t required, there is no reason to expose it to the Internet.

Minimum Access, Minimum Privileges.

We then reviewed how the server itself could be administered.

FTP access was removed completely. File transfers and server administration are now handled exclusively over SSH.

Password-based SSH authentication was disabled, with access allowed only through cryptographic keys.

We kept a single user account for website administration with only the permissions it actually needs. The account can manage the website files and perform the necessary operations on nginx and php-fpm without receiving unnecessary privileges elsewhere on the system.

The firewall allows access to administration services only from authorised networks.

The same rule applies to phpMyAdmin. The interface was brought up to date and is accessible only from the trusted IP list.

In other words, services that need to be public remain public. Services intended for administration are accessible only to administrators.

We Simplified the Server.

Another important step was taking inventory of the installed services.

Over time, servers can accumulate components that once served a purpose but are no longer required. Every additional service means updates, memory consumption, and another component that needs to be monitored from a security perspective.

This server had multiple PHP versions installed even though the website was using only one of them.

We removed the versions that were no longer needed.

We did the same with several monitoring and geolocation services that were no longer in use and removed a subdomain left over from an older configuration.

The result is a simpler server: fewer services, fewer components to maintain, and a smaller attack surface.

We Updated the TLS Configuration.

We also reviewed the HTTPS configuration.

The server still accepted protocols and cryptographic options retained for compatibility with older clients. For this website, there was no longer a practical reason to maintain that level of backwards compatibility.

We restricted secure connections to TLS 1.2 and TLS 1.3 and updated the cryptographic configuration accordingly.

This is a good example of something that should be reviewed periodically: a configuration considered reasonable several years ago does not automatically remain the best configuration forever.

Only Then Did We Move on to Performance.

Once the security review and server cleanup were complete, we turned our attention to performance.

Here, we followed an equally simple principle: avoid unnecessary work.

We configured and properly sized OPcache so PHP could keep compiled code in memory instead of processing the same files from scratch for every request.

We adjusted php-fpm according to the server’s actual available memory and the website’s workload, ensuring that enough PHP processes were available to handle traffic without consuming memory unnecessarily.

We Added Server-Level Caching.

One of the most effective optimisations was introducing a caching layer at the web server level.

For pages that can safely be cached, nginx can respond directly to the visitor without running the entire WordPress → PHP → database chain for every request.

The difference can be substantial.

Instead of every request requiring PHP execution and database queries, a significant portion of requests can be served directly by the web server.

This means both faster response times and less load on the CPU and database.

We Optimised the Database.

WordPress relies heavily on its database, so we reviewed its configuration as well.

We increased the memory available for database caching so frequently accessed information could remain in RAM, reducing the number of disk operations.

This doesn’t mean simply allocating as much memory as possible to the database. PHP, the database, the operating system, and the web server cache all share the same physical resources.

The important part is finding the right balance between them.

We Moved Backups Outside the Public Web Directory.

We also reviewed how backups were being stored.

The website was using UpdraftPlus, with generated backup archives stored within the public WordPress directory structure.

Although access to these files can be restricted through web server configuration, we prefer a simpler rule: if a file should never be accessible from the web, it should not be stored inside the website’s public directory in the first place.

We moved the backups to a separate location that cannot be accessed directly over HTTP.

This means that even a future nginx or WordPress configuration mistake cannot accidentally turn a backup archive into a publicly downloadable file.

Same Website, Better Server.

From a visitor’s perspective, almost nothing has changed.

The website looks exactly the same and does exactly what it did before. In many situations, however, it now responds faster.

The important difference is underneath.

The surface exposed to the Internet is smaller. Administrative access is tightly controlled. Unnecessary services have been removed. The cryptographic configuration is up to date. PHP and the database use memory more efficiently, while caching significantly reduces the amount of work required to serve pages.

None of these changes is particularly spectacular on its own.

Together, however, they make the difference between simply having a website that “works” and having an actively managed WordPress web hosting environment where security and performance are continuously maintained.

This Is What Managed Web Hosting Means.

At ServerHost, managed web hosting means more than simply providing a server with WordPress installed on it.

It means taking care of the infrastructure behind the website: securing access, configuring the web server, PHP and database, keeping components up to date, monitoring resources, managing backups, and optimising performance.

Infrastructure changes, software evolves, and a configuration that was perfectly reasonable a few years ago can often be improved today.

And if you already have a WordPress website running on your own server, a VPS, or with another hosting provider, we can take over its management, review the existing configuration, and identify what can be improved in terms of security, performance, and ongoing administration.