| |

LFCE 51 ๐Ÿง Apache โ€” Basic Configuration

โฑ๏ธ Estimated read: 12 min | |

Apache HTTP Server, commonly called httpd, is the other major web server in the Linux ecosystem. The previous chapter covered installation and the default “It works!” page. This chapter covers the configuration that replaces the default with a working site: the ServerName and DocumentRoot directives, the <Directory> block that controls access to the filesystem, the DirectoryIndex that determines which file is served for a directory request, and the validation command that prevents a syntax error from becoming an outage. Apache’s configuration is directive-based, and the directives live inside containers like <Directory> and <VirtualHost>. The main configuration file differs by distribution: /etc/apache2/apache2.conf on Debian and Ubuntu, and /etc/httpd/conf/httpd.conf on RHEL and its derivatives .

Key point: The DocumentRoot directive tells Apache where the site’s files live. The <Directory> block for that path controls which features are allowed and who can access the files. The ServerName directive identifies the hostname the server uses for self-referential URLs. Always run apache2ctl configtest (Debian) or httpd -t (RHEL) before reloading; a configuration error prevents the new configuration from being applied.


Why basic configuration requires understanding the container model

The directory-permission problem.

Apache serves files from the filesystem, and the <Directory> block is the mechanism that grants or denies access to a specific path. The default configuration on many distributions includes a <Directory /var/www/> block with Require all granted, which allows access to the web root. If the DocumentRoot is changed to a path that is not covered by a permissive <Directory> block, the server returns a 403 Forbidden response even though the files exist and the path is correct . The <Directory> block is not optional decoration; it is the access control layer that sits between the filesystem and the HTTP response.

The ServerName problem.

Apache uses the ServerName directive to construct self-referential URLs, such as redirects when a client requests a directory without a trailing slash. If ServerName is not set, Apache attempts to determine the hostname from the system’s DNS configuration, which may be slow or incorrect. A warning during startup indicates that ServerName is not configured . The directive should be set explicitly to the hostname that clients use to reach the server.

The DirectoryIndex problem.

A request for a directory, such as http://example.com/, does not specify a file. The DirectoryIndex directive tells Apache which file to serve when the request resolves to a directory. The default is index.html, but applications often need index.php or a list of candidates. If the DirectoryIndex does not include the file that exists in the directory, Apache returns a 403 or a directory listing, depending on the Options setting .


a. The ServerName and DocumentRoot directives

The ServerName directive identifies the hostname, and the DocumentRoot directive sets the filesystem path for the site. Both belong in the main server configuration or in a virtual host block.

# /etc/apache2/apache2.conf (Debian) or /etc/httpd/conf/httpd.conf (RHEL)
ServerName example.com

DocumentRoot /var/www/example

<Directory /var/www/example>
    Options FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

The ServerName is the hostname that Apache uses when it needs to construct a URL that refers to itself. The DocumentRoot is the base path for all requests. The <Directory> block grants access to that path and sets the options for the directory .

The Options directive controls which features are enabled in the directory. FollowSymLinks allows symbolic links to be followed. Indexes allows directory listings when no index file exists; it should be removed or negated (-Indexes) to prevent listing the contents of directories that lack an index file . The AllowOverride directive controls whether .htaccess files can override the configuration; None disables them, which is the recommended setting when the application does not require them.


b. The DirectoryIndex and access control

The DirectoryIndex directive specifies the files that Apache tries when a request resolves to a directory. The first file that exists is served.

# Serve index.html or index.php for directory requests
DirectoryIndex index.html index.php

The order matters. Apache tries each file in the order listed and serves the first one that exists. If the application uses PHP, index.php should be in the list. If the site is static, index.html is sufficient .

The access control is provided by the Require directive inside the <Directory> block. The Require all granted directive allows access from all clients. The Require all denied directive denies access from all clients. A more restrictive configuration can require authentication or restrict access to specific IP addresses.

<Directory /var/www/example>
    Options -Indexes +FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

# Deny access to sensitive files
<Files ".env">
    Require all denied
</Files>

The <Files> block applies the access control to a specific filename pattern, regardless of which directory it is in. The Require all denied directive for .env prevents the file from being served, even if it is inside the DocumentRoot .


c. Validating and reloading the configuration

The validation command parses the configuration and reports syntax errors before the reload. On Debian and Ubuntu, the command is apache2ctl configtest. On RHEL and its derivatives, the command is httpd -t .

# Debian / Ubuntu
sudo apache2ctl configtest
# Output: Syntax OK

# RHEL / Rocky
sudo httpd -t
# Output: Syntax OK

If the validation succeeds, the configuration can be reloaded without dropping active connections. The reload command differs by distribution: systemctl reload apache2 on Debian, systemctl reload httpd on RHEL .

# Debian
sudo systemctl reload apache2

# RHEL
sudo systemctl reload httpd

After the reload, the site can be tested with curl from the local host or from a remote client. The curl -I http://localhost command retrieves the HTTP headers and confirms that the server returns a response. A browser request to the server’s IP address or hostname returns the content from the DocumentRoot.


Complete Example Session

# ============================================
# PART 1: CREATE THE SITE DIRECTORY
# ============================================
sudo mkdir -p /var/www/example
echo "<h1>Example Site</h1>" | sudo tee /var/www/example/index.html

# ============================================
# PART 2: SET OWNERSHIP AND PERMISSIONS
# ============================================
# Debian: www-data; RHEL: apache
sudo chown -R www-data:www-data /var/www/example
sudo chmod -R 755 /var/www/example

# ============================================
# PART 3: EDIT THE MAIN CONFIGURATION
# ============================================
# Debian: /etc/apache2/apache2.conf
# RHEL: /etc/httpd/conf/httpd.conf
# Add or modify:
# ServerName example.com
# DocumentRoot /var/www/example
# <Directory /var/www/example>
#     Options -Indexes +FollowSymLinks
#     AllowOverride None
#     Require all granted
# </Directory>
# DirectoryIndex index.html index.php

# ============================================
# PART 4: VALIDATE THE CONFIGURATION
# ============================================
sudo apache2ctl configtest    # Debian
# or
sudo httpd -t                 # RHEL
# Output: Syntax OK

# ============================================
# PART 5: RELOAD APACHE
# ============================================
sudo systemctl reload apache2    # Debian
# or
sudo systemctl reload httpd      # RHEL

# ============================================
# PART 6: TEST LOCALLY
# ============================================
curl -I http://localhost
# Output: HTTP/1.1 200 OK

# ============================================
# PART 7: TEST FROM A REMOTE CLIENT
# ============================================
# From another machine:
# curl http://<server-ip>
# Output: <h1>Example Site</h1>

# ============================================
# PART 8: VERIFY DIRECTORY LISTING IS DISABLED
# ============================================
curl -I http://localhost/nonexistent/
# Output: HTTP/1.1 403 Forbidden (or 404)
# The -Indexes option prevents the listing

# ============================================
# PART 9: CHECK THE ERROR LOG
# ============================================
sudo tail -5 /var/log/apache2/error.log    # Debian
# or
sudo tail -5 /var/log/httpd/error_log      # RHEL
# Output shows any warnings or errors from the reload

# ============================================
# PART 10: VERIFY THE SERVER NAME
# ============================================
sudo apache2ctl -S    # Debian
# or
sudo httpd -S         # RHEL
# Output shows the server name and the virtual host configuration

The ten parts demonstrate the complete basic configuration workflow: create content, set permissions, edit the configuration, validate, reload, test locally, test remotely, verify directory listing is disabled, check the error log, and verify the server name. The critical steps are Part 4 (validation before reload) and Part 10 (confirming that ServerName is recognized).


Quick Reference

Basic Configuration Directives

DirectivePurposeExample
ServerNameHostname for self-referential URLsServerName example.com
DocumentRootFilesystem path for the siteDocumentRoot /var/www/example
<Directory>Access control for a path<Directory /var/www/example>
OptionsFeatures enabled in the directoryOptions -Indexes +FollowSymLinks
AllowOverrideWhether .htaccess can overrideAllowOverride None
RequireAccess controlRequire all granted
DirectoryIndexDefault file for directory requestsDirectoryIndex index.html
<Files>Access control for a filename pattern<Files ".env">

Validation and Control Commands

CommandDistributionPurpose
apache2ctl configtestDebianValidate configuration syntax
httpd -tRHELValidate configuration syntax
systemctl reload apache2DebianReload without dropping connections
systemctl reload httpdRHELReload without dropping connections
apache2ctl -S / httpd -SBothShow server name and virtual hosts

Common Options

OptionMeaning
IndexesAllow directory listings
-IndexesDisable directory listings
FollowSymLinksAllow symbolic links
+FollowSymLinksEnable symbolic links (additive)
NoneDisable all options

Best Practices

โœ… Do This:

# Set ServerName explicitly
ServerName example.com                                        # โœ…

# Use -Indexes to prevent directory listings
Options -Indexes +FollowSymLinks                              # โœ…

# Grant access explicitly to the DocumentRoot
<Directory /var/www/example>
    Require all granted
</Directory>                                                  # โœ…

# Deny access to sensitive files
<Files ".env">
    Require all denied
</Files>                                                      # โœ…

# Set DirectoryIndex to include the application's entry file
DirectoryIndex index.html index.php                           # โœ…

# Validate before reloading
apache2ctl configtest    # or httpd -t                        # โœ…

โŒ Don’t Do This:

# Forget the <Directory> block for the DocumentRoot
DocumentRoot /var/www/example    # 403 without the block       # โŒ

# Leave Indexes enabled on a directory with no index file
Options Indexes    # Lists the directory contents             # โŒ

# Use a permissive <Directory> for the entire filesystem
<Directory />
    Require all granted
</Directory>    # Grants access to /etc, /root, etc.          # โŒ

# Omit DirectoryIndex for PHP applications
DirectoryIndex index.html    # index.php is not served        # โŒ

# Reload without validation
systemctl reload apache2    # A syntax error is rejected      # โŒ

Common Pitfalls

PitfallWhy It HappensFix
403 Forbidden on the siteNo <Directory> block or wrong permissionsAdd the block; chown to the web user
404 but the file existsDocumentRoot path is wrongVerify the path and the file location
Directory listing appearsOptions Indexes is enabledUse Options -Indexes
ServerName warning at startupServerName not setAdd ServerName example.com
PHP file is not servedDirectoryIndex does not include index.phpAdd it to the list
Configuration error after editMissing directive or typoapache2ctl configtest reports the line

Real-World Examples

1. Set ServerName

ServerName example.com

2. Set DocumentRoot

DocumentRoot /var/www/example

3. Grant access to the DocumentRoot

<Directory /var/www/example>
    Require all granted
</Directory>

4. Disable directory listing

Options -Indexes +FollowSymLinks

5. Disable .htaccess overrides

AllowOverride None

6. Set DirectoryIndex

DirectoryIndex index.html index.php

7. Deny access to sensitive files

<Files ".env">
    Require all denied
</Files>

8. Validate configuration

apache2ctl configtest    # Debian
httpd -t                 # RHEL

9. Reload Apache

systemctl reload apache2    # Debian
systemctl reload httpd      # RHEL

10. Show server configuration

apache2ctl -S    # Debian
httpd -S         # RHEL

Visual

The Configuration Container Model

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  APACHE CONFIGURATION IS DIRECTIVES INSIDE CONTAINERS        โ”‚
โ”‚                                                              โ”‚
โ”‚  ServerName example.com        โ† Global directive            โ”‚
โ”‚  DocumentRoot /var/www/example โ† Global directive            โ”‚
โ”‚                                                              โ”‚
โ”‚  <Directory /var/www/example>  โ† Container                   โ”‚
โ”‚      Options -Indexes                                        โ”‚
โ”‚      Require all granted       โ† Directive inside container  โ”‚
โ”‚  </Directory>                                                โ”‚
โ”‚                                                              โ”‚
โ”‚  <Files ".env">                โ† Container                   โ”‚
โ”‚      Require all denied                                      โ”‚
โ”‚  </Files>                                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  The container determines where the directives apply.        โ”‚
โ”‚  <Directory> applies to a filesystem path.                   โ”‚
โ”‚  <Files> applies to a filename pattern.                      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Access Control Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE <Directory> BLOCK GRANTS OR DENIES ACCESS               โ”‚
โ”‚                                                              โ”‚
โ”‚  Request: GET /index.html                                    โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  DocumentRoot = /var/www/example                             โ”‚
โ”‚  Filesystem path = /var/www/example/index.html               โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  Is there a <Directory> block for /var/www/example?          โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ No โ†’ 403 Forbidden                                 โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ””โ”€โ”€ Yes โ†’ Check Require directive                      โ”‚
โ”‚             โ”‚                                                โ”‚
โ”‚             โ”œโ”€โ”€ Require all denied โ†’ 403 Forbidden           โ”‚
โ”‚             โ”‚                                                โ”‚
โ”‚             โ””โ”€โ”€ Require all granted โ†’ Serve the file         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Validation and Reload Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  VALIDATE BEFORE RELOADING                                   โ”‚
โ”‚                                                              โ”‚
โ”‚  Edit configuration                                          โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ–ผ                                                      โ”‚
โ”‚  apache2ctl configtest (Debian) / httpd -t (RHEL)            โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ Error โ†’ Fix file, repeat                           โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ””โ”€โ”€ Syntax OK โ†’ systemctl reload apache2 / httpd       โ”‚
โ”‚                           โ”‚                                  โ”‚
โ”‚                           โ–ผ                                  โ”‚
โ”‚                     New configuration active                 โ”‚
โ”‚                     Active connections preserved             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Debian main config/etc/apache2/apache2.conf
RHEL main config/etc/httpd/conf/httpd.conf
Server hostnameServerName directive
Document rootDocumentRoot directive
Access control<Directory> + Require
Directory listingOptions Indexes / -Indexes
Default index fileDirectoryIndex directive
Sensitive file denial<Files> + Require all denied
Validation (Debian)apache2ctl configtest
Validation (RHEL)httpd -t
Reload (Debian)systemctl reload apache2
Reload (RHEL)systemctl reload httpd

Key takeaways:

  • The <Directory> block is the access control layer. Without it, Apache returns 403 Forbidden even when the files exist and the path is correct. The block grants access with Require all granted and sets the options for the directory .
  • ServerName should be set explicitly. Apache uses it to construct self-referential URLs. Without it, the server may produce incorrect redirects or a warning at startup .
  • DirectoryIndex determines the default file. A request for a directory serves the first file in the list that exists. For PHP applications, index.php must be in the list .
  • Options -Indexes prevents directory listings. Without it, a request for a directory with no index file produces a listing of its contents, which can expose files that should not be visible .
  • The <Files> block denies access to specific filenames. A <Files ".env"> block with Require all denied prevents the file from being served even if it is inside the DocumentRoot .
  • Validate before reloading. apache2ctl configtest on Debian and httpd -t on RHEL catch syntax errors before the configuration is applied. A configuration error prevents the reload, and the running configuration remains in effect .

Remember: Apache configuration is built from directives inside containers. The ServerName and DocumentRoot directives set the identity and the filesystem path. The <Directory> block grants access and controls the features for that path. The DirectoryIndex determines which file is served for a directory request. The <Files> block denies access to sensitive filenames. Validate with configtest or -t, reload with systemctl reload, and test with curl. A configuration that parses is not necessarily a configuration that serves the right site; the test confirms both.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!