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
Laravel Eloquent ORM — a model class mapping to a database table with query methods
Laravel Eloquent ORM: The Complete Guide to Querying Your Database
June 16, 2026
Set vi as the default editor in Ubuntu — a terminal opening the vim editor
How to Set vi (Vim) as the Default Editor in Ubuntu
June 8, 2026
rsync says ALL DONE but files are missing — a terminal showing ALL DONE next to an empty folder
rsync Says “ALL DONE” but Files Are Missing: How to Verify
June 8, 2026
Migrate a website to a new server with rsync — files copying from an old server to a new one over SSH
How to Migrate a Website to a New Server With rsync
June 8, 2026
Bun runtime — faster JS toolkit replacing npm in Laravel projects
How to Install Bun Runtime on Ubuntu (And Use It in a Laravel Project)
May 24, 2026

You Might Also Like

MariaDB restart on Linux — systemctl restart mariadb
Server Management

How to Restart the MariaDB Server on Linux

6 Min Read
WordPress logged-in menu swap — register_nav_menus + wp_nav_menu with is_user_logged_in ternary
Web Development

How to Display Different Menus to Logged-In Users in WordPress

7 Min Read
WordPress system cron — DISABLE_WP_CRON + system crontab hitting wp-cron.php
Web Development

How to Set Up a System-Based Cron Job in WordPress

7 Min Read
Fix DKIM not signing emails in aaPanel
Server Management

How to Fix DKIM Not Signing Emails in aaPanel

5 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?