Skip to content
RU
← All articles

What Is Apache HTTP Server? How It Works and vs nginx

A web server rack and a laptop showing its configuration in a terminal

Apache, or Apache HTTP Server, is a free, open-source web server that listens for HTTP and HTTPS requests and answers them with web pages, files, or output from PHP and other back-end code. It is maintained by the Apache Software Foundation, runs on Linux, Windows and macOS, and remains one of the most widely deployed web servers.

What is Apache, in plain terms

A browser asks a server for /blog/index.php on example.com. Apache is the program on that server that works out which site the request belongs to, finds the right file on disk, hands PHP scripts to an interpreter if needed, attaches response headers, and sends back a status code — 200, 301, 404 and so on. The binary is called httpd on most systems and apache2 on Debian and Ubuntu, which is why documentation uses both names.

The word "Apache" also names the foundation behind the server. apache.org hosts hundreds of unrelated projects — Kafka, Spark, Airflow, Superset, Tomcat — that share only governance and a license. That license, the Apache License 2.0, is a permissive open-source license used well beyond the foundation; when people search for "Apache 2.0" they usually mean the license rather than a server version. The current server branch is 2.4; the 2.2 branch reached end of life years ago, so a Server: Apache/2.2 header is a signal to schedule an upgrade.

How the Apache web server handles a request

The parent process starts as root so it can bind ports 80 and 443, reads the configuration, then spawns worker processes that run as an unprivileged user (www-data on Debian-family systems, apache on Red Hat-family ones). Each request then goes through roughly these steps:

  1. A worker accepts the connection and parses the request.
  2. Apache picks a virtual host by the Host header, or by SNI for HTTPS.
  3. The URL is mapped to a path under DocumentRoot, and <Directory>, <Location> and .htaccess rules along that path are applied.
  4. Modules do their part: mod_rewrite rewrites the URL, access control modules check permissions, mod_proxy_fcgi passes PHP to PHP-FPM, mod_deflate compresses the output.
  5. The response goes out and the request is written to the access log; problems land in the error log.

Multi-Processing Modules: prefork, worker, event

How Apache spreads connections across processes and threads is decided by exactly one MPM. The choice drives memory use more than almost any other setting.

MPMModelUse it when
preforkOne single-threaded process per connectionYou depend on a non-thread-safe module, typically classic mod_php. Heaviest on RAM
workerSeveral processes, each with a thread poolYou want lower memory use, but a thread stays tied up for the whole keep-alive connection
eventLike worker, plus a listener thread that parks idle keep-alive connectionsDefault choice for modern setups, especially with PHP-FPM

Run apachectl -V | grep -i mpm (or apache2ctl -V on Debian) to see the active one. If PHP already runs through PHP-FPM but the server is still on prefork, switching to event usually frees a lot of memory. The official MPM documentation covers the tuning directives.

Modules

The core is small; features arrive through LoadModule. The ones you meet on almost every server:

  • mod_rewrite for redirects and clean URLs;
  • mod_ssl for TLS;
  • mod_headers to add or strip response headers, including security headers;
  • mod_proxy, mod_proxy_fcgi and mod_proxy_http to forward requests to PHP-FPM or an application server;
  • mod_deflate and mod_expires for compression and caching;
  • mod_remoteip to restore the real client IP behind a proxy.

apachectl -M lists what is loaded. Debian and Ubuntu toggle modules with a2enmod and a2dismod; RHEL, AlmaLinux and Rocky Linux keep the LoadModule lines in /etc/httpd/conf.modules.d/.

.htaccess files

Per-directory .htaccess files are why Apache dominated shared hosting: a site owner without root access can add redirects, block paths, or enable pretty permalinks for WordPress, and the change takes effect on the next request. The cost is that with AllowOverride set to anything but None, Apache looks for .htaccess in every directory along the path on every request. On a server you control, move the rules into the main configuration. The .htaccess guide walks through common rules, and the Apache .htaccess tutorial explains when not to use them.

Apache vs nginx

Both are free, both can serve static files and act as reverse proxies, but their internals differ.

AspectApachenginx
Concurrency modelProcesses and threads, chosen via MPMEvent-driven, a few workers handle many connections
Static contentFine, with more overhead per connectionVery efficient in CPU and memory
PHPIn-process mod_php or external PHP-FPMExternal PHP-FPM over FastCGI only
Per-directory configYes, .htaccessNo, everything lives in central config
ModulesLoaded at runtime with LoadModuleDynamic modules exist; some features need a custom build
Typical roleApplication back end, shared hostingEdge: TLS termination, static files, load balancing

A common hybrid puts nginx on ports 80 and 443 and proxies dynamic requests to Apache on 127.0.0.1:8080. Sites keep working .htaccess rules while nginx absorbs slow clients. The reverse proxy explainer covers the pattern. The trap: Apache now logs every visitor as 127.0.0.1. Fix it with mod_remoteip, trusting only your own proxy:

RemoteIPHeader X-Real-IP
RemoteIPTrustedProxy 127.0.0.1

and have nginx send proxy_set_header X-Real-IP $remote_addr;.

Where Apache keeps its configuration

ItemDebian / UbuntuRHEL / AlmaLinux / Rocky
Main config/etc/apache2/apache2.conf/etc/httpd/conf/httpd.conf
Sitessites-available/, symlinked into sites-enabled/*.conf files in /etc/httpd/conf.d/
Logs/var/log/apache2/access.log, error.log/var/log/httpd/access_log, error_log
Service nameapache2httpd
Run-as userwww-dataapache

The project itself ships source code only. For Windows, httpd.apache.org points to third-party builds such as Apache Lounge, which unpack to C:\Apache24 and install as a service with httpd.exe -k install from an elevated prompt.

A minimal Debian virtual host in /etc/apache2/sites-available/example.com.conf:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public

    <Directory /var/www/example.com/public>
        AllowOverride All
        Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>

Everyday Apache commands

# Debian / Ubuntu
sudo apt install apache2
sudo systemctl enable --now apache2

# RHEL / AlmaLinux / Rocky
sudo dnf install httpd
sudo systemctl enable --now httpd
  • sudo apachectl configtest (same as apachectl -t) — syntax check; expect Syntax OK before every reload.
  • sudo systemctl reload apache2 / httpd — apply config without dropping active connections.
  • sudo apachectl -S — which virtual hosts were parsed and which one is the default per port.
  • sudo a2ensite example.com, sudo a2enmod rewrite headers ssl — enable a site or modules on Debian/Ubuntu.
  • httpd -v or apache2 -v — show the version.

Common Apache errors

  • 403 with AH01630: client denied by server configuration — a Require rule blocks access.
  • 403 with AH00035: ... search permissions are missing on a component of the path — the server user lacks execute permission on a parent directory; namei -l /path/to/file shows which one. More causes in the 403 Forbidden guide.
  • 500 with Invalid command 'RewriteEngine' — .htaccess uses mod_rewrite, but the module is off.
  • 500 with AH00124: Request exceeded the limit of 10 internal redirects — a rewrite loop. See the 500 Internal Server Error guide for the rest.
  • AH00072: make_sock: could not bind to address [::]:80 — something else owns port 80; find it with sudo ss -ltnp | grep ':80 '.
  • AH00558: Could not reliably determine the server's fully qualified domain name — harmless; set a global ServerName.

Hardening basics

Set ServerTokens Prod and ServerSignature Off so the Server header and error pages stop advertising the exact version and OS (ServerTokens reference). Add Options -Indexes, TraceEnable Off, disable unused modules, restrict mod_status with Require ip, send security headers through mod_headers, and keep the package patched. The web server hardening checklist has the full list.

How to check whether a site runs on Apache

Look at the Server response header:

curl -sI https://example.com | grep -i '^server'

On Windows use curl.exe -sI https://example.com, or in PowerShell (Invoke-WebRequest -Uri https://example.com -Method Head).Headers.Server. Server: Apache/2.4.x (Ubuntu) is unambiguous, but with ServerTokens Prod you only see Apache, and behind nginx or a CDN the header names the front server instead. Default error pages signed "Apache Server at … Port 443" are another giveaway.

No terminal? The HTTP header checker shows the Server header, status code and redirect chain; website technology detection identifies the web server alongside CMS, language and CDN; and the security scanner flags version leaks and missing security headers.

FAQ

Is Apache the same as Apache Tomcat?

No. Apache HTTP Server is a general-purpose web server written in C. Tomcat is a separate foundation project that runs Java servlets and JSP; the two are often paired, with httpd proxying to Tomcat.

What does "Apache 2.0" mean?

Usually the Apache License 2.0, a permissive license that allows commercial use and modification as long as notices are kept. The full text is on the foundation's site. The server itself is on the 2.4 branch.

Can Apache and nginx run on the same machine?

Yes, as long as they listen on different ports — typically nginx on 80/443 and Apache on a loopback port — with mod_remoteip configured so logs show real client IPs.

Does WordPress need Apache?

No. It runs on nginx with PHP-FPM too, but it assumes .htaccess out of the box, so Apache needs less manual rewrite configuration.

How do I restart Apache without downtime?

Validate with apachectl configtest, then run systemctl reload apache2 or httpd. A reload re-reads config without dropping connections; a restart drops them.

Check your website right now

Monitor your server →
More articles: Infrastructure
Infrastructure
Load Balancing Algorithms: Round Robin, Least Connections
16.03.2026 · 1 090 views
Infrastructure
Database Connection Pooling: How It Works and Best Practices
16.03.2026 · 701 views
Infrastructure
API Versioning: URL, Header and Query Parameter Approaches
16.03.2026 · 549 views
Infrastructure
Multi-CDN: Failover, Cost Control and Traffic Splitting
16.03.2026 · 426 views