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
VirtualHostand normally controls one hostname and port combination. - Per-directory configuration applies to a filesystem path through a
Directoryblock, or through a.htaccessfile 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
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
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 grantedallows access to all clients subject to other restrictions.Require all deniedblocks access.Require ip 192.0.2.0/24allows matching client addresses.Require valid-userallows 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:
rewritefor redirects and URL rewriting.sslfor TLS and HTTPS.headersfor HTTP response headers.proxyandproxy_httpfor reverse-proxy requests.phpfor the distribution's supported Apache PHP integration when installed.authz_corefor core authorization rules.mimefor 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
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.
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, ormods-available, not generated enabled links. - Use clear filenames and avoid duplicate
VirtualHostdefinitions 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 configtestbefore every reload or restart, then verify the site and logs.
Practical Verification Workflow
- Create or edit a file in an
-availabledirectory. - Enable the site, module, or global snippet with the appropriate
a2en...command. - Run
sudo apache2ctl configtestand stop if it reports an error. - Reload Apache gracefully.
- Test with a browser or
curl, including the correct hostname and HTTPS scheme. - Inspect
apache2ctl -S, the service status, and the relevant access or error log if the result is unexpected. - Revert the focused change if it causes an outage, then investigate in staging.
Key Takeaways
/etc/apache2/apache2.confis 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.
VirtualHostblocks select content and behavior by hostname and port.Directory,Require,Options, andAllowOverridecontrol access and per-directory behavior.a2ensite,a2enmod, anda2enconfmanage Debian and Ubuntu enablement links.- Use
apache2ctl configtest, then a graceful reload, then functional and log-based verification.