Restricting unused HTTP methods in Apache reduces the attack surface and removes unexpected request paths that scanners and opportunistic clients probe. A tight method allowlist also helps keep application behavior predictable by limiting requests to the verbs the service actually supports.
In Apache, method-based control is implemented by scoping authorization rules to request verbs using containers such as <Limit> and <LimitExcept> within a relevant configuration context like <VirtualHost> or <Location>. An allowlist built with <LimitExcept> is the safer pattern because the enclosed access rules apply to every method not explicitly named, including nonstandard methods.
Method filtering is workload-specific: disabling OPTIONS can break browser CORS preflight, and APIs may legitimately use PUT, PATCH, or DELETE. The TRACE method is controlled separately using TraceEnable, so set it explicitly alongside the allowlist and validate syntax before reloading the service.
Steps to disable HTTP methods in Apache:
- Open the site Apache virtual host configuration for editing.
$ sudo vi /etc/apache2/sites-available/000-default.conf
On Ubuntu or Debian, enabled site configs are typically linked from /etc/apache2/sites-enabled and often include a separate HTTPS vhost in /etc/apache2/sites-available/default-ssl.conf.
- Locate the <VirtualHost> block that serves the site.
<VirtualHost *:80> ServerName host.example.net DocumentRoot /var/www/html </VirtualHost>
- Set TraceEnable to off inside the same <VirtualHost>.
<VirtualHost *:80> ServerName host.example.net DocumentRoot /var/www/html TraceEnable off </VirtualHost>
TraceEnable extended reflects request bodies for diagnostics and is not appropriate for production hardening.
- Add a <Location> method allowlist using <LimitExcept>.
<VirtualHost *:80> ServerName host.example.net DocumentRoot /var/www/html TraceEnable off <Location /> <LimitExcept GET POST> Require all denied </LimitExcept> </Location> </VirtualHost>
Methods not listed in <LimitExcept> are denied for this vhost, including common API verbs like PUT and DELETE.
GET also permits HEAD under <LimitExcept> rules, and method names are case-sensitive.
- Write the updated configuration file to disk.
- Validate the Apache configuration syntax.
$ sudo apache2ctl configtest Syntax OK
- Reload Apache to apply the changes.
$ sudo systemctl reload apache2
- Confirm the Apache service is active.
$ sudo systemctl status apache2 --no-pager -l ● apache2.service - The Apache HTTP Server Loaded: loaded (/usr/lib/systemd/system/apache2.service; enabled; preset: enabled) Active: active (running) since Sat 2026-01-10 13:43:16 +08; 25s ago Docs: https://httpd.apache.org/docs/2.4/ Process: 7605 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS) Process: 8248 ExecReload=/usr/sbin/apachectl graceful (code=exited, status=0/SUCCESS) Main PID: 7608 (apache2) Tasks: 29 (limit: 4546) Memory: 3.4M (peak: 6.9M) ##### snipped ##### - Verify that TRACE requests return 405.
$ curl -i -X TRACE -H 'Host: host.example.net' http://127.0.0.1/ HTTP/1.1 405 Method Not Allowed Date: Sat, 10 Jan 2026 05:43:41 GMT Server: Apache/2.4.58 (Ubuntu) Allow: Content-Length: 304 Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>405 Method Not Allowed</title> </head><body> <h1>Method Not Allowed</h1> <p>The requested method TRACE is not allowed for this URL.</p> <hr> <address>Apache/2.4.58 (Ubuntu) Server at host.example.net Port 80</address> </body></html>
- Verify that a non-allowlisted method is denied.
$ curl -i -X PUT -H 'Host: host.example.net' http://127.0.0.1/ HTTP/1.1 403 Forbidden Date: Sat, 10 Jan 2026 05:43:41 GMT Server: Apache/2.4.58 (Ubuntu) Content-Length: 281 Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>403 Forbidden</title> </head><body> <h1>Forbidden</h1> <p>You don't have permission to access this resource.</p> <hr> <address>Apache/2.4.58 (Ubuntu) Server at host.example.net Port 80</address> </body></html>
Blocking OPTIONS can break CORS preflight, so include OPTIONS in the allowlist when browser clients require it.
- Verify that an allowlisted method still succeeds.
$ curl -I -H 'Host: host.example.net' http://127.0.0.1/ HTTP/1.1 200 OK Date: Sat, 10 Jan 2026 05:43:41 GMT Server: Apache/2.4.58 (Ubuntu) Last-Modified: Sat, 10 Jan 2026 05:32:07 GMT ETag: "29af-64801f6762249" Accept-Ranges: bytes Content-Length: 10671 Vary: Accept-Encoding Content-Type: text/html
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
