Enabling HTTP Strict Transport Security (HSTS) forces modern browsers to stick to HTTPS for a site, shutting down protocol-downgrade attacks and accidental plain-HTTP visits that can leak cookies or session tokens.

HSTS works by sending a Strict-Transport-Security response header over a successful HTTPS connection. The browser caches the policy for the declared max-age, automatically upgrading future HTTP navigations to HTTPS for that host while the policy is valid.

Because browsers ignore the header on HTTP responses, the HTTPS endpoint must be healthy first and plain HTTP should redirect to HTTPS. Examples below use the Debian-style Apache layout (/etc/apache2, apache2 service); adjust file paths and the service name on other distributions, and remember that rollback is client-cached (a temporary Strict-Transport-Security: max-age=0 over HTTPS is the usual way to clear a policy early).

Steps to enable HSTS in Apache:

  1. Confirm the site responds over HTTPS without certificate errors.
    $ curl --head https://mysite.example/
    HTTP/1.1 200 OK
    Date: Sat, 13 Dec 2025 12:34:56 GMT
    Server: Apache
    Content-Type: text/html; charset=UTF-8
  2. Confirm the HTTP endpoint redirects to HTTPS.
    $ curl --head http://mysite.example/
    HTTP/1.1 301 Moved Permanently
    Location: https://mysite.example/
    Connection: close
    Content-Type: text/html; charset=iso-8859-1

    If the Location header does not point at https://mysite.example, add or fix the VirtualHost *:80 redirect before enabling HSTS.

  3. Enable the headers module to allow Apache to emit the Strict-Transport-Security header.
    $ sudo a2enmod headers
    Enabling module headers.
    To activate the new configuration, you need to run:
      systemctl restart apache2

    On RHEL-family systems, mod_headers is commonly available already and the service name is usually httpd.

  4. Open the site’s HTTPS VirtualHost configuration file.
    $ sudo vi /etc/apache2/sites-available/000-mysite.conf
  5. Add the Strict-Transport-Security header inside the <VirtualHost *:443> block.
    <VirtualHost *:443>
            # ...
            <IfModule mod_headers.c>
                    Header always set Strict-Transport-Security "max-age=86400"
            </IfModule>
    </VirtualHost>

    A long max-age can lock browsers into HTTPS for that hostname until the timer expires, even if the header is later removed; start small, validate, then increase. Avoid includeSubDomains unless every subdomain is reachable over HTTPS, or browsers will refuse HTTP on subdomains too, and treat preload as a one-way door if a preload list submission is intended.

    After a clean rollout, a common hardened value is max-age=31536000; includeSubDomains; a rollback policy is typically max-age=0 until clients expire the cached setting.

  6. Validate the Apache configuration syntax.
    $ sudo apache2ctl -t
    Syntax OK
  7. Restart the apache2 service to apply the change.
    $ sudo systemctl restart apache2

    A restart can briefly interrupt in-flight connections; use a reload if the deployment requires a graceful config apply.

  8. Check the HTTPS response headers for a Strict-Transport-Security line.
    $ curl --head https://mysite.example/
    HTTP/1.1 200 OK
    Date: Sat, 13 Dec 2025 12:36:02 GMT
    Server: Apache
    Strict-Transport-Security: max-age=86400
    Content-Type: text/html; charset=UTF-8

    HTTP/2 responses may show lower-case header names in curl output; the presence of the policy and the max-age value is what matters.

Discuss the article:

Comment anonymously. Login not required.