Apache HTTP Server is a web server for serving sites over HTTP and HTTPS. This guide helps your AI assistant make sure it is configured securely: the TLS modules enabled, an HTTPS virtual host configured, HTTP redirected to HTTPS, and authentication required where needed.
If an AI assistant is helping you secure a deployment, give it the prompt below:
Read the secureconfig guide at
https://raw.githubusercontent.com/jposluns/secureconfig/main/apache.md
in full, including the section for AI assistants at the end. Then, for my
deployment: state which of its recommendations apply and the exact changes
to make; compare the versions the guide was written against with the
releases I am running and with the vendor's current releases, and flag any
guidance a newer release may have changed; and run or adapt the guide's
Verify steps where you can. List separately every item you could not
verify instead of reporting it as passed.
Written against Apache HTTP Server 2.4, Apache TLSv1.3 minimum 2.4.36+, Apache per-vhost protocol minimum 2.4.42+, Apache chain-file minimum 2.4.8, httpd htpasswd 2.4.69, OpenSSL qualification 1.1.1+, Certbot Apache installation v2.3.0, and Debian apache2 packaging 2.4.69-1, plus 5 more recorded bases; 1 further source carries no recorded version. Metadata reviewed 2026-10-18; documentation checked September 2026. The guide records 20 claims, all reasoned from cited sources.
A newer release of any of this software can make version-specific details here outdated. To prioritize an update, open a GitHub issue, send a pull request, add a request under requests/, or reach the maintainer as CONTRIBUTING.md describes. The machine-readable version basis and claim list are in the section for AI assistants at the end of this guide.
Applies to Apache 2.4. Get a certificate first: free-certificates.md for a public host (note that certbot --apache obtains and installs the certificate and, at the time of writing, enables the HTTP-to-HTTPS redirect by default (--redirect requests it explicitly), but review its generated TLS config against steps 1 to 3 and add HSTS yourself, since certbot's --hsts is off by default), or self-signed.md for internal use.
# Debian/Ubuntu
sudo a2enmod ssl headers
sudo a2ensite default-ssl # or your own :443 vhost file
# RHEL/Fedora
sudo dnf install mod_ssl httpd-toolsDebian apache2 2.4.69-1 installs a2enmod, links a2ensite to it, and ships the default-ssl configuration. Fedora f44 httpd packaging at commit 6df70d39 defines the mod_ssl and httpd-tools packages. These packaging citations do not establish every Debian/Ubuntu or RHEL release. (https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/changelog#L1; https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/apache2.install#L1-7; https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/apache2.links#L7; https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/config-dir/sites-available/default-ssl.conf#L1-4; https://src.fedoraproject.org/rpms/httpd/blob/6df70d392dace11a7c01ceffc5d8a929de0b7a35/f/httpd.spec#_204-212)
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# TLS 1.2 minimum. The TLSv1.3 keyword needs Apache 2.4.36+ with OpenSSL 1.1.1+;
# on older builds use: SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# A per-vhost SSLProtocol takes effect independently only on Apache 2.4.42+ (with OpenSSL
# 1.1.1+ and client SNI); on older builds the base or first-listed :443 vhost sets the floor,
# so set the same SSLProtocol in the global/base config as well.
SSLProtocol -all +TLSv1.2 +TLSv1.3
# Send HSTS only once HTTPS is confirmed working. Add `includeSubDomains` ONLY after every
# subdomain also serves valid HTTPS: it forces them all onto HTTPS and blocks any HTTP-only one.
Header always set Strict-Transport-Security "max-age=31536000"
</VirtualHost>On Apache 2.4.8 and later, SSLCertificateFile may contain the certificate plus its chain (certbot's fullchain.pem), and SSLCertificateChainFile is deprecated. For cipher suites beyond the protocol floor, generate a current list with the Mozilla SSL Configuration Generator rather than copying one from an old tutorial.
<VirtualHost *:80>
ServerName example.com
Redirect permanent / https://example.com/
</VirtualHost>Keep port 80 serving only this redirect (and ACME HTTP-01 challenges if certbot uses the webroot method).
Application-level login is preferable (authentication.md). To gate a whole site or path at the server, use basic authentication over TLS with bcrypt-hashed entries:
sudo htpasswd -B -C 12 -c /etc/apache2/.htpasswd admin # suggested Debian/Ubuntu path; /etc/httpd/conf/.htpasswd is the suggested RHEL/Fedora choice. -C 12 sets bcrypt cost; -c creates the file only for the first userDebian apache2 2.4.69-1 provides htpasswd in apache2-utils; Fedora f44 httpd packaging at commit 6df70d39 puts it in httpd-tools. In httpd 2.4.69, -B selects bcrypt, -C sets its cost, and the default bcrypt cost is 5. The OWASP cheat sheet at commit 72865b1e recommends a work factor of at least 10 for legacy bcrypt; 12 is this guide's choice. Both password-file paths above are guide choices. (https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/changelog#L1; https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/control#L92-102; https://src.fedoraproject.org/rpms/httpd/blob/6df70d392dace11a7c01ceffc5d8a929de0b7a35/f/httpd.spec#_819-824; https://github.com/apache/httpd/blob/2.4.69/support/htpasswd.c#L100-L128; https://github.com/apache/httpd/blob/2.4.69/support/passwd_common.h#L43-L45; https://github.com/apache/httpd/blob/2.4.69/support/passwd_common.c#L290-L295; https://github.com/OWASP/CheatSheetSeries/blob/72865b1e3b5754246a101778dc00b37f9c233373/cheatsheets/Password_Storage_Cheat_Sheet.md#L13)
<Location "/">
AuthType Basic
AuthName "Restricted"
# suggested Debian/Ubuntu path; on RHEL/Fedora use /etc/httpd/conf/.htpasswd (match the htpasswd -c path above)
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Location>For machine-to-machine links, mutual TLS is stronger than passwords. Put it in a SEPARATE :443 vhost dedicated to machine clients, not the human-facing one: vhost-level SSLVerifyClient require makes every client present a trusted certificate, so a browser user with no client certificate is rejected during the TLS handshake before basic auth can apply. SSLCACertificateFile belongs at server or vhost level, not inside <Location>:
SSLCACertificateFile /etc/ssl/certs/internal-ca.crt
SSLVerifyClient require
SSLVerifyDepth 2Basic authentication is single-factor. Authelia v4.39.28 says Apache is unsupported for its proxy integration (https://github.com/authelia/authelia/blob/v4.39.28/docs/content/integration/proxies/support.md#L112-L115). For human-facing sites, use mod_auth_openidc v2.4.20.3 to make Apache an OIDC relying party (https://github.com/OpenIDC/mod_auth_openidc/blob/v2.4.20.3/README.md#L11-L20), and configure MFA at the identity provider as this guide advises. Cloudflare Access is another suggested option for fronting an Apache origin (this guide's assessment); its self-hosted application places an authentication layer between users and an origin server (https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L14-L16; https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L40-L54), and an Access policy can require MFA (https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx#L35-L81); see mfa.md. This guide assesses that an Apache origin reachable without passing through Access is not protected by it (https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L45-L45; https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L48-L48).
5. Verify (REASONED: all Verify scenarios follow the cited Apache documentation; this guide records no exposed/fixed deployment run. This metadata-only review has no authorized Apache deployment fixture.)
These are read-and-judge checks. curl exits 0 for a 401 as readily as for a 200, so the
status code is printed and you compare it; nothing here fails on its own.
sudo apachectl configtest && sudo systemctl reload apache2 # httpd on RHEL
curl -q -sSI --noproxy '*' http://example.com/ # expect 301 with a https:// Location
curl -q -sS -o /dev/null --noproxy '*' -w '%{http_code}\n' https://example.com/
# 200 before section 4, 401 after it. Once
# authentication is on, a 200 here is the finding
# Read every listener. Do not filter to the ports you expect: a filter cannot show you a port
# you did not think of, which is the whole question, and `grep ':(80|443)'` also matches an
# address such as [2001:db8:80::1]:9000.
ss -tlnp
# A request whose name matches no ServerName or ServerAlias does not fail. Apache falls through
# to "the first listed virtual host that matches" the address and port, so a vhost listed
# before yours over the same DocumentRoot answers without your authentication.
#
# Over TLS the name that selects the vhost is the SNI one, not the Host header: Apache says
# that when the handshake carries it, "that hostname is used below just like the Host: header
# would be used on a non-SSL connection". So setting only the header tests nothing. It leaves
# SNI saying example.com, which selects YOUR vhost and answers 401, or makes mod_ssl reject the
# mismatched pair with 421; both look like a pass and neither is the request an attacker sends.
# The URL hostname supplies SNI and the Host header; --connect-to changes only the connection destination (your address):
curl -q -sS -o /dev/null --noproxy '*' -w '%{http_code}\n' \
--connect-to REPLACE_WITH_AN_UNCONFIGURED_NAME:443:example.com:443 \
https://REPLACE_WITH_AN_UNCONFIGURED_NAME/REPLACE_WITH_A_PROTECTED_PATH
# 401 is the pass. 200 means another vhost served the
# protected resource with no authentication at allThat name has to be one your certificate already covers, typically a spare label under a
wildcard SAN, because the guide will not tell you to disable certificate verification to run a
test. If the certificate covers no name you can spare, this check is a configuration review
instead: list the vhosts for that address and port, and confirm the first one Apache would
choose does not serve the protected DocumentRoot.
sudo apachectl -S # the vhost list, in Apache's own matching order- Serving the application on port 80 next to the HTTPS vhost instead of only redirecting.
- Enabling
mod_sslwithoutHeader/HSTS, leaving downgrade open on repeat visits. - World-readable private keys; keep them
0600and root-owned. - Protecting
/adminbut leaving/apiopen;Requirerules apply per path, so enumerate what is public.
- Apache SSL/TLS how-to: https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html
- Apache authentication how-to: https://httpd.apache.org/docs/2.4/howto/auth.html
- Apache name-based virtual hosts, for which vhost answers an unmatched Host header: https://httpd.apache.org/docs/2.4/vhosts/name-based.html
- Apache mod_ssl
SSLVHostSNIPolicy, for the 421 a mismatched SNI and Host pairing can produce (TLSv1.3: Apache 2.4.36+ with OpenSSL 1.1.1+; per-vhost SSLProtocol: Apache 2.4.42+ with OpenSSL 1.1.1+ and client SNI; chain in SSLCertificateFile: Apache 2.4.8+): https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslvhostsnipolicy - Apache virtual host matching in detail, for SNI selecting the vhost on a TLS connection: https://httpd.apache.org/docs/2.4/vhosts/details.html
- Mozilla SSL Configuration Generator: https://ssl-config.mozilla.org/
- Certbot v2.3.0 Apache installation (checked October 2026): https://github.com/certbot/certbot/blob/v2.3.0/certbot/docs/using.rst#L104-L106
- Certbot v2.3.0 redirect default and enhancement application (checked October 2026): https://github.com/certbot/certbot/blob/v2.3.0/certbot/certbot/_internal/client.py#L646 ; https://github.com/certbot/certbot/blob/v2.3.0/certbot/certbot/_internal/client.py#L674-L677
- Certbot v2.3.0 redirect and opt-in HSTS defaults (checked October 2026): https://github.com/certbot/certbot/blob/v2.3.0/certbot/certbot/_internal/constants.py#L66-L68
- Apache 2.4
Header always setresponse-header handling (checked October 2026): https://httpd.apache.org/docs/2.4/mod/mod_headers.html - Debian apache2 packaging version 2.4.69-1 (checked October 2026): https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/changelog#L1
- Debian apache2 2.4.69-1 helper,
a2ensitelink and default SSL configuration: https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/apache2.install#L1-7 ; https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/apache2.links#L7 ; https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/config-dir/sites-available/default-ssl.conf#L1-4 - Debian apache2 2.4.69-1
apache2-utilspackage: https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/control#L92-102 - Fedora f44 httpd packaging at commit 6df70d39 package definitions and
htpasswdfile list: https://src.fedoraproject.org/rpms/httpd/blob/6df70d392dace11a7c01ceffc5d8a929de0b7a35/f/httpd.spec#_204-212 ; https://src.fedoraproject.org/rpms/httpd/blob/6df70d392dace11a7c01ceffc5d8a929de0b7a35/f/httpd.spec#_819-824 - httpd 2.4.69
htpasswdoptions and bcrypt default: https://github.com/apache/httpd/blob/2.4.69/support/htpasswd.c#L100-L128 ; https://github.com/apache/httpd/blob/2.4.69/support/passwd_common.h#L43-L45 ; https://github.com/apache/httpd/blob/2.4.69/support/passwd_common.c#L290-L295 - OWASP cheat sheet at commit 72865b1e legacy bcrypt guidance: https://github.com/OWASP/CheatSheetSeries/blob/72865b1e3b5754246a101778dc00b37f9c233373/cheatsheets/Password_Storage_Cheat_Sheet.md#L13
- Authelia v4.39.28 Apache proxy support: https://github.com/authelia/authelia/blob/v4.39.28/docs/content/integration/proxies/support.md#L112-L115
- Cloudflare Access self-hosted application at commit c896795b8e8bab68d05ae78d64c9cbcda1fdb104 (checked October 2026): https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L14-L16 ; https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L40-L54
- Cloudflare Access origin reachability at commit c896795b8e8bab68d05ae78d64c9cbcda1fdb104 (checked October 2026): https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L45-L45 ; https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L48-L48
- Cloudflare Access MFA policy controls at commit c896795b8e8bab68d05ae78d64c9cbcda1fdb104 (checked October 2026): https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx#L35-L81
- mod_auth_openidc v2.4.20.3 relying-party description: https://github.com/OpenIDC/mod_auth_openidc/blob/v2.4.20.3/README.md#L11-L20
This generated section holds the recorded versions, claim statuses and source mappings for AI assistants; use the prompt at the top. This guide is guidance to verify against your own deployment, not a certification, an audit, or a guarantee of compliance with any standard.
Version basis
AI assistants must compare the versions listed below with current releases and treat this guide as guidance, re-verifying version-specific defaults when newer releases exist.
DEMONSTRATED refers to historical evidence in this guide; REASONED records source reasoning, not a live demonstration. Unknown means no version recorded.
Components (recorded basis):
- apache: Apache HTTP Server (2.4)
- tls-min: Apache TLSv1.3 minimum (2.4.36+)
- sni-min: Apache per-vhost protocol minimum (2.4.42+)
- chain-min: Apache chain-file minimum (2.4.8)
- htpasswd: httpd htpasswd (2.4.69)
- openssl: OpenSSL qualification (1.1.1+)
- certbot: Certbot Apache installation (v2.3.0)
- debian-packaging: Debian apache2 packaging (2.4.69-1)
- fedora-packaging: Fedora f44 httpd packaging (commit 6df70d39)
- authelia: Authelia proxy support (v4.39.28)
- cloudflare-access: Cloudflare Access documentation (commit c896795b8e8bab68d05ae78d64c9cbcda1fdb104)
- openidc: mod_auth_openidc (v2.4.20.3)
- policy: Mozilla TLS policy (unknown)
- owasp: OWASP password storage cheat sheet (commit 72865b1e)
Claims (full source mapping in the JSON block below):
- certbot (REASONED; apache, certbot): The guide says certbot --apache installs certificates and redirects by default; --redirect is explicit and --hsts defaults off.
- modules (REASONED; apache, debian-packaging, fedora-packaging): Enable ssl/headers and a 443 vhost on Debian/Ubuntu, or install mod_ssl/httpd-tools on RHEL/Fedora; pinned packaging shows a2enmod, a2ensite (a link to a2enmod), default-ssl, and Fedora package names.
- tls (REASONED; apache): The 443 vhost enables TLS with a certificate chain and private key and TLSv1.2/TLSv1.3 only.
- tls-version (REASONED; apache, tls-min, openssl): TLSv1.3 needs Apache 2.4.36+ with OpenSSL 1.1.1+; older builds use SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1.
- vhost-floor (REASONED; apache, sni-min, openssl): Independent per-vhost SSLProtocol needs Apache 2.4.42+, OpenSSL 1.1.1+ and client SNI; older builds also need the floor in global/base config.
- chain (REASONED; apache, chain-min): Apache 2.4.8+ permits the chain in SSLCertificateFile; SSLCertificateChainFile is deprecated.
- hsts (REASONED; apache): Header always sets HSTS after HTTPS works; includeSubDomains requires valid HTTPS everywhere.
- cipher-policy (REASONED; policy): Generate explicit cipher policy with Mozilla rather than copying old lists.
- redirect (REASONED; apache): The 80 vhost sends a permanent redirect to the canonical HTTPS host; retain only redirects and needed ACME HTTP-01 paths.
- password-file (REASONED; apache, debian-packaging, fedora-packaging, htpasswd, owasp): Create a bcrypt htpasswd file with cost 12 and -c only for its first user; httpd 2.4.69 defaults bcrypt cost to 5 and OWASP recommends at least 10 for legacy bcrypt. Both password-file paths are guide choices.
- basic (REASONED; apache): AuthType Basic, AuthName, AuthUserFile and Require valid-user protect the chosen site/path over TLS; enumerate every public path.
- mtls (REASONED; apache): A separate machine-client 443 vhost requires a trusted certificate with SSLVerifyClient require and depth 2; SSLCACertificateFile is server/vhost scoped.
- mfa (REASONED; apache, authelia, openidc, cloudflare-access): Basic is single-factor; Authelia v4.39.28 says Apache is unsupported for its proxy integration, and mod_auth_openidc v2.4.20.3 is an OIDC relying party. Provider MFA is guide advice; Cloudflare Access documents self-hosted application and MFA policy controls; fronting an Apache origin is this guide's suggested option and assessment. This guide assesses that an Apache origin reachable without passing through Access is not protected by it.
- key-permissions (REASONED; apache): Keep private keys root-owned and mode 0600.
- verify-config (REASONED; apache): Run apachectl configtest before service reload; no outcome is recorded.
- verify-redirect (REASONED; apache): HTTP should return 301 with an HTTPS Location.
- verify-auth (REASONED; apache): Read printed status: curl can exit 0 for 200 or 401; expect 200 before auth and 401 after it.
- verify-listeners (REASONED; apache): Inspect the entire listener table, without filtering away unexpected ports.
- verify-unmatched (REASONED; apache): Use an unconfigured certificate-covered URL name for both SNI and Host; 401 passes, 200 exposes a protected resource through another vhost. Host-only probes can misleadingly give 401 or 421.
- verify-vhost-review (REASONED; apache): If no spare certificate-covered name exists, use apachectl -S and review that the first matching vhost cannot serve the protected DocumentRoot.
{
"schema": 1,
"checked": "2026-10-18",
"documentation_checked": "2026-09",
"body_sha256": "1337f946ff115e07d47b82d92b16b180220ad1d5cada50672a7a286bf5e4bbd3",
"components": {
"apache": {
"name": "Apache HTTP Server",
"basis": "2.4",
"sources": {
"sde155f1667f3": "https://httpd.apache.org/docs/2.4/ssl/ssl_howto.html",
"s99dcb49d86a4": "https://httpd.apache.org/docs/2.4/howto/auth.html",
"sc07f97af99e3": "https://httpd.apache.org/docs/2.4/vhosts/name-based.html",
"scf804f4940d7": "https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslvhostsnipolicy",
"s7c302c734a0d": "https://httpd.apache.org/docs/2.4/vhosts/details.html",
"s1dbb2636d050": "https://httpd.apache.org/docs/2.4/mod/mod_headers.html"
}
},
"tls-min": {
"name": "Apache TLSv1.3 minimum",
"basis": "2.4.36+",
"sources": {
"scf804f4940d7": "https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslvhostsnipolicy"
}
},
"sni-min": {
"name": "Apache per-vhost protocol minimum",
"basis": "2.4.42+",
"sources": {
"scf804f4940d7": "https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslvhostsnipolicy"
}
},
"chain-min": {
"name": "Apache chain-file minimum",
"basis": "2.4.8",
"sources": {
"scf804f4940d7": "https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslvhostsnipolicy"
}
},
"htpasswd": {
"name": "httpd htpasswd",
"basis": "2.4.69",
"sources": {
"s309ecdd34379": "https://github.com/apache/httpd/blob/2.4.69/support/htpasswd.c#L100-L128",
"s7850e1e9dfa1": "https://github.com/apache/httpd/blob/2.4.69/support/passwd_common.h#L43-L45",
"s1c1a101a70e7": "https://github.com/apache/httpd/blob/2.4.69/support/passwd_common.c#L290-L295"
}
},
"openssl": {
"name": "OpenSSL qualification",
"basis": "1.1.1+",
"sources": {
"scf804f4940d7": "https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslvhostsnipolicy"
}
},
"certbot": {
"name": "Certbot Apache installation",
"basis": "v2.3.0",
"sources": {
"sc74fcd0167d8": "https://github.com/certbot/certbot/blob/v2.3.0/certbot/docs/using.rst#L104-L106",
"sa453a66e4130": "https://github.com/certbot/certbot/blob/v2.3.0/certbot/certbot/_internal/client.py#L646",
"sacf90ffa5a6d": "https://github.com/certbot/certbot/blob/v2.3.0/certbot/certbot/_internal/client.py#L674-L677",
"s74412ad87016": "https://github.com/certbot/certbot/blob/v2.3.0/certbot/certbot/_internal/constants.py#L66-L68"
}
},
"debian-packaging": {
"name": "Debian apache2 packaging",
"basis": "2.4.69-1",
"sources": {
"s1c05297f1ef0": "https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/apache2.install#L1-7",
"s32bd234fb40a": "https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/config-dir/sites-available/default-ssl.conf#L1-4",
"sc9b152b1a444": "https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/apache2.links#L7",
"sd1c9de6b39aa": "https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/control#L92-102",
"s62f6ed2866ab": "https://salsa.debian.org/apache-team/apache2/-/blob/fc6e58fa5248fc058591097c94ac8fde34283519/debian/changelog#L1"
}
},
"fedora-packaging": {
"name": "Fedora f44 httpd packaging",
"basis": "commit 6df70d39",
"sources": {
"s7d73f140a3fe": "https://src.fedoraproject.org/rpms/httpd/blob/6df70d392dace11a7c01ceffc5d8a929de0b7a35/f/httpd.spec#_204-212",
"s4479577a2e6a": "https://src.fedoraproject.org/rpms/httpd/blob/6df70d392dace11a7c01ceffc5d8a929de0b7a35/f/httpd.spec#_819-824"
}
},
"authelia": {
"name": "Authelia proxy support",
"basis": "v4.39.28",
"sources": {
"s1de7fe72d011": "https://github.com/authelia/authelia/blob/v4.39.28/docs/content/integration/proxies/support.md#L112-L115"
}
},
"cloudflare-access": {
"name": "Cloudflare Access documentation",
"basis": "commit c896795b8e8bab68d05ae78d64c9cbcda1fdb104",
"sources": {
"sfddb92e438ca": "https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L14-L16",
"s7cafe1b17afd": "https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L40-L54",
"s603bdb6b24ab": "https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L45-L45",
"s863803bd9a1f": "https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/applications/http-apps/self-hosted-public-app.mdx#L48-L48",
"sdcac732541da": "https://github.com/cloudflare/cloudflare-docs/blob/c896795b8e8bab68d05ae78d64c9cbcda1fdb104/src/content/docs/cloudflare-one/access-controls/policies/mfa-requirements.mdx#L35-L81"
}
},
"openidc": {
"name": "mod_auth_openidc",
"basis": "v2.4.20.3",
"sources": {
"s01e183d16f03": "https://github.com/OpenIDC/mod_auth_openidc/blob/v2.4.20.3/README.md#L11-L20"
}
},
"policy": {
"name": "Mozilla TLS policy",
"basis": "unknown",
"sources": {
"s529b0eabe2ed": "https://ssl-config.mozilla.org/"
}
},
"owasp": {
"name": "OWASP password storage cheat sheet",
"basis": "commit 72865b1e",
"sources": {
"s4531e65b6502": "https://github.com/OWASP/CheatSheetSeries/blob/72865b1e3b5754246a101778dc00b37f9c233373/cheatsheets/Password_Storage_Cheat_Sheet.md#L13"
}
}
},
"claims": {
"certbot": {"text": "The guide says certbot --apache installs certificates and redirects by default; --redirect is explicit and --hsts defaults off.", "components": ["apache", "certbot"], "sources": ["apache:sde155f1667f3", "certbot:sc74fcd0167d8", "certbot:sa453a66e4130", "certbot:sacf90ffa5a6d", "certbot:s74412ad87016"], "status": "REASONED"},
"modules": {"text": "Enable ssl/headers and a 443 vhost on Debian/Ubuntu, or install mod_ssl/httpd-tools on RHEL/Fedora; pinned packaging shows a2enmod, a2ensite (a link to a2enmod), default-ssl, and Fedora package names.", "components": ["apache", "debian-packaging", "fedora-packaging"], "sources": ["apache:sde155f1667f3", "debian-packaging:s62f6ed2866ab", "debian-packaging:s1c05297f1ef0", "debian-packaging:sc9b152b1a444", "debian-packaging:s32bd234fb40a", "fedora-packaging:s7d73f140a3fe"], "status": "REASONED"},
"tls": {"text": "The 443 vhost enables TLS with a certificate chain and private key and TLSv1.2/TLSv1.3 only.", "components": ["apache"], "sources": ["apache:sde155f1667f3", "apache:scf804f4940d7"], "status": "REASONED"},
"tls-version": {"text": "TLSv1.3 needs Apache 2.4.36+ with OpenSSL 1.1.1+; older builds use SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1.", "components": ["apache", "tls-min", "openssl"], "sources": ["apache:scf804f4940d7", "tls-min:scf804f4940d7", "openssl:scf804f4940d7"], "status": "REASONED"},
"vhost-floor": {"text": "Independent per-vhost SSLProtocol needs Apache 2.4.42+, OpenSSL 1.1.1+ and client SNI; older builds also need the floor in global/base config.", "components": ["apache", "sni-min", "openssl"], "sources": ["apache:scf804f4940d7", "apache:s7c302c734a0d", "sni-min:scf804f4940d7", "openssl:scf804f4940d7"], "status": "REASONED"},
"chain": {"text": "Apache 2.4.8+ permits the chain in SSLCertificateFile; SSLCertificateChainFile is deprecated.", "components": ["apache", "chain-min"], "sources": ["apache:scf804f4940d7", "chain-min:scf804f4940d7"], "status": "REASONED"},
"hsts": {"text": "Header always sets HSTS after HTTPS works; includeSubDomains requires valid HTTPS everywhere.", "components": ["apache"], "sources": ["apache:sde155f1667f3", "apache:s1dbb2636d050"], "status": "REASONED"},
"cipher-policy": {"text": "Generate explicit cipher policy with Mozilla rather than copying old lists.", "components": ["policy"], "sources": ["policy:s529b0eabe2ed"], "status": "REASONED"},
"redirect": {"text": "The 80 vhost sends a permanent redirect to the canonical HTTPS host; retain only redirects and needed ACME HTTP-01 paths.", "components": ["apache"], "sources": ["apache:sc07f97af99e3", "apache:sde155f1667f3"], "status": "REASONED"},
"password-file": {"text": "Create a bcrypt htpasswd file with cost 12 and -c only for its first user; httpd 2.4.69 defaults bcrypt cost to 5 and OWASP recommends at least 10 for legacy bcrypt. Both password-file paths are guide choices.", "components": ["apache", "debian-packaging", "fedora-packaging", "htpasswd", "owasp"], "sources": ["apache:s99dcb49d86a4", "debian-packaging:s62f6ed2866ab", "debian-packaging:sd1c9de6b39aa", "fedora-packaging:s4479577a2e6a", "htpasswd:s309ecdd34379", "htpasswd:s7850e1e9dfa1", "htpasswd:s1c1a101a70e7", "owasp:s4531e65b6502"], "status": "REASONED"},
"basic": {"text": "AuthType Basic, AuthName, AuthUserFile and Require valid-user protect the chosen site/path over TLS; enumerate every public path.", "components": ["apache"], "sources": ["apache:s99dcb49d86a4"], "status": "REASONED"},
"mtls": {"text": "A separate machine-client 443 vhost requires a trusted certificate with SSLVerifyClient require and depth 2; SSLCACertificateFile is server/vhost scoped.", "components": ["apache"], "sources": ["apache:scf804f4940d7"], "status": "REASONED"},
"mfa": {"text": "Basic is single-factor; Authelia v4.39.28 says Apache is unsupported for its proxy integration, and mod_auth_openidc v2.4.20.3 is an OIDC relying party. Provider MFA is guide advice; Cloudflare Access documents self-hosted application and MFA policy controls; fronting an Apache origin is this guide's suggested option and assessment. This guide assesses that an Apache origin reachable without passing through Access is not protected by it.", "components": ["apache", "authelia", "openidc", "cloudflare-access"], "sources": ["apache:s99dcb49d86a4", "authelia:s1de7fe72d011", "openidc:s01e183d16f03", "cloudflare-access:sfddb92e438ca", "cloudflare-access:s7cafe1b17afd", "cloudflare-access:sdcac732541da", "cloudflare-access:s603bdb6b24ab", "cloudflare-access:s863803bd9a1f"], "status": "REASONED"},
"key-permissions": {"text": "Keep private keys root-owned and mode 0600.", "components": ["apache"], "sources": ["apache:sde155f1667f3"], "status": "REASONED"},
"verify-config": {"text": "Run apachectl configtest before service reload; no outcome is recorded.", "components": ["apache"], "sources": ["apache:sde155f1667f3"], "status": "REASONED", "verify": [1]},
"verify-redirect": {"text": "HTTP should return 301 with an HTTPS Location.", "components": ["apache"], "sources": ["apache:sc07f97af99e3"], "status": "REASONED", "verify": [1]},
"verify-auth": {"text": "Read printed status: curl can exit 0 for 200 or 401; expect 200 before auth and 401 after it.", "components": ["apache"], "sources": ["apache:s99dcb49d86a4"], "status": "REASONED", "verify": [1]},
"verify-listeners": {"text": "Inspect the entire listener table, without filtering away unexpected ports.", "components": ["apache"], "sources": ["apache:sc07f97af99e3"], "status": "REASONED", "verify": [1]},
"verify-unmatched": {"text": "Use an unconfigured certificate-covered URL name for both SNI and Host; 401 passes, 200 exposes a protected resource through another vhost. Host-only probes can misleadingly give 401 or 421.", "components": ["apache"], "sources": ["apache:sc07f97af99e3", "apache:scf804f4940d7", "apache:s7c302c734a0d"], "status": "REASONED", "verify": [1]},
"verify-vhost-review": {"text": "If no spare certificate-covered name exists, use apachectl -S and review that the first matching vhost cannot serve the protected DocumentRoot.", "components": ["apache"], "sources": ["apache:sc07f97af99e3", "apache:s7c302c734a0d"], "status": "REASONED", "verify": [2]}
}
}