How I Fixed Fail2ban, Plugin Lockouts and WP-CLI Problems on AWS Lightsail
Getting locked out of WordPress sounds simple.
Reset the password.
Log back in.
Done.
Except sometimes there are multiple security systems involved, and each one can block you independently.
That is exactly what happened to me on a WordPress site hosted on AWS Lightsail.
I had just taken over the management of the site and discovered that the admin login details I had been provided with weren’t working. The client had left their previous WordPress guy due to communication issues, so while I could have emailed him and asked for the password to be reset, how hard could resetting a WordPress password be when you have SSH access.
Ugh.
What looked like one login problem turned out to involve:
- fail2ban
- Admin Site Enhancements
- Wordfence
- WP-CLI
- multiple PHP versions
- a non-standard WordPress file layout
- and a database password that wasn’t actually written in
wp-config.php
This is the route I took to regain access.
The first problem: Fail2ban blocked my entire IP
The site had a custom fail2ban jail:
[wordpress-bots]
enabled = true
port = http,https
filter = wordpress-auth
logpath = /var/log/apache2/access.log
maxretry = 3
findtime = 300
bantime = 604800
The filter was:
failregex = ^<HOST> .* "(GET|POST) .*(wp-login.php|xmlrpc.php)
At first glance that looks reasonable.
In practice, it is far too broad.
It does not detect failed WordPress logins.
It detects requests to the WordPress login page.
That means:
3 visits to wp-login.php within 5 minutes
=
7 day ban
My IP was blocked from both port 80 and 443.
The first sign was that the website suddenly stopped loading from my browser.
SSH still worked because port 22 was unaffected.
How I checked the ban
The jail status showed:
sudo fail2ban-client status wordpress-bots
and my IP appeared in the banned list.
I removed it with:
sudo fail2ban-client set wordpress-bots unbanip YOUR.IP.ADDRESS
Then I temporarily whitelisted my IP while working:
sudo fail2ban-client set wordpress-bots addignoreip YOUR.IP.ADDRESS
That got browser access back.
But I still could not log into WordPress.
The second problem: WordPress itself had locked me out
The login screen displayed a message along the lines of:
You've been locked out.
You can login again in 15 minutes.
My first assumption was Wordfence.
That was wrong.
I deactivated Wordfence and the message remained.
So instead of guessing, I searched the plugin directory for the exact wording:
sudo grep -Rni "login again in" /var/www/html/wp-content/plugins 2>/dev/null
That returned:
admin-site-enhancements/classes/class-limit-login-attempts.php
The lockout was coming from Admin Site Enhancements.
That was a useful lesson in itself.
When WordPress shows a specific error message, searching the plugin source for that exact phrase can be faster than guessing which plugin is responsible.
I temporarily disabled ASE and the lockout disappeared.
The third problem: password reset email wasn’t a reliable option
The account existed, but the credentials supplied by the previous IT provider were not working.
I wanted to confirm the user and reset the password directly.
That meant using WP-CLI.
Simple enough.
Except WP-CLI immediately failed.
WP-CLI said PHP was missing the MySQL extension
The error was:
Your PHP installation appears to be missing the MySQL extension which is required by WordPress.
That was confusing because the live WordPress site was clearly connecting to MySQL.
So the site itself had a working MySQL PHP extension.
The problem turned out to be the command-line PHP version.
Running:
which php
php -v
showed:
PHP 8.5.x CLI
But the installed MySQL extensions were for PHP 8.2, 8.3 and 8.4.
PHP 8.5 CLI did not have mysqli.
I confirmed PHP 8.2 did:
php8.2 -m | grep -Ei 'mysqli|pdo_mysql'
which returned:
mysqli
pdo_mysql
So instead of:
wp user get username
I ran WP-CLI explicitly through PHP 8.2:
php8.2 $(which wp)
That solved the PHP extension issue.
The fourth problem: WP-CLI couldn’t find WordPress
The next error was:
This does not seem to be a WordPress installation.
I had been running:
--path=/var/www
because that was where wp-config.php lived.
But WordPress core itself was somewhere else.
I found the real installation path with:
sudo find /var/www -name wp-load.php -type f 2>/dev/null
That returned:
/var/www/html/wp-load.php
So the correct command became:
php8.2 $(which wp) --path=/var/www/html
That worked.
Why wp-config.php was in a different directory
The server was using a perfectly valid WordPress layout:
/var/www/wp-config.php
/var/www/html/wp-load.php
/var/www/html/wp-admin/
/var/www/html/wp-includes/
WordPress allows wp-config.php to live one directory above the core installation.
So the config path and the WordPress root are not always the same thing.
That is worth remembering when WP-CLI says it cannot find WordPress.
The fifth problem: the database password wasn’t visible in wp-config.php
I also wanted to inspect the database directly.
The configuration showed:
define( 'DB_NAME', 'wordpress-db' );
define( 'DB_USER', 'user' );
define( 'DB_PASSWORD', $db_password );
So the password was not stored directly in the file.
Further down, the config showed:
$cmd = 'tail -n 1 /opt/aws/wordpress/credentials.log';
$db_password = shell_exec($cmd);
The database password was being loaded dynamically from:
/opt/aws/wordpress/credentials.log
That was another reminder not to assume every WordPress installation has conventional hosting defaults.
Confirming the WordPress user
Once WP-CLI was running correctly, I checked the user:
php8.2 $(which wp) --path=/var/www/html user get peter-pc
That confirmed:
user_login: peter-pc
user_email: peter@example.com
roles: administrator
The account existed.
The email was correct.
So all I needed to do was set a new password.
But remember, requesting a new password was not an option because sending emails had been disabled on this WordPress installation.
Resetting the password with WP-CLI
The working command was:
php8.2 $(which wp) --path=/var/www/html user update peter-pc --user_pass='NEW-STRONG-PASSWORD'
That bypassed the need for email-based password recovery entirely.
Once ASE was disabled and fail2ban was no longer blocking my IP, I could log in using the new password.
Why this problem was more complicated than it looked
There were actually three independent lockout layers.
Layer 1: Server-level protection
Fail2ban blocked my IP from the website.
Layer 2: WordPress-level login protection
Admin Site Enhancements locked the account/IP after repeated login attempts.
Layer 3: Recovery tooling
WP-CLI initially failed because it was using the wrong PHP version and wrong WordPress path.
Each problem had to be solved separately.
That is why simply “resetting the password” didn’t work.
Useful commands if you’re dealing with something similar
Check Fail2ban
sudo fail2ban-client status
Check a specific jail:
sudo fail2ban-client status wordpress-bots
Unban an IP:
sudo fail2ban-client set wordpress-bots unbanip YOUR.IP.ADDRESS
Search plugins for a lockout message
sudo grep -Rni "locked out" /var/www/html/wp-content/plugins 2>/dev/null
Check which PHP WP-CLI is using
which php
php -v
php -m | grep -Ei 'mysqli|pdo_mysql'
Find the actual WordPress directory
sudo find /var/www -name wp-load.php -type f 2>/dev/null
Run WP-CLI with a specific PHP version
php8.2 $(which wp) --path=/var/www/html user list
Reset a WordPress password
php8.2 $(which wp) --path=/var/www/html user update USERNAME --user_pass='NEW-PASSWORD'
What I would change permanently
The biggest issue was the fail2ban filter.
This:
failregex = ^<HOST> .* "(GET|POST) .*(wp-login.php|xmlrpc.php)
is not really detecting abuse.
It is detecting access.
A better setup should distinguish between genuine failed authentication and simply loading a WordPress endpoint.
I would also avoid stacking multiple aggressive login protection systems unless there is a good reason.
This site had:
- Fail2ban
- Admin Site Enhancements login limits
- Wordfence
- Really Simple Security
That is a lot of overlapping security logic.
More security plugins do not automatically mean better security.
Sometimes they just make recovery harder.
The broader lesson
The biggest thing I took away from this was that WordPress troubleshooting is often about understanding layers.
A login problem might be:
- browser-side
- CDN-side
- firewall-side
- server-side
- PHP-side
- WordPress-side
- plugin-side
- database-side
The fastest route is usually not to guess.
It is to prove which layer is failing.
That is what eventually turned a frustrating lockout into a straightforward fix.
If you’ve inherited a WordPress site with old plugins, unclear hosting, custom security rules or mystery server configuration, I help businesses work out what is actually happening and stabilise it properly.