Fix Nginx 405 Method Not Allowed When POSTing to Static Content

intermediateโšก Nginx2026-06-11| Nginx 1.18+ on Ubuntu 20.04/22.04, Debian, CentOS โ€” any setup serving static files via root/alias/try_files

Error Message

405 Method Not Allowed
#nginx#405#static-files#post-method

The Error

You send a POST request โ€” from a form, fetch(), or curl โ€” and Nginx returns:

405 Method Not Allowed

The response headers include:

Allow: GET, HEAD

Your backend never receives the request. Nginx kills it first.

Root Cause

Nginx's static file module (ngx_http_static_module) only handles GET and HEAD. When a POST request hits a location block that resolves to a file on disk, Nginx rejects it immediately with 405. Your app never sees it. This happens with root, alias, and try_files alike.

Four patterns that trigger this:

  • A form with action="/submit" pointing to a URL matched by a static root block
  • A React or Vue SPA where try_files $uri /index.html catches all routes โ€” including your backend API calls
  • Location block ordering: the static catch-all location / matches before a more specific proxy block
  • An API endpoint like /api/login accidentally served as a static file

Diagnose First

Before changing anything, find which location block is handling your request:

sudo nginx -T | grep -A 10 "location"

Then test with curl and check what comes back:

curl -sv -X POST https://yourdomain.com/api/submit \
  -H "Content-Type: application/json" \
  -d '{"key":"value"}' 2>&1 | grep -E "&1 | grep X-Debug-Upstream
  • Header present with an IP: the 405 is coming from your app server. Fix it in the app, not Nginx.
  • Header absent: Nginx generated the 405 itself. Apply Fix 1 or Fix 2.

Verify the Fix

After editing the config, check syntax and reload:

# Check syntax
sudo nginx -t

# Reload without downtime
sudo nginx -s reload

Retest the failing request:

curl -sv -X POST https://yourdomain.com/api/submit \
  -H "Content-Type: application/json" \
  -d '{"test": true}'

A successful fix gives you a real backend response โ€” 200, 201, or even a validation error from your app. Anything except 405. Still seeing 405? Make sure the config file you edited is actually loaded:

sudo nginx -T | grep "include"

Prevention

  • Always define specific location blocks before generic ones. Put /api/ above / in every server block that mixes static files and a backend proxy.
  • Keep try_files and API proxying in separate blocks. One block for the SPA fallback, a separate one for the proxy โ€” no exceptions.
  • Test all HTTP methods in staging. A one-liner after every deploy catches this immediately: curl -X POST https://staging.example.com/api/health.
  • Tail the error log during development. The 405 shows up in /var/log/nginx/error.log long before you notice it in a browser: tail -f /var/log/nginx/error.log.

Related Error Notes