How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: How to Configure Nginx for a Subdirectory
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Server Management > How to Configure Nginx for a Subdirectory
Server Management

How to Configure Nginx for a Subdirectory

how7o
By how7o
Last updated: May 22, 2026
5 Min Read
Nginx subdirectory configuration with alias and PHP-FPM
SHARE

To configure Nginx for a subdirectory that lives outside your main site’s document root (for example a separate PHP app at example.com/api/ on a WordPress site), use a prefix location block with alias and a nested location for the PHP handler. The classic mistake is letting the top-level location ~ \.php$ regex catch your subdirectory’s PHP files — this guide shows the working pattern.

Contents
  • The problem
  • The working config
  • Why each piece is there
  • Test and reload
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-05-17 on Nginx 1.24 / PHP-FPM 8.2. Originally published 2023-03-13, rewritten and updated 2026-05-17.

The problem

A typical WordPress nginx site uses these two blocks:

location / {
    try_files $uri $uri/ /index.php?$args;
}

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_intercept_errors on;
    fastcgi_pass unix:/tmp/php-cgi.socket;
}

Now you want a separate app at example.com/api/ with its own index.php, living at /var/www/wordpress/api/ on disk. Two things go wrong by default:

  • The top-level location / sends /api/whatever through WordPress’s front controller (/index.php?$args).
  • Even if you add a location /api/ block, the regex location ~ \.php$ still catches every .php request before your prefix block runs — that’s how nginx’s location matching order works.

The working config

location /api/ {
    alias /var/www/wordpress/api/;
    try_files $uri $uri/ @api;

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_intercept_errors on;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/tmp/php-cgi.socket;
    }
}

location @api {
    rewrite ^/api/(.*)$ /api/index.php?/$1 last;
}
Nginx subdirectory routing — alias, nested PHP block, named location fallback

Why each piece is there

  • alias /var/www/wordpress/api/; — replaces the /api/ prefix with that filesystem path. A request for /api/users.php looks for /var/www/wordpress/api/users.php. Use alias, not root, when the URL prefix doesn’t match the directory name on disk.
  • try_files $uri $uri/ @api; — serve the file if it exists, then the directory, otherwise hand off to the named @api location. This is what makes “pretty URLs” like /api/users/42 route to index.php.
  • Nested location ~ \.php$ — putting the PHP handler inside the /api/ block keeps it scoped. Nginx will prefer the nested PHP location for requests already matched by /api/, so it doesn’t fall through to the top-level location ~ \.php$.
  • fastcgi_param SCRIPT_FILENAME $request_filename; — when you use alias, the variable $document_root$fastcgi_script_name (which the stock fastcgi_params uses) builds the wrong path. $request_filename is already the resolved absolute path, so it bypasses that pitfall.
  • location @api { rewrite ... } — the named location front-controller fallback. Anything that doesn’t match a real file or directory becomes /api/index.php?/$1.

Test and reload

# Test config syntax
sudo nginx -t

# Apply without dropping connections
sudo systemctl reload nginx

# Quick smoke test
curl -I https://example.com/api/
curl https://example.com/api/health

If you see File not found from PHP-FPM, the SCRIPT_FILENAME line is the first thing to re-check. If you see WordPress’s 404, the /api/ block isn’t matching at all — confirm it sits in the same server { } block as the WordPress locations and that there’s no earlier server matching the host.

Frequently asked questions

Why use alias instead of root for a subdirectory?

root appends the full request URI (including the /api/ prefix) to the filesystem path, which means files have to live at /var/www/wordpress/api/api/index.php — almost never what you want. alias replaces the matched prefix, so /api/foo maps to {alias}/foo on disk. For subdirectories that don’t mirror the URL, alias is the right choice.

Why does my location ~ \.php$ block hijack PHP requests under /api/?

Nginx evaluates regex location blocks before any prefix locations, so a request like /api/index.php matches ~ \.php$ first and is dispatched to PHP-FPM with the wrong SCRIPT_FILENAME. The fix is to put the PHP handling inside the location /api/ block (nested location) so requests under /api/ resolve there first. The pattern is shown below.

Will this break my WordPress permalinks?

No. WordPress uses the top-level location / { try_files $uri $uri/ /index.php?$args; } block. Requests that match /api/... are caught by the more specific prefix location and never fall through to the WordPress rewrite. Anything outside /api/ still goes to WordPress as before.

Do I need to reload nginx after editing the config?

Yes — config changes only apply after nginx -t (test) and sudo systemctl reload nginx (apply without dropping connections). nginx -t first; a syntax error makes reload a no-op but it’s worth catching before you reload.

Related guides

  • How to Fix Nginx FastCGI “Connection Reset by Peer” Errors
  • How to Configure WordPress Multisite with Subdirectories on Nginx

References

Nginx location matching: nginx.org/en/docs/http/ngx_http_core_module.html#location. alias vs root: nginx.org/en/docs/http/ngx_http_core_module.html#alias. FastCGI params: nginx.org/en/docs/http/ngx_http_fastcgi_module.html.

TAGGED:configurationNginxphp

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article Comment in a .gitignore file with the # character How to Comment in a .gitignore File
Next Article Convert an image to a base64 data URL in JavaScript How to Convert an Image to a Base64 String in JavaScript
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Run Laravel queue workers with Supervisor
How to Run Laravel Queue Workers in Production with Supervisor
May 23, 2026
Nginx as a reverse proxy for a Node.js app on Ubuntu
How to Set Up Nginx as a Reverse Proxy for Node.js on Ubuntu
May 23, 2026
Install and configure Redis on Ubuntu for Laravel and WordPress
How to Install and Configure Redis on Ubuntu (for Laravel & WordPress)
May 23, 2026
Harden a fresh Ubuntu VPS with UFW, Fail2Ban, and SSH key auth
How to Harden a Fresh Ubuntu VPS: UFW + Fail2Ban + SSH Key Auth
May 23, 2026
Set up Let's Encrypt SSL with Certbot on Ubuntu
How to Set Up Let’s Encrypt SSL with Certbot on Ubuntu (Apache & Nginx)
May 23, 2026

You Might Also Like

Return or throw an error in Laravel (JSON response vs exception)
Web Development

How to Manually Return or Throw an Error Exception in Laravel

6 Min Read
Fix XAMPP MySQL shutdown unexpectedly error
Server Management

How to Fix “Error: MySQL Shutdown Unexpectedly” in XAMPP

5 Min Read
Laravel updateOrCreate method shown in an Eloquent code snippet with insert and update branches
Web Development

Laravel updateOrCreate: Insert or Update Records in Eloquent

8 Min Read
Install Laravel on Ubuntu — terminal with composer create-project command and Laravel red-pillar icon
Web Development

How to Install Laravel on Ubuntu: Step-by-Step Guide

9 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?