Locking Down WordPress with AdminEase: Maintenance Mode & Password Protection

Search the docs

⌘ K
Try "heartbeat", "restore from S3", or "WP-

Popular

License activation

WP-CLI install

Restore a backup

Hooks reference

What you'll have when you finish

A WordPress install you can take offline behind a friendly 503 maintenance page during a migration, gate behind a single shared password during a staging cycle or soft launch, scope so that only specific pages are protected (or only specific pages are exempt), and configure so that user registration is off, post-login redirects go where you want them, and login sessions expire on a schedule. All five features ship in the free AdminEase, and all five are reversible from the same settings screens.

  • Prerequisites: WordPress 5.0+, PHP 7.4+, and a basic AdminEase install.
  • You'll need access to: a WordPress admin account, and the ability to test as both a logged-in admin and a logged-out visitor (use an incognito window).
  • Time: 15 to 20 minutes for the lockdown features, another 5 to 10 for the related access toggles.
Test in an incognito window Both maintenance mode and password protection have admin bypass logic. If you stay logged in and just refresh, you will keep seeing the normal site and assume nothing happened. Always verify in a private window or a second browser where you are logged out.
The walkthrough
  1. When to reach for maintenance mode versus password protection
  2. Configure and enable maintenance mode
  3. What maintenance mode actually sends to visitors and search engines
  4. How AdminEase's password protection works under the hood
  5. Set the site password and the session length
  6. Scope protection: excluded pages, included pages, bypass archives
  7. IP binding, brute-force lockout, and the access log
  8. Pair it with disable frontend user registration
  9. Redirect after login and logout
  10. Auto-logout for stale sessions

Five features sit in this tutorial. The first two are different ways to take the site away from visitors: maintenance mode shows a friendly "we'll be back" page, full-site password protection gates the site behind a shared password. The other three tighten what happens when users do get in: disable frontend registration stops anonymous sign-ups, redirect after login and logout controls where users land, and auto-logout sets an expiry on stale sessions.

Each section names the exact path. Most of what we'll touch lives under AdminEase › Security › Site Lock and AdminEase › Users › Authentication. Maintenance mode is the odd one out: it sits under AdminEase › Debug › Maintenance Mode, on the principle that taking a site offline is a debugging or operational action, not a security action.

1. When to reach for maintenance mode versus password protection

These two features look superficially similar (both interrupt the normal site for visitors, both let admins through, both render a templated page) but they solve different problems.

Reach for maintenance mode when: the site is being changed and you do not want anyone to see broken intermediate states. Migrating to a new host, running a major plugin update, restructuring URLs. The audience is "everyone on the internet," and the message is "we'll be back shortly." Search engines need to know this is temporary, not a permanent removal.

Reach for password protection when: the site is finished but the audience is restricted. Pre-launch reviews for a client, a staging cycle where stakeholders need to click through, a private blog that only invited readers should see. The audience is "people who have the password," and the gate stays up until you remove it.

The SEO difference Maintenance mode returns HTTP 503 with a Retry-After header. Search engines treat this as temporary and come back later. Password protection returns a normal HTML page (the password form) with a 200 response. To search engines, that just looks like your site's content, which is not what you want long-term. If you intend a site to be private for weeks or months, add noindex headers via your theme or a separate plugin alongside the password protection.

2. Configure and enable maintenance mode

Maintenance mode replaces the front-end of the site with a single templated page for every logged-out visitor. Admins (anyone with the edit_posts capability) bypass it automatically and see the site normally, which is what makes it safe to flip on without locking yourself out.

Enable it: Go to AdminEase › Debug › Maintenance Mode › Enable Maintenance Mode. Toggle on. A panel of child fields appears: page title, headline, message, three colors (primary, secondary, text), a toggle to show your site logo from the Customizer, and the SEO Retry-After value in seconds. Set them, save, then verify in an incognito window.

The defaults are sensible: page title set to {your blog name} - Maintenance Mode, headline set to your blog name, message set to "We are currently performing scheduled maintenance. Please check back soon!", colors at WordPress-admin blue and dark grey, and Retry-After at 3600 seconds (1 hour). The message field accepts basic HTML, so you can add a link to your status page, a Twitter handle, or an expected return time.

Pro tip Set Retry-After to a realistic estimate of when you'll be done. If you say one hour and finish in twenty minutes, search engines may still wait. If you say one hour and take six, they may come back early, find the maintenance page again, and slow their crawl rate. The honest number serves you better than the optimistic one.

3. What maintenance mode actually sends to visitors and search engines

When maintenance mode is active and a logged-out visitor hits the site, AdminEase intercepts the request at template_redirect priority 0 (early enough that no template loading happens) and emits the following:

  • HTTP status: 503 Service Temporarily Unavailable.
  • Retry-After header, set to the value you configured (default 3600). Setting Retry-After to 0 in the settings disables this header.
  • Cache-busting headers: Cache-Control: no-store, no-cache, must-revalidate, max-age=0 plus Pragma: no-cache.
  • Three PHP constants defined for cooperating cache and minification plugins: DONOTCACHEPAGE, DONOTCACHEOBJECT, and DONOTMINIFY. WP Rocket, W3 Total Cache, Autoptimize, and most major caching plugins honor these.

The Classic theme renders the page using your configured colors, headline, message, and (optionally) the Customizer logo. The full output HTML is passed through the adminease_maintenance_mode_html filter before being echoed, so a developer can replace the template entirely from a mu-plugin if needed.

If you use a CDN, purge it Cloudflare, BunnyCDN, KeyCDN, and similar networks may have cached the previous page. Even with the no-cache headers in place, edge caches will not pick up the change until they expire or get purged. Purge the cache the moment you enable maintenance mode, and again when you disable it.

4. How AdminEase's password protection works under the hood

Before configuring it, understand the mechanism. Password protection in AdminEase is stateless: it does not use PHP sessions and it does not store anything per-visitor in the database. Authentication is carried entirely in a signed cookie. This matters because PHP sessions break page caches (every visitor gets a unique session cookie, defeating the cache key), and stateless cookie auth does not.

The mechanics, in order:

  1. Visitor submits the site password through the form. The submission goes via AJAX, with a nonce.
  2. AdminEase checks the submitted password against the stored hash using WordPress's wp_check_password(). The stored value is a phpass, bcrypt, or argon2 hash. The plaintext is never stored. If a site is migrating from an older AdminEase that stored plaintext, the first successful login transparently rewrites the stored value as a hash.
  3. On success, AdminEase issues a cookie containing a JSON blob: {v: 2, t: issued-timestamp, e: expiration-timestamp, h: HMAC-SHA256-signature}. The signature key is derived from wp_salt('auth') and the stored password hash, so changing the password instantly invalidates every existing cookie on the site.
  4. The cookie is set with HttpOnly, Secure (when SSL is active), and SameSite=Lax. The cookie name is adminease_pps_auth_ followed by a CRC32 hash of the site's home URL, which keeps multi-site installs separated.
  5. On every subsequent request, AdminEase reads the cookie, verifies the signature with hash_equals() (timing-safe), and lets the request through if it matches.

Failed attempts are tracked per-IP via a WordPress transient (no extra database table). After 5 failed attempts within a 30-minute window, the IP is locked out for the rest of the window. Successful login clears the counter.

5. Set the site password and the session length

Enable it: Go to AdminEase › Security › Site Lock › Enable Password Protection. Toggle on. The child fields appear. Set the site password in the "Site Password" field. Save. The field then displays masked dots, the description confirms a password is saved, and the value itself is never displayed back.

Choose a strong password (long, random, not reused). The "Force strong passwords" feature from Article 1 does not apply to the site password, because that is a different authentication flow. Pick something that would survive a brute-force attempt even without the rate-limit lockout.

Session length is governed by the password_protect_site_remember_device setting. The defaults: if "remember device" is not requested at login, the cookie is a browser-session cookie and expires when the browser closes. If "remember device" is requested, the cookie persists across browser sessions for 1 day. Both can be overridden via the adminease_password_protect_site_remember_device_expiration filter from a mu-plugin if your use case needs a longer remember window.

What "remember device" really stores The remember-device cookie is bound to the password hash. If you change the site password, every "remembered" device on the site loses access immediately and has to re-authenticate. This is the right behavior for a private site: rotating the password actually rotates access.

6. Scope protection: excluded pages, included pages, bypass archives

The default behavior of password protection is "gate the whole site." You can narrow that in two opposite directions:

  • Excluded pages: a multi-select of any published post, page, or custom post type. Selected items bypass protection while everything else stays gated. Typical use: keep the privacy policy and contact page public on an otherwise password-gated site.
  • Included pages: the inverse. When set, ONLY the selected items show the password form, and everything else passes through unprotected. Typical use: protect a single landing page or a small group of pages on an otherwise public site.
  • Bypass on archives & home: a single toggle that lets archive pages, the blog index, the front page, search results, and 404 pages through without authentication. Useful for sites where the homepage is meant to be public but individual articles are gated.
Included and excluded are mutually exclusive in practice If you set both lists, the included list wins: only those pages get the password form, and the excluded list is irrelevant because everything outside the included list is already bypassed. Pick one approach and use it consistently. The mental model is: included = "protect only these," excluded = "protect everything except these."

Both lists support any public post type, not just pages. The selector queries via AJAX as you type, so it scales to thousands of posts without slowing the settings page.

7. IP binding, brute-force lockout, and the access log

Three more controls round out the password protection feature.

Bind Authentication To IP is a toggle that adds the client IP hash to the cookie signature payload. When enabled, the cookie becomes invalid the moment the visitor's IP changes. The trade-off is security versus convenience: it stops a stolen cookie from being replayed elsewhere, but it also logs out mobile users who switch between Wi-Fi and cellular. Leave it off if your audience is mobile-heavy, turn it on for a desktop-only audience like an agency review portal.

Brute-force lockout is on by default and not configurable from the UI. After 5 failed password attempts from the same IP within 30 minutes, that IP gets a "too many attempts" response on every subsequent attempt until the window expires. The counter is stored as a per-IP transient (key derived from md5(client_ip)) and the window is anchored on the first attempt, not the most recent, so the lockout is a fixed half-hour rather than a sliding one.

Access log records every authentication attempt (success, failure, lockout) with timestamp, IP, user agent, status, and (for failures) a SHA-256 hash of the attempted password. The default retention is 1000 entries, configurable up to 10000 or set to 0 to disable logging entirely. The log is stored as a non-autoloaded WordPress option, so it does not bloat every page load even when long.

Use it: The access log table renders directly below the password protection settings in the admin. There is a button to refresh, and a button to download the full log as a CSV (with a UTF-8 BOM so Excel reads non-ASCII characters correctly). The downloaded filename includes a UTC timestamp.
What you can do with the log Two things worth doing: scan the log periodically for repeat failures from the same IP and consider adding that IP to a server-level block, and verify that "success" entries match real reviewers you expected (not strangers who guessed correctly). Pattern recognition matters more than individual entries.

8. Pair it with disable frontend user registration

If you have password protection on a public site, or you have a finished site that should not accept new user accounts, the frontend registration form is dead weight. AdminEase has a one-toggle disable that handles it on four levels at once.

Enable it: AdminEase › Users › Authentication › Disable user registration. Save.

When enabled, AdminEase:

  1. Sets the WordPress core option users_can_register to 0 on every init hook at priority 1 (so even if a plugin re-enables it, it gets reset).
  2. Blocks the default wp-login.php?action=register form by returning a 403 page titled "Registration Disabled" when that URL is requested.
  3. Filters register_url to return an empty string, so any theme code that prints a "Register" link gets nothing.
  4. Registers a REST API override at POST /wp/v2/users that returns a 403 with the message "User registration is disabled." This blocks programmatic registration via the REST API.
What this breaks Any plugin that uses the frontend registration flow to onboard users: WooCommerce checkout-as-new-user, BuddyPress signups, LMS course registrations. If your site genuinely needs frontend registration for paying customers or members, leave this off and rely on those plugins' own anti-spam and approval workflows instead.

9. Redirect after login and logout

By default, WordPress sends users to the admin dashboard after login and to the login page after logout. Neither default is what you want on most non-admin sites: editors get dropped into an admin they do not need to see, and logged-out users end the journey on a generic WP login screen rather than back at your homepage.

Configure login redirect: AdminEase › Users › Authentication › Redirect after login. Toggle on. Enter the full URL where users should land after login (your homepage, a member dashboard page, a welcome page). Save.
Configure logout redirect: Same path, scroll to Redirect after logout. Toggle on. Enter the post-logout URL. Save.

Behind the scenes, AdminEase hooks into wp_login at priority 999 (high enough to run after most other plugins that might also redirect, so the AdminEase setting wins) and wp_logout at priority 1. Both redirects use wp_redirect() with esc_url_raw() on the configured URL.

Same redirect for all roles The current implementation sends every user to the same URL regardless of role. If you need role-aware redirects (admins to the dashboard, subscribers to a profile page, customers to "my account"), you need a role-aware login redirect plugin or a custom wp_login hook. AdminEase's redirect is a global one-URL-fits-all setting.

10. Auto-logout for stale sessions

The default WordPress login session lasts two days (48 hours), or 14 days if "remember me" is checked. For most sites that is too long. A laptop left on a coffee-shop table with WordPress admin open is a real, common scenario, and the longer the session, the larger the window of risk.

Enable it: AdminEase › Users › Authentication › Auto-logout user. Toggle on. A "Auto-logout user after X seconds" dropdown appears with sensible presets (1 minute, 5, 10, 15, 20, 30, 45, 1 hour, 2 hours, 4 hours, 8 hours, 12 hours, 1 day, 1 week, 1 month, Other). Pick a value. Save.

What it actually does: AdminEase filters auth_cookie_expiration and returns your configured value instead of the WordPress default. Existing sessions keep their original expiry (the cookie is already issued), but every new login from this point on will get a session that expires after your chosen interval. The filter is exposed as adminease_auth_cookie_expiration for further customization in code.

For agency-managed client sites, 8 hours is a reasonable default: long enough that an editor working a full day will not get logged out mid-task, short enough that a forgotten session expires by morning. For higher-security contexts (financial, healthcare, anything regulated) 30 minutes to 1 hour is more appropriate.

This is session length, not idle timeout Auto-logout fires when the cookie expires, regardless of whether the user has been active. WordPress does not have a built-in "log out after X minutes of inactivity" mechanism. If you need true idle-based logout (logout after no activity for N minutes), you need a session-tracking plugin that watches user activity in JavaScript and triggers a logout, which is a different feature than this one.

Where to go from here

You now have two distinct ways to make a WordPress site unavailable to visitors (maintenance mode for "temporarily down" with proper SEO signals, password protection for "permanently private" with a stateless cookie gate), plus the three access toggles that pair naturally with both: no anonymous registration, controlled post-login destinations, and session expiry that matches your risk tolerance.

The companion tutorials in the security set cover the layers above and below this one. Below: "Hardening WordPress Security with AdminEase" closes the most-exploited attack surfaces at the configuration layer. Above: "Geo-Blocking & Bot Protection" filters traffic by country and bot identity at the web-server layer. Together the three tutorials cover most of what AdminEase's Security tab does.

Frequently asked questions

Can I use maintenance mode and password protection at the same time?

Yes, and they layer in a specific order. Maintenance mode runs first (at template_redirect priority 0). Password protection also hooks template_redirect at priority 0 but checks is_user_logged_in(). If maintenance mode is on, logged-out visitors get the maintenance page before they ever see the password form. If you specifically want the password form to be reachable during a maintenance window (for client previews), you have to gate maintenance mode with the adminease_maintenance_mode_check_access filter, returning true for password-protected visitors.

Will password protection break my page cache?

No, by design. The authentication is carried in a single cookie that varies between authenticated and unauthenticated visitors, but the cookie name is fixed and predictable. Most page-cache plugins can be configured to vary cache keys on the presence of this cookie. Without that configuration, cached pages may briefly show to unauthenticated visitors and vice versa. WP Rocket's "User Cache" and W3 Total Cache's "Vary by cookie" options both handle this. On host-managed caches (WP Engine, Kinsta), open a support ticket and reference the cookie name adminease_pps_auth_*.

What happens if I forget the site password?

The password is stored hashed, so it cannot be recovered. Reset it by going to AdminEase › Security › Site Lock › Site Password in the admin and entering a new value. (You can still get into the admin because is_user_logged_in() bypasses the password gate.) If you have somehow lost both the WordPress admin password and the site password, you need standard WordPress recovery: SFTP to the server, reset the WP admin via WP-CLI or the database, then reset the site password from the dashboard.

Can different team members have different site passwords?

Not in the current release. The Site Lock feature uses a single shared password for all gate-passers. If you need per-user access, the right tool is the regular WordPress user system (give your reviewers actual user accounts) and password protection is the wrong layer. Site Lock is intended for short-term shared-secret access (a soft launch, a beta cycle, a client review), not for ongoing per-user authentication.

Do these features work on a multisite network?

Maintenance mode and password protection are configured per site, not network-wide. The cookie name includes a CRC32 hash of home_url(), which keeps authenticated state separated between sites in the same network: a visitor authenticated on site-a.example.com is not automatically authenticated on site-b.example.com. The other three toggles (registration, redirects, auto-logout) work per-site as well.

If I enable auto-logout at 30 minutes, does that log out users mid-session?

No. Auto-logout sets the expiry on new auth cookies issued at login. A user who was already logged in keeps their existing session until that cookie's original expiry passes. The new shorter expiry kicks in on their next login. If you need to force-expire current sessions immediately, use Users › Your Profile › Log Out Everywhere Else on each user, or programmatically destroy session tokens via WP-CLI.

Was this article helpful?

On this page
Back to top
Copy link to article