Last modified: January 24, 2026
This article is written in: 🇺🇸
Apache HTTP Server (commonly referred to as “Apache”) is one of the most widely used web servers in the world. It is maintained by the Apache Software Foundation and offers robust, flexible, and highly configurable capabilities for serving static and dynamic content. Over the decades, Apache has become a cornerstone of the modern web, powering websites of all sizes, from personal blogs to large enterprise systems. This guide explores Apache’s architecture, configuration files, modules, and common tasks. ASCII diagrams provide insight into request flows and how Apache interacts with operating system resources and other services.
Apache’s architecture revolves around “Multi-Processing Modules” (MPMs) that define how it manages child processes or threads to handle incoming requests. Common MPMs include:
A simplified diagram of how Apache might handle connections using the Worker MPM:
+----------------+ (Incoming Connections)
| Internet | ------------+
| (Clients) | |
+--------+-------+ |
| |
v v
+-----------+ +-----------+ +-----------+
| Apache | | Apache | | Apache |
| Parent |... | Child1 |.. | Child2 |...
| Process | +-----+-----+ +-----+-----+
+-----------+ | |
(Thread 1,2,...n) (Thread 1,2,...n)
In this diagram, the main Apache parent process spawns child processes (in Worker/Event MPM) that each manage a pool of threads. Each thread can handle one client connection at a time.
How you install Apache depends on your OS:
CODE_BLOCK_PLACEHOLDER - CentOS/Red Hat:
CODE_BLOCK_PLACEHOLDER - macOS (Homebrew):
sudo apt-get update
sudo apt-get install apache2
Once installed, Apache typically runs as a service (e.g., apache2.service or httpd.service). You can start, stop, or restart it via your distribution’s service manager (systemctl, service, etc.).
Although file paths vary across distributions, a general layout might look like this:
sudo yum install httpd
This file sets up fundamental directives like ServerRoot, ServerAdmin, ServerName, MPM settings, and includes references to other config files. For example:
brew install httpd
Virtual hosts allow Apache to serve different websites or applications from a single server instance by matching domain names or IP addresses. A common pattern on Debian-based systems is to have site-specific config files in sites-available/, then symlink them into sites-enabled/. A simple mywebsite.conf might look like:
/etc/apache2/ (Debian/Ubuntu) or /etc/httpd/ (Red Hat/CentOS)
├── apache2.conf or httpd.conf (Main config file)
├── mods-available/ or modules.d/
├── mods-enabled/
├── sites-available/
├── sites-enabled/
└── conf.d/ (Additional config fragments)
Then enable it (Debian/Ubuntu style) via:
ServerRoot "/etc/httpd"
ServerAdmin admin@example.com
ServerName www.example.com
Listen 80
LoadModule mpm_event_module modules/mod_mpm_event.so
LoadModule rewrite_module modules/mod_rewrite.so
# ...
Include conf.modules.d/*.conf
Include conf.d/*.conf
On Red Hat-based systems, you manually include it in httpd.conf or place it in conf.d/, ensuring NameVirtualHost *:80 is set if needed (for older versions).
Apache’s functionality can be extended with modules such as mod_rewrite (URL rewriting), mod_ssl (SSL/TLS), mod_proxy (reverse proxy), etc.
On Debian-based systems, commands like a2enmod and a2dismod enable or disable modules. On Red Hat-based systems, you typically edit httpd.conf or a related file to load them (e.g., LoadModule rewrite_module modules/mod_rewrite.so).
Apache can serve static assets like HTML, CSS, images, and more. By default, the DocumentRoot directive designates the root directory for static content. For instance, if DocumentRoot is /var/www/html, then requests to http://server/index.html map to /var/www/html/index.html.
<VirtualHost *:80>
ServerName mywebsite.com
ServerAlias www.mywebsite.com
DocumentRoot /var/www/mywebsite
<Directory /var/www/mywebsite>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog /var/log/apache2/mywebsite_error.log
CustomLog /var/log/apache2/mywebsite_access.log combined
</VirtualHost>
To serve PHP pages, Apache traditionally used mod_php which runs PHP code within the Apache worker processes. However, a more modern approach is using mod_proxy_fcgi with PHP-FPM:
sudo a2ensite mywebsite
sudo systemctl reload apache2
In this case, .php requests are forwarded through a FastCGI socket managed by PHP-FPM. This separation can offer better security and performance than older mod_php approaches.
For Python-based applications (e.g., Django or Flask), mod_wsgi is commonly used:
<VirtualHost *:80>
DocumentRoot /var/www/html
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
When integrating with Tomcat, you might use the AJP connector and mod_jk. The configuration references a workers.properties file specifying the Tomcat backend.
Apache’s mod_proxy can forward requests to another server or service, acting as a reverse proxy. For example:
<VirtualHost *:80>
ServerName phpexample.com
DocumentRoot /var/www/phpapp
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php7.4-fpm.sock|fcgi://localhost/"
</FilesMatch>
</VirtualHost>
Requests to http://proxyexample.com/ are internally proxied to a local service on port 3000. For load balancing multiple backends, use mod_proxy_balancer:
<VirtualHost *:80>
ServerName pythonapp.com
WSGIDaemonProcess myapp python-path=/var/www/myapp
WSGIScriptAlias / /var/www/myapp/myapp/wsgi.py process-group=myapp
<Directory /var/www/myapp/myapp>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
Apache can distribute requests among those two servers using the default (round-robin) or other algorithms.
Enable HTTPS to secure traffic. On many systems, mod_ssl is included but may need enabling (a2enmod ssl on Debian/Ubuntu). Then configure a virtual host on port 443:
<VirtualHost *:80>
ServerName proxyexample.com
ProxyPreserveHost On
ProxyRequests Off
<Location />
ProxyPass http://127.0.0.1:3000/
ProxyPassReverse http://127.0.0.1:3000/
</Location>
</VirtualHost>
You can enforce HTTP to HTTPS redirection:
<Proxy balancer://mycluster>
BalancerMember http://192.168.0.10:3000
BalancerMember http://192.168.0.11:3000
</Proxy>
<VirtualHost *:80>
ProxyPreserveHost On
<Location /api/>
ProxyPass balancer://mycluster/
ProxyPassReverse balancer://mycluster/
</Location>
</VirtualHost>
Apache logs requests and errors in typically two separate files:
/var/log/apache2/access.log or /var/log/httpd/access_log. Captures each request line, status code, bytes sent, user agent, etc. /var/log/apache2/error.log or /var/log/httpd/error_log for errors, warnings, and diagnostic messages.You can customize the log format using the LogFormat directive:
<VirtualHost *:443>
ServerName secure.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.crt
SSLCertificateKeyFile /etc/ssl/private/example.key
DocumentRoot /var/www/secure
<Directory "/var/www/secure">
Require all granted
</Directory>
</VirtualHost>
Monitoring solutions like GoAccess, AWStats, or Elastic Stack can parse and visualize these logs, revealing traffic volumes, response codes, and performance bottlenecks.
For the worker or event MPM, you might configure:
<VirtualHost *:80>
ServerName secure.example.com
Redirect / https://secure.example.com/
</VirtualHost>
The MaxRequestWorkers sets the total threads available. Adjust these for your application’s concurrency needs.
Keep-alive allows multiple requests over a single TCP connection, reducing overhead. You can tweak:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog /var/log/apache2/access.log combined
Use mod_deflate to compress text-based responses:
<IfModule mpm_worker_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
Set caching headers for static content:
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
mod_autoindex if you don’t want directory listings). ServerTokens Prod and ServerSignature Off to not reveal internal version details. SSLCipherSuite and SSLProtocol to avoid outdated cryptography. .htaccess overrides. Use your system’s service manager:
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript
</IfModule>
To apply config changes without dropping active connections abruptly:
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/css "access plus 7 days"
ExpiresByType application/javascript "access plus 7 days"
ExpiresByType image/png "access plus 30 days"
</IfModule>
Apache has a built-in config test:
CODE_BLOCK_PLACEHOLDER or
sudo systemctl start apache2 # Debian/Ubuntu
sudo systemctl enable apache2
sudo systemctl stop httpd # Red Hat/CentOS
It reports syntax errors and other issues before you reload or restart.
sudo systemctl reload apache2 # or httpd
In this diagram, Apache listens on ports 80 or 443. Static files are served directly, while dynamic requests are routed to backend services (PHP-FPM, Tomcat, etc.) or proxied to external APIs.