Skip to content
Plugin PantryPlugins

Plugins / Pantry Login

Plugin Pantry

Pantry Login

v1.0.0

Contents: Limit login attempts and move the login page.

25 KB, no external requests

Stop password guessing with a lockout after a few failed attempts, and move the login page to an address of your own. Errors stop revealing whether the username exists. Put your logo on the login form.

Compared with the popular plugins

The Pantry Login settings screen in the WordPress admin, at Settings > Pantry Login.

What it does

  • Lock out an IP and username after a set number of failed attempts within a window, for a set number of minutes
  • Remaining-attempts message and a clear lockout message on the form
  • Lockout log of the last 50 events with a masked IP, username and time, stored in one option
  • Optional trust of a proxy header for the real IP, off by default
  • Custom login address, with wp-login.php and direct wp-admin access for visitors sent to a 404
  • Generic error message so the form never confirms a username
  • Login form logo with a link to the home page

What it does not do

  • No two-factor authentication
  • No CAPTCHA
  • No IP allow or deny lists
  • No country blocking
  • No external requests

Measured footprint

Zip size
25 KB
Lines of PHP
1,935
Options
pantry_login_settings, pantry_login_log, pantry_login_version
Post meta
none
Custom tables
none
Post types
none
Cron events
none
Transients
pantry_login_c_<md5 of address and username>, pantry_login_i_<md5 of address>, pantry_login_lp_<md5 of address and username>, pantry_login_li_<md5 of address>
Admin assets
includes/core/assets/pantry-admin.css on the settings screen only, includes/core/assets/pantry-admin.js on the settings screen only
Front-end assets
one inline style block on the login page, printed only when a logo is set
External requests
none
Measured on
2026-09-12

Compatibility

WordPress
6.4 or newer, tested to 7.1
PHP
8.1 or newer
Where it lives
Settings > Pantry Login
Licence
GPLv2 or later

Documentation

Limit login attempts and move the login page.

Pantry Login counts failed logins, locks out the address that made them, stops the form from confirming which usernames exist, serves the login form at an address of your choosing, and puts your own logo above it.

Settings

Settings > Pantry Login. Everything lives on one screen, in one option (pantry_login_settings).

Failed attempts
Setting Default What it does
Lockout On Turns the counting and the lockout on or off. Everything else in this section still applies to the message only when this is off.
Attempts allowed 5 Failed attempts before the address is locked out.
Counting window 15 minutes How long a failed attempt is remembered. Each new failure restarts the window.
Lockout length 15 minutes How long the address is refused for.
Remaining attempts On Adds "You have 3 attempts left" to the error on the form.
Error message On Replaces "unknown username" and "the password you entered for the username x is incorrect" with one message that says neither.
Proxy header Off Reads the visitor address from the first entry in X-Forwarded-For instead of REMOTE_ADDR. Only switch this on when a proxy or CDN in front of the site sets that header, because anyone can send it.

Two counters run at once: one for the address, one for the address and username together. Whichever reaches the limit first starts the lockout, and both the address and that username are refused until it ends. A successful login clears both counters for that address. Counters and lockouts are transients, so they expire on their own and they never grow the database.

Login address
Setting Default What it does
Custom address Off Serves the login form at your own address.
Address my-login One path segment. Saved through sanitize_title(), so My Login becomes my-login.

With this on, https://example.com/my-login/ shows the login form, and wp-login.php and wp-admin return a 404 to anyone who is not logged in. WordPress emits the new address everywhere it would have printed wp-login.php: wp_login_url(), wp_logout_url(), wp_lostpassword_url(), the form action and the links in emails. Logging out, password-protected posts and password-reset links that carry a key still work through wp-login.php itself, because those arrive from links that were sent before the address changed.

Save the screen before you log out, and keep the address somewhere safe. If you lose it, add this to wp-config.php, load wp-login.php, and remove it again:

add_filter( 'option_pantry_login_settings', function ( $settings ) {
	$settings['hide_login_enabled'] = false;
	return $settings;
} );

The address is refused if it is empty, if WordPress reserves it (wp-admin, wp-json and similar), or if a published post or page already uses it. In that case the setting is switched back off and the screen says why.

Login form logo
Setting Default What it does
Logo none Image shown above the login form instead of the WordPress logo. The link points at your home page and its text is the site name.
Logo width 84px Width in pixels. The height follows the image's own proportions.

Nothing is printed on the login page unless a logo is set.

Lockout log

The last 50 lockouts are listed under the settings, newest first: when, the address with its last octet (or last hextet) replaced by xxx, the username that was tried, the attempts counted and how long the lockout was. The whole log is one option, pantry_login_log, and it never holds more than 50 entries.

Two buttons sit under the table. Release every lockout deletes the lockouts and counters for every entry in the log, which is how you let someone back in before their lockout ends. Clear the log empties the table.

Hooks

pantry_login_locked

Fires when an address is locked out. The array holds the masked address, the username that was tried, the attempts counted, the lockout length in minutes and the timestamp it ends.

add_action( 'pantry_login_locked', function ( array $event ) {
	error_log( sprintf( '%s locked out after %d attempts on %s', $event['ip'], $event['attempts'], $event['username'] ) );
} );
pantry_login_generic_message

Filters the one message that replaces the username-revealing errors.

add_filter( 'pantry_login_generic_message', function ( string $message ) {
	return '<strong>' . esc_html__( 'Error:', 'my-theme' ) . '</strong> ' . esc_html__( 'Those details did not work.', 'my-theme' );
} );

What it stores

Three options (pantry_login_settings, pantry_login_log, pantry_login_version) and transients named pantry_login_c_, pantry_login_i_, pantry_login_lp_ and pantry_login_li_ followed by a hash. No tables, no post types, no cron events, no post meta, and no request ever leaves your server. Uninstalling removes all of it.

Scope

This plugin does not do two-factor authentication, CAPTCHAs, IP allow or deny lists, or country blocking, and it never calls out to another service.

Pro add-on (planned)

See Pantry Pro pricing
  • Two-factor authentication with recovery codes
  • IP allow and deny lists
  • Login notifications
  • Cloudflare Turnstile

None of this is in the free plugin, and none of it is switched off inside it. Pro would be a separate plugin.

Changelog

All notable changes to Pantry Login are recorded here. The format follows Keep a Changelog, and the project uses semantic versioning.

1.0.0 - 2026-09-12

  • First release.
  • Lockout after a set number of failed attempts within a window, counted per address and per address and username together.
  • Remaining-attempts message and a lockout message with the time left, shown on the login form.
  • Lockout log of the last 50 events with a masked address, the username tried and the time, held in one option.
  • Buttons to release every recorded lockout and to clear the log.
  • Optional trust of the X-Forwarded-For header for sites behind a proxy, off by default.
  • Custom login address, with wp-login.php and wp-admin returning a 404 to logged-out visitors.
  • One generic error message so the form never confirms that a username exists.
  • Login form logo linked to the home page.
  • pantry_login_locked action and pantry_login_generic_message filter.