8.1 Apache Web Server
Key Takeaways
- Apache is installed from the apache2 package, but like all network services on Kali it is disabled by default until you run systemctl start apache2.
- The /etc/apache2 configuration uses an available/enabled split: files live in sites-available and are activated as symlinks in sites-enabled with a2ensite/a2dissite.
- a2enmod and a2dismod manage module symlinks between mods-available and mods-enabled the same way a2ensite manages sites.
- The default DocumentRoot is /var/www/html, served by the 000-default site listening on port 80 from ports.conf.
- Always run apachectl configtest before applying changes, and prefer systemctl reload apache2 (graceful) over restart to avoid dropping active connections.
8.1 Apache Web Server
The Apache HTTP Server is the most widely deployed web server on the internet, and Kali packages it as apache2. You will often need a local web server during an engagement — to host payloads, serve files to a target, or stage a phishing page — so the KLCP exam expects you to install, configure, and control it fluently. One critical Kali-specific fact frames everything in this section: network services are disabled by default on Kali. Installing apache2 does not start it and does not make it start at boot; you must explicitly run systemctl start apache2 (and systemctl enable apache2 if you want it persistent). This is a deliberate security posture, because an exposed service on a penetration testing machine is an attack surface.
Before the service-by-service detail, learn the generic method for configuring an unfamiliar daemon, because the exam asks it in the abstract. Start with what the package maintainer wrote: /usr/share/doc/<package>/README.Debian. Then list what the package actually installed with dpkg -L <package> — its configuration files are the ones under /etc/ — and read dpkg -s <package> for metadata plus recommended or suggested helper packages. Sample configurations often sit in /usr/share/doc/<package>/examples/, the shipped config files are usually self-documenting through their comments, and dpkg-reconfigure <package> re-runs the package's own configuration dialogue.
Installing and Controlling Apache
A standard Kali install already ships Apache — the kali-linux-headless metapackage pulls in apache2 — so it is simply stopped and not enabled. On a minimal image, install it with the standard APT workflow:
- sudo apt update && sudo apt install apache2 — pulls in apache2, apache2-bin, apache2-data, and apache2-utils.
- sudo systemctl start apache2 — starts the service for the current session.
- sudo systemctl enable apache2 — makes it start at boot (not the Kali default).
- systemctl status apache2 — shows whether it is active and the most recent log lines.
Once running, browsing to http://localhost displays the default Apache2 Debian Default Page, which is served from /var/www/html/index.html. That page itself is a useful map: it documents the configuration layout described below.
The /etc/apache2 Configuration Layout
Debian (and therefore Kali) splits Apache configuration into a structured directory tree under /etc/apache2 rather than a single monolithic file. The exam tests this layout directly, so memorize it:
| Path | Purpose |
|---|---|
| apache2.conf | The main configuration file; includes everything else |
| ports.conf | Defines the ports Apache listens on (Listen 80 by default) |
| envvars | Environment variables, including the runtime user www-data |
| sites-available/ | Virtual host definition files stored here |
| sites-enabled/ | Symlinks to the virtual hosts currently active |
| mods-available/ | Load configuration for every installed module |
| mods-enabled/ | Symlinks to the modules currently loaded |
| conf-available/ and conf-enabled/ | Snippets of global configuration, same pattern |
The available/enabled pattern is the heart of the Debian approach. You never edit or delete a site to turn it off; you create or remove a symlink in the *-enabled directory. apache2.conf only loads files through the *-enabled directories, so anything not symlinked there is ignored even though it still exists on disk.
Three helper commands manage these symlinks, and the exam loves to test which one does what:
- a2ensite / a2dissite — enable or disable a virtual host (creates/removes the symlink in sites-enabled). Example: sudo a2ensite 000-default.
- a2enmod / a2dismod — enable or disable a module. Example: sudo a2enmod rewrite activates URL rewriting for .htaccess-style rules.
- a2enconf / a2disconf — enable or disable global configuration snippets.
A classic trap: a2ensite only creates the symlink — it does not reload Apache. The change takes effect only after you reload or restart the service. Another trap: a2enmod manages modules, not sites; answering with a2enmod when the question asks about enabling a virtual host is wrong.
DocumentRoot and Virtual Hosts
The default virtual host, 000-default.conf, sets DocumentRoot /var/www/html, so any file you place there is immediately served. A virtual host lets one Apache instance serve multiple sites, distinguished by hostname or port. To add one, create a new file such as /etc/apache2/sites-available/example.conf:
<VirtualHost *:80>
ServerName example.local
DocumentRoot /var/www/example
ErrorLog ${APACHE_LOG_DIR}/example-error.log
CustomLog ${APACHE_LOG_DIR}/example-access.log combined
</VirtualHost>
Then create the document root, enable the site, validate, and reload:
- sudo mkdir -p /var/www/example
- sudo a2ensite example
- sudo apachectl configtest
- sudo systemctl reload apache2
Runtime Identity, Logs, and Ports
Three operational details round out the exam picture. First, Apache starts as root only long enough to bind privileged ports, then drops privileges and serves requests as the unprivileged www-data user and group, defined in envvars. Files under /var/www/html must be readable by www-data or Apache answers with 403 Forbidden. Second, logs land in /var/log/apache2/ — access.log and error.log by default, plus any per-vhost logs you define. When a site misbehaves, error.log is the first place to look. Third, the listening port is not set in the virtual host file alone; ports.conf carries the Listen 80 directive, and adding a port requires both a Listen line there and a matching <VirtualHost *:port> block. Verify what is actually bound with ss -tlnp | grep apache2.
You should also know about .htaccess files: per-directory configuration files Apache reads only when the site's AllowOverride directive permits it (the Debian default sets AllowOverride None for the web root, which ignores them). Enabling them requires editing the site's config to AllowOverride All and enabling the rewrite module with a2enmod rewrite if pretty URLs are needed — then reloading, as always.
Directory Blocks, Options, and the Require Model
Most per-location behaviour is set in <Directory> blocks. Debian's stock apache2.conf ships this one:
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Options selects per-directory features — Indexes (auto-generate a listing when no DirectoryIndex file exists), FollowSymLinks, SymLinksIfOwnerMatch, ExecCGI, Includes (server-side includes), MultiViews (content negotiation); None disables all of them and All enables everything except MultiViews. DirectoryIndex index.html index.php lists the files tried when a request names a directory.
Access control is where Apache 2.2 and 2.4 diverge, and the exam tests it. Apache 2.2 used Order allow,deny with Allow from / Deny from; Apache 2.4 replaced all of that with Require:
Require all granted— allow everyone (the Debian default for the web root)Require all denied— deny everyoneRequire ip 192.168.0.0/16— restrict to a networkRequire valid-user— require a successful login
Password protection combines Require valid-user with a Basic-auth stanza, usually in a .htaccess file (which only works where AllowOverride permits it):
Require valid-user
AuthName "Private directory"
AuthType Basic
AuthUserFile /etc/apache2/authfiles/htpasswd-private
Create the password file with htpasswd /etc/apache2/authfiles/htpasswd-private user. Remember that Basic authentication only base64-encodes credentials, so it offers no confidentiality without TLS — enable HTTPS with a2enmod ssl and start from the shipped example at /etc/apache2/sites-available/default-ssl.conf. PHP applications need libapache2-mod-php, which enables its module automatically on install.
Validating and Applying Changes
apachectl configtest (equivalently apache2ctl configtest) parses the entire configuration without starting or touching the running server and prints Syntax OK when everything is valid. Run it after every edit — a syntax error introduced into a config file will prevent Apache from restarting at all, which on a production box means downtime and on the exam means a wrong answer if you skipped validation.
Finally, know the difference between reload and restart. systemctl reload apache2 performs a graceful reload: Apache re-reads its configuration without killing existing worker processes or dropping in-flight connections. systemctl restart apache2 fully stops and starts the daemon, severing active connections. The correct operational habit — and the expected exam answer — is to edit the config, run configtest, then reload. Reserve restart for cases where a reload cannot apply the change, such as certain module loads, or when the service is genuinely hung.
You created /etc/apache2/sites-available/payload.conf for a new virtual host. Which sequence actually makes Apache serve the new site?
On a default Kali installation, why does http://localhost refuse connections immediately after apt install apache2 completes?