If your WordPress homepage loads fine but every other page — posts, categories, even wp-admin sometimes — returns a 404 right after you changed the permalink structure under Settings → Permalinks, this is a server rewrite-rule problem, not a WordPress bug. The fix is different depending on whether your site runs on Apache or Nginx, and giving the wrong one the wrong fix (or checking the wrong config file) is the most common reason people stay stuck on this for hours.

Symptoms

  • The homepage (/) loads normally, but any individual post or page URL (e.g., /2026/07/my-post/ or /sample-page/) returns a 404 "Page not found."
  • The 404 is coming from WordPress's own 404 template (styled like the rest of your site), or a raw server-level 404 with no WordPress styling at all — this distinction matters (see Likely causes below).
  • Switching Settings → Permalinks back to "Plain" temporarily fixes all the URLs (they just look ugly, like ?p=123).
  • This started immediately after changing the permalink structure, migrating hosts, or restoring from a backup.

Likely causes, in order of how often they actually happen

  1. On Apache: the .htaccess file wasn't regenerated or AllowOverride is disabled. WordPress writes its rewrite rules into .htaccess in the site root. If that file is missing, has stale rules from a migration, or the server's config has AllowOverride None for that directory, Apache never applies WordPress's rewrite rules at all — hence every non-homepage URL 404s.
  2. On Nginx: there's no try_files directive for WordPress in the server config. This is the single biggest point of confusion for people coming from Apache. Nginx does not read .htaccess files — at all, ever, no exceptions. WordPress's "pretty" permalinks depend entirely on the actual Nginx server block having a rewrite rule (almost always a try_files $uri $uri/ /index.php?$args; line, or equivalent) already written into it. If that line is missing, was removed, or the config was regenerated without it after a migration, Nginx returns a raw 404 for anything that isn't a literal file on disk.
  3. A caching or reverse-proxy layer is serving a stale 404 it cached before the permalink change. Less common, but if you have a page cache, CDN, or object cache in front of the site, it may have cached the old error state.

How to tell if you're on Apache or Nginx

If you're not sure, check one of these before doing anything else:

  • Hosting control panel: aaPanel, cPanel, and most managed WordPress hosts state the web server type directly on the dashboard or in your hosting plan details.
  • Ask your host's support — a one-line question, and the fastest way to be certain if you have no panel access.
  • Response headers: in your browser's developer tools (Network tab), reload the site and check the Server response header on the main document request. It will typically say Apache, nginx, LiteSpeed, or openresty (which is Nginx-based). Note that some hosts intentionally hide or rewrite this header, so treat it as a strong hint, not absolute proof.

Fix it: lowest-risk steps first

Step 1 — Re-save permalinks from within WordPress (works for both server types, try this first)

  1. Go to Settings → Permalinks in wp-admin.
  2. Without changing anything, click Save Changes at the bottom.

This forces WordPress to attempt to rewrite .htaccess (on Apache) with fresh rules. It's harmless to try even on Nginx — it won't fix an Nginx config issue, but it costs nothing and resolves a surprising number of Apache cases where .htaccess simply went stale or wasn't writable at the time of the original change.

Step 2 — If you're on Apache: check .htaccess exists and AllowOverride is enabled

  1. Using FTP or your hosting file manager, look in the WordPress root directory (same folder as wp-config.php) for a file named .htaccess. Note it's a hidden file — make sure your FTP client or file manager is set to show hidden/dotfiles.
  2. If it's missing, create a new .htaccess file there and paste in WordPress's default rewrite block (found in the Codex/WordPress.org documentation under "htaccess"), then repeat Step 1 to let WordPress regenerate the rest.
  3. If the file exists but rules still don't apply, the server's Apache config likely has AllowOverride None set for your site's directory. This requires editing the Apache virtual host config (not .htaccess itself) to AllowOverride All for the WordPress directory — on managed/shared hosting this is usually something only your host can change; on a VPS you control, it's in the <Directory> block of your site's Apache config, followed by apachectl restart (or your distro's equivalent) to apply it.

Step 3 — If you're on Nginx: confirm a WordPress-aware try_files rule exists in the server config

  1. Ask your host, or check your control panel's site/rewrite settings for a "pseudo-static" or "URL rewrite" option scoped to WordPress. Panels like aaPanel include a built-in WordPress rewrite template specifically for this — applying it writes the correct try_files block into the Nginx config for you without hand-editing files.
  2. If you do have direct access to the Nginx config, confirm the relevant server block includes a line functionally equivalent to:
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
  3. After adding or restoring this, test the Nginx config syntax (nginx -t on a VPS) before reloading, then reload Nginx (nginx -s reload or your panel's restart button).

If you don't have server-level access at all (common on some shared hosts), this step has to go through your host's support — there is no WordPress-side workaround, because the request never reaches WordPress's own rewrite logic without this line in place.

Step 4 — Purge any caching layer or CDN

If Steps 1–3 fixed the server-level rewrite but the site still shows 404s intermittently or for previously-visited URLs specifically, purge your page cache plugin, any server-level cache (Redis/Varnish if applicable), and your CDN's cache (Cloudflare: Caching → Configuration → Purge Everything) to clear out any 404 responses cached before the fix.

Verify the fix

  1. Visit several different URL types directly: a blog post, a static page, a category archive, and the homepage. All should load your actual content, not a 404.
  2. Reload Settings → Permalinks one more time and confirm no error/warning is shown about the permalink structure or a non-writable .htaccess.
  3. Test in a private browser window to rule out a cached 404 in your own browser.

If you need to roll back

If the fix doesn't work or the site becomes unreachable while editing server config, restore the .htaccess file you backed up before starting (Apache), or revert the Nginx config file to its previous version and reload Nginx (Nginx). As an immediate stopgap on any server type, switching Settings → Permalinks back to Plain restores functional (if ugly) URLs while you continue troubleshooting the server-level rewrite separately.

Related fixes

FAQ

Why does only the homepage work and nothing else?

The homepage is typically served as the literal root document regardless of rewrite rules, so it loads even when the server has no idea how to translate /sample-page/ into a request WordPress can answer. Every other URL depends entirely on the rewrite rule (Apache's .htaccess or Nginx's try_files) to redirect the request into index.php where WordPress can parse it.

I switched hosts recently — is that connected to this?

Very likely. Migrations between hosts, especially between an Apache host and an Nginx host (or between panels like cPanel and aaPanel), commonly lose the WordPress-specific rewrite configuration because it isn't part of the WordPress files themselves — it lives in server config that has to be recreated on the new environment.

Can I just leave permalinks on "Plain" instead of fixing the server config?

You can as a temporary measure, but it's not a real fix — plain permalinks (?p=123) are worse for SEO and readability, and any internal links, backlinks, or bookmarks pointing to your pretty URLs will 404 until the underlying rewrite rule is actually restored.

Do I need to touch wp-config.php for this?

No. This is entirely a server-level rewrite issue; wp-config.php has no bearing on permalink 404s.