Unit

Apache2 Configuration Files: Structure, Directives, Virtual Hosts, and Safe Changes

Learn the Debian and Ubuntu Apache2 configuration layout, directives, virtual hosts, modules, HTTPS, rewrites, validation, logging, and safe reloads.

Apache HTTP Server is web-server software that receives HTTP or HTTPS requests and returns web content. On Debian and Ubuntu, it is commonly managed as the apache2 service. Its configuration determines which ports Apache listens on, which modules are loaded, which hostnames it serves, how directories are protected, where logs are written, and how requests are handled.

This lesson focuses on the Debian and Ubuntu layout. Other distributions may use paths such as /etc/httpd, httpd.conf, conf.d, or vhosts.d.

How Apache2 Configuration Works

An Apache configuration file contains directives. A directive is an instruction that sets Apache behavior. The usual form is a directive name followed by one or more values.

ServerName web.example.test
DocumentRoot /var/www/example/public
DirectoryIndex index.html index.php

Apache processes a main configuration file and the files it includes. This creates an include tree: one file loads other files, which can load additional snippets. Splitting configuration into focused files makes sites, modules, and global settings easier to manage.

Configuration has different scopes:

  • Server-wide configuration applies to the whole Apache instance, such as global logging, loaded modules, listening ports, and default settings.
  • Per-site configuration belongs to a VirtualHost and normally controls one hostname and port combination.
  • Per-directory configuration applies to a filesystem path through a Directory block, or through a .htaccess file when the server permits it.

A directive is valid only in certain configuration contexts. A context is the location where a directive is allowed and takes effect. A directive that is valid in server configuration may not be valid inside a directory block or a virtual host.

Debian and Ubuntu Configuration Layout

Common Apache2 Configuration Files and Directories

/etc/apache2/apache2.conf — Main configuration entry point and general server settings.

/etc/apache2/ports.conf — Common Listen directives for HTTP and HTTPS ports.

/etc/apache2/sites-available/ — Virtual-host definitions that are available but not necessarily enabled.

/etc/apache2/sites-enabled/ — Enabled virtual-host definitions, usually symbolic links to files in sites-available.

/etc/apache2/conf-available/ — Reusable global configuration snippets.

/etc/apache2/conf-enabled/ — Enabled global snippets, usually symbolic links to conf-available.

/etc/apache2/mods-available/ — Module load files and module-specific configuration.

/etc/apache2/mods-enabled/ — Enabled module files, usually symbolic links to mods-available.

/var/log/apache2/ — Common location for access and error logs.

apache2.conf is the main entry point. The Debian and Ubuntu packaging convention uses helper commands to create and remove symbolic links in the enabled directories. Edit the original file in an -available directory, then enable it. Do not normally edit a generated link in an enabled directory.

ls -l /etc/apache2/sites-enabled/
ls -l /etc/apache2/mods-enabled/

Typical include directives connect these directories to the main configuration:

IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

Include loads additional configuration files and generally expects them to exist. IncludeOptional loads matching files when present and does not fail merely because no file matches. These directives help keep a large configuration manageable.

Apache Configuration Syntax and Contexts

Whitespace separates directive values. Comments begin with # and continue to the end of the line. Quotation marks preserve spaces inside a value when supported. Some directives allow a line continuation mechanism, but consult the directive documentation before splitting a line.

# This is a comment
ServerAdmin "Web Operations <webops@example.test>"
DirectoryIndex index.html index.php

Container directives enclose settings that apply to a selected object or condition:

  • <VirtualHost> selects a site and listening address or port.
  • <Directory> selects a filesystem directory.
  • <DirectoryMatch> selects directories using a regular expression.
  • <Files> and <FilesMatch> select files by name or pattern.
  • <Location> selects a URL path rather than a filesystem path.
  • <IfModule> conditionally processes content when a named module is loaded.

Do not confuse a filesystem path in <Directory> with a URL path in <Location>. Also remember that .htaccess is not automatically active everywhere; its allowed directives are controlled by AllowOverride.

Core Server Settings

Frequently Used Apache Directives

ServerName — Identifies the canonical server or virtual-host name. Common contexts: server and virtual host. Example: ServerName example.test.

DocumentRoot — Sets the filesystem directory from which a site serves content. Typical context: virtual host. Example: DocumentRoot /var/www/example/public.

Directory — Groups rules for a filesystem path. Typical context: server configuration. Example: <Directory /var/www/example/public>.

Require — Controls authorization. Typical contexts: directory and virtual host. Example: Require all granted.

AllowOverride — Controls which settings may be changed by .htaccess. Typical context: directory. Example: AllowOverride None.

Listen — Selects network addresses and ports where Apache accepts connections. Typical context: server configuration. Example: Listen 80.

ErrorLog — Selects an error log. Typical context: server and virtual host. Example: ErrorLog ${APACHE_LOG_DIR}/example-error.log.

CustomLog — Selects request logging and its format. Typical context: server and virtual host. Example: CustomLog ${APACHE_LOG_DIR}/example-access.log combined.

DirectoryIndex — Defines default filenames. Typical context: server, virtual host, and directory. Example: DirectoryIndex index.html index.php.

RewriteRule — Performs redirects or internal URL rewrites when mod_rewrite is loaded. Typical contexts: virtual host and permitted .htaccess.

Identity, content, and logging

ServerName sets the canonical hostname. A global value is also useful when Apache starts without a fully qualified hostname and displays an AH00558 warning. ServerAdmin stores an administrative contact, often used in generated error pages or operational documentation.

DocumentRoot maps a site's normal content root to a filesystem directory. For example, a request for /images/logo.png may map to /var/www/example/public/images/logo.png. DirectoryIndex supplies default files when a URL names a directory.

ServerName server.example.test
ServerAdmin webops@example.test
DocumentRoot /var/www/example/public
DirectoryIndex index.html index.php
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

LogFormat defines a reusable format such as combined. CustomLog records requests using a selected format, while ErrorLog records startup problems, authorization failures, missing files, proxy errors, and other server-side problems.

Runtime and connection settings

PidFile identifies the file containing the main process ID. User and Group describe the account under which worker processes operate after startup, although exact process behavior depends on the installed multi-processing module and distribution defaults.

Timeout limits how long Apache waits for certain operations. KeepAlive allows a client to reuse a connection for multiple requests. Raising timeouts can help slow operations but can consume workers for longer; disabling or shortening keep-alive can increase connection overhead. Change these settings only after measuring the effect.

Directory Access and Permissions

A Directory block applies Apache rules to a filesystem path. A common secure pattern grants access only to the intended public directory:

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

Authorization and filesystem permissions are separate layers. Apache's Require rules decide whether a request is authorized, while Linux ownership and read, write, and execute permissions decide whether the Apache process can traverse directories and read files. Both layers must allow access.

  • Require all granted allows access to all clients subject to other restrictions.
  • Require all denied blocks access.
  • Require ip 192.0.2.0/24 allows matching client addresses.
  • Require valid-user allows users who successfully authenticate through a configured authentication provider.

Important Options values include FollowSymLinks, SymLinksIfOwnerMatch, Indexes, and ExecCGI. Indexes may expose directory listings when no index file exists, so enable it only intentionally. ExecCGI permits CGI execution and should be limited to directories that need it. Prefer SymLinksIfOwnerMatch when its ownership restriction is appropriate.

AllowOverride None prevents .htaccess from changing settings in that directory. More permissive values such as AllowOverride FileInfo permit selected overrides, including many rewrite rules. Disabling unnecessary overrides improves predictability and avoids repeated filesystem checks.

Virtual Hosts

A VirtualHost is a configuration container describing how Apache serves a hostname and port combination. With name-based virtual hosting, Apache first selects a listening address and port, then compares the request's hostname with ServerName and ServerAlias.

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

    <Directory /var/www/example.test/public>
        Require all granted
        AllowOverride None
    </Directory>

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

The DNS records for example.test and www.example.test must point to the Apache server. For local testing, add a temporary entry to the client machine's hosts file or send an explicit host header:

curl -H 'Host: example.test' http://127.0.0.1/

If no hostname matches, Apache uses the first enabled virtual host for the relevant address and port as the default. Inspect the selection order with:

sudo apache2ctl -S

HTTP and HTTPS normally use separate virtual-host definitions. Each HTTPS definition needs its own TLS settings and usually the same site content or an intentional redirect target.

Listening Ports and HTTPS

Listen tells Apache which network address and port should accept connections. Port 80 is the conventional HTTP port and port 443 is the conventional HTTPS port. On Debian and Ubuntu, common port declarations are kept in /etc/apache2/ports.conf.

Listen 80
Listen 443

HTTPS uses TLS to protect the connection. Apache generally needs the SSL module, a certificate, and a private key:

<VirtualHost *:443>
    ServerName example.test
    DocumentRoot /var/www/example.test/public

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.test.pem
    SSLCertificateKeyFile /etc/ssl/private/example.test.key
</VirtualHost>

Private keys must have restrictive filesystem permissions and should not be placed below a publicly served document root. The certificate must cover the requested hostname. After HTTPS works, the HTTP virtual host can issue a permanent redirect:

<VirtualHost *:80>
    ServerName example.test
    Redirect permanent / https://example.test/
</VirtualHost>

Modules and Feature Configuration

Apache features are commonly supplied by modules. On Debian and Ubuntu, a2enmod enables a module and a2dismod disables one. Common modules include:

  • rewrite for redirects and URL rewriting.
  • ssl for TLS and HTTPS.
  • headers for HTTP response headers.
  • proxy and proxy_http for reverse-proxy requests.
  • php for the distribution's supported Apache PHP integration when installed.
  • authz_core for core authorization rules.
  • mime for mapping file extensions to content types.
sudo a2enmod rewrite
sudo a2enmod ssl
sudo systemctl reload apache2

If Apache reports an invalid command, the directive may be misspelled, placed in an invalid context, or supplied by a module that is not loaded. IfModule can conditionally ignore a block when a module is absent, but it should not hide a required dependency or make a production feature silently disappear.

URL Rewriting and Redirects

mod_rewrite can issue a client-visible redirect or perform an internal rewrite. A permanent redirect, commonly status 301, tells the client to request another URL. An internal rewrite changes Apache's handling internally while the browser keeps the original URL.

A front-controller application can route requests that are not real files or directories to index.php:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]

Rules are evaluated in order. Conditions apply to the following rule, and flags such as [L] influence later processing. Test query strings, existing files, directories, loops, and unexpected paths. Rewrite rules may be placed in a virtual host or in .htaccess only when the relevant AllowOverride setting permits them.

Enable, Validate, and Apply Changes

Apache2 Management Commands

a2ensite example.test.conf — Enables a virtual-host file. Use after saving it in sites-available.

a2dissite example.test.conf — Disables a virtual host.

a2enmod rewrite — Enables a module.

a2dismod rewrite — Disables a module.

a2enconf security-snippet — Enables a global configuration snippet.

a2disconf security-snippet — Disables a global snippet.

apache2ctl configtest — Checks configuration syntax before applying changes.

systemctl reload apache2 — Gracefully applies valid configuration changes with minimal interruption.

systemctl restart apache2 — Stops and starts the service; use when a full restart is required.

systemctl status apache2 — Displays service state and recent service messages.

A safe site-enablement sequence is:

sudo cp -a /etc/apache2 /etc/apache2.backup-$(date +%F)
# Edit /etc/apache2/sites-available/example.test.conf
sudo a2ensite example.test.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
curl -H 'Host: example.test' http://127.0.0.1/

A graceful reload applies valid settings while minimizing interruption to active requests. A restart fully stops and starts Apache and may be necessary for some runtime or module changes, but it creates more disruption. Never reload or restart before a successful syntax test.

Logs and Diagnosis

Access logs record requests, response status codes, client information, and timing fields according to the selected log format. Error logs record configuration errors, authorization failures, missing resources, proxy problems, and TLS errors. Common Debian and Ubuntu locations include /var/log/apache2/access.log, /var/log/apache2/error.log, and site-specific files selected by CustomLog and ErrorLog.

sudo systemctl status apache2
sudo journalctl -u apache2 -n 50 --no-pager
sudo tail -n 50 /var/log/apache2/error.log
sudo tail -f /var/log/apache2/example.test-error.log

Temporarily increasing LogLevel can provide more detail during investigation. Use the narrowest useful scope, avoid leaving verbose logging enabled unnecessarily, and return to the normal level after diagnosis.

Common Errors and Likely Causes

Syntax test failure — A syntax error, invalid context, or missing module. Read the reported filename and line, correct it, and run configtest again.

AH00558 ServerName warning — No global ServerName. Add a valid global setting in an enabled configuration snippet, validate, and reload.

403 Forbidden — Authorization rules, filesystem traversal permissions, ownership, or an denying .htaccess rule. Check Require, Linux permissions, and the error log.

404 Not Found — The URL does not map to an existing resource, the DocumentRoot is wrong, or rewriting routes incorrectly. Check the path, virtual host, and rewrite log details.

Wrong virtual host — Hostname mismatch, incorrect DNS, disabled site, or default virtual-host selection. Use apache2ctl -S and test with an explicit Host header.

Connection refused — Apache is stopped, is not listening on the requested port, or a firewall is blocking or rejecting the connection. Check service status, Listen, and network rules.

HTTPS certificate failure — SSL is disabled, paths are wrong, Apache cannot read the key, or the certificate does not match the hostname. Check the SSL module, permissions, and error log.

Rewrite directives invalid or ignoredmod_rewrite is disabled, the context is wrong, or AllowOverride does not permit the directives. Enable the module or move the rules to an allowed context.

Safe Configuration Management

  • Back up a known-working configuration before modifying it.
  • Make one focused change at a time so failures are easy to identify.
  • Edit files in sites-available, conf-available, or mods-available, not generated enabled links.
  • Use clear filenames and avoid duplicate VirtualHost definitions for the same hostname and port.
  • Protect private keys, credentials, and included secret files from public access.
  • Use version control or a documented change record for managed systems.
  • Test production changes in staging when possible.
  • Run apache2ctl configtest before every reload or restart, then verify the site and logs.

Practical Verification Workflow

  1. Create or edit a file in an -available directory.
  2. Enable the site, module, or global snippet with the appropriate a2en... command.
  3. Run sudo apache2ctl configtest and stop if it reports an error.
  4. Reload Apache gracefully.
  5. Test with a browser or curl, including the correct hostname and HTTPS scheme.
  6. Inspect apache2ctl -S, the service status, and the relevant access or error log if the result is unexpected.
  7. Revert the focused change if it causes an outage, then investigate in staging.

Key Takeaways

  • /etc/apache2/apache2.conf is the main entry point, while ports, modules, snippets, and sites are organized in dedicated files and directories.
  • Enabled directories commonly contain symbolic links to files in corresponding available directories.
  • VirtualHost blocks select content and behavior by hostname and port.
  • Directory, Require, Options, and AllowOverride control access and per-directory behavior.
  • a2ensite, a2enmod, and a2enconf manage Debian and Ubuntu enablement links.
  • Use apache2ctl configtest, then a graceful reload, then functional and log-based verification.