Apache HTTP Server¶
Apache httpd is the long-standing, modular web server that powers a huge share of the internet. Its big differentiators are a rich module ecosystem and per-directory .htaccess overrides. This page covers installing httpd, its configuration layout, DocumentRoot, a basic <VirtualHost>, enabling modules, and .htaccess.
Tested on
AlmaLinux 9 / RHEL 9 with the httpd package from AppStream. Debian/Ubuntu uses the apache2 package and tooling — notes are inline.
When to choose Apache vs nginx¶
- Choose Apache when you want
.htaccessper-directory config (common in shared hosting and many PHP apps),mod_php, or a specific Apache module. - Choose nginx for high-concurrency static serving and reverse proxying with the lowest memory footprint. See Nginx.
Apache's concurrency behaviour is set by its MPM (Multi-Processing Module):
| MPM | Model | Notes |
|---|---|---|
prefork |
One process per connection, no threads | Required by the non-thread-safe mod_php; heaviest on memory |
worker |
Threads within processes | Lighter than prefork |
event |
Like worker but offloads keep-alive handling | Default on RHEL 9; best for high concurrency |
RHEL 9 ships the event MPM by default. If you need mod_php you must switch to prefork — but the modern recommendation is PHP-FPM instead (see PHP & PHP-FPM), which works with any MPM.
Install Apache httpd¶
Open the firewall¶
sudo firewall-cmd --add-service=http --add-service=https --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-services
Browse to http://<server-ip>/ — you should see the Apache test page. (Debian/Ubuntu with UFW: sudo ufw allow 'Apache Full'.) See Firewalls.
Configuration layout¶
/etc/httpd/
├── conf/
│ └── httpd.conf # main config (global settings, default DocumentRoot)
├── conf.d/ # drop-in *.conf files (vhosts, ssl.conf, etc.)
├── conf.modules.d/ # *.conf files that LoadModule for installed modules
└── /var/www/html/ # default DocumentRoot
httpd.conf ends with IncludeOptional conf.d/*.conf, so any .conf file you drop in conf.d/ is loaded. Modules are loaded by files in conf.modules.d/.
/etc/apache2/
├── apache2.conf # main config
├── ports.conf # Listen directives
├── sites-available/ # vhost files (write here)
├── sites-enabled/ # symlinks created by a2ensite
├── mods-available/ # all available modules
└── mods-enabled/ # symlinks created by a2enmod
└── /var/www/html/ # default DocumentRoot
Debian splits everything into available/enabled pairs managed by helper commands:
DocumentRoot and a basic VirtualHost¶
DocumentRoot is the directory Apache serves files from. The global default is /var/www/html. To host a site under its own root, define a <VirtualHost>.
1. Create the site files¶
sudo mkdir -p /var/www/example.com
echo '<h1>Hello from Apache on AlmaLinux 9</h1>' | sudo tee /var/www/example.com/index.html
2. SELinux: label the custom DocumentRoot (RHEL/AlmaLinux)¶
Apache (like nginx) is confined by SELinux. A DocumentRoot outside /var/www/html must carry the httpd_sys_content_t type or you will get 403 Forbidden:
sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example.com(/.*)?"
sudo restorecon -Rv /var/www/example.com
Outbound connections
If Apache must reach a network service (proxying, remote DB, sending mail from an app), allow it persistently: sudo setsebool -P httpd_can_network_connect 1. See SELinux.
3. Create the vhost file¶
On RHEL/AlmaLinux, create /etc/httpd/conf.d/example.com.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
<Directory /var/www/example.com>
# Allow Apache to serve this directory
Require all granted
# Control whether .htaccess can override settings here (see below)
AllowOverride All
</Directory>
# Per-site logs
ErrorLog /var/log/httpd/example.com-error.log
CustomLog /var/log/httpd/example.com-access.log combined
</VirtualHost>
On Debian, write this to /etc/apache2/sites-available/example.com.conf (logs go to /var/log/apache2/), then run sudo a2ensite example.com.
Enabling modules¶
Apache's functionality comes from modules. On RHEL many are installed and loaded by default; install extra ones with dnf.
.htaccess and AllowOverride¶
.htaccess is a per-directory config file. Apache reads it on every request for that directory tree — handy on shared hosting where you cannot edit the main config, but slower than central config.
.htaccess only takes effect if AllowOverride permits it for that directory:
AllowOverride value |
Effect |
|---|---|
None |
.htaccess is ignored entirely (default on RHEL 9 for /var/www/html) |
All |
All directives allowed in .htaccess |
FileInfo, AuthConfig, etc. |
Allow only specific classes of directive |
Example .htaccess in /var/www/example.com/ that needs mod_rewrite and AllowOverride All:
# /var/www/example.com/.htaccess
RewriteEngine On
# Redirect everything that is not a real file to index.php (common front-controller pattern)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
Performance
On servers you fully control, prefer putting these rules directly in the <Directory> block and leaving AllowOverride None. This avoids Apache walking the directory tree looking for .htaccess files on every request.
Test the config, then reload¶
Never reload blindly — validate first:
Expected:
Then apply with a graceful reload:
On Debian the test command is sudo apache2ctl configtest.
Logs¶
Verify your work¶
# 1. Service enabled and active
systemctl is-enabled httpd && systemctl is-active httpd
# 2. Config syntax is OK
sudo apachectl configtest
# 3. Firewall allows HTTP/HTTPS
sudo firewall-cmd --list-services | grep http
# 4. The vhost responds
curl -H 'Host: example.com' http://localhost/
# -> <h1>Hello from Apache on AlmaLinux 9</h1>
# 5. Custom DocumentRoot has the right SELinux label
ls -Zd /var/www/example.com # -> httpd_sys_content_t
Summary¶
- Install with
dnf install httpd(service: httpd) on RHEL/AlmaLinux orapt install apache2(service: apache2) on Debian. - RHEL config lives in
/etc/httpd/conf/httpd.confplus drop-ins inconf.d/; Debian uses/etc/apache2witha2ensite/a2enmodhelpers. DocumentRootsets the served directory;<VirtualHost>hosts a site under its own root andServerName..htaccessonly works whereAllowOverrideallows it; prefer central config when you control the server.- Custom DocumentRoots on RHEL/AlmaLinux need the
httpd_sys_content_tSELinux label. - Always
apachectl configtestbeforesystemctl reload httpd; logs are in/var/log/httpd/.
Next: add PHP with PHP & PHP-FPM, host multiple sites in Virtual Hosts, or enable HTTPS in HTTPS with Let's Encrypt.