Restricting HTTP methods at the Nginx edge prevents unexpected verbs from reaching an application, shrinking the exposed surface area and cutting down noisy scanner traffic. A tight method allow-list also makes behavior predictable for static sites, reverse proxies, and APIs that only support a small set of verbs.

Nginx selects a server block for a request, then routes the URI into the best matching location block. The limit_except directive applies an allow-list of methods in a location, and its nested access rules run only when the request method is not in that allow-list.

Method filtering belongs as close as possible to the endpoint that needs it, since broad blocks can break APIs, WebDAV-style clients (PROPFIND), and browser CORS preflight requests (OPTIONS). Always run nginx -t before reloading the service to avoid taking the site offline due to a syntax error.

Steps to restrict HTTP methods in Nginx:

  1. Choose an allow-list of methods that matches the endpoint behavior.

    Common allow-lists: GET + HEAD for static content, GET + HEAD + POST for form handlers, GET + HEAD + POST + PUT + PATCH + DELETE for APIs. Add OPTIONS on endpoints that must pass browser preflight checks.

  2. Open the site’s server block configuration file in /etc/nginx/sites-available.
    $ sudoedit /etc/nginx/sites-available/example.conf

    Layouts without /etc/nginx/sites-available commonly use /etc/nginx/conf.d or edit /etc/nginx/nginx.conf directly.

  3. Add a limit_except block inside the target location to deny every method not on the allow-list.
    location / {
        limit_except GET HEAD {
            deny all;
        }
    }

    Blocking POST breaks logins, forms, and many APIs. Blocking OPTIONS breaks browser CORS preflight.

  4. Save the configuration file.
  5. Test the updated Nginx configuration for syntax errors.
    $ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  6. Reload Nginx to apply the change without dropping active connections.
    $ sudo systemctl reload nginx

    Use

    sudo systemctl restart nginx

    when reload fails due to a module or binary change.

  7. Send a HEAD request to confirm allowed methods succeed.
    $ curl -I https://example.com/
    HTTP/1.1 200 OK
    Server: nginx
    ##### snipped #####
  8. Send a blocked method request to confirm the restriction triggers.
    $ curl -i -X PUT https://example.com/
    HTTP/1.1 403 Forbidden
    Server: nginx
    ##### snipped #####
Discuss the article:

Comment anonymously. Login not required.