Site AI Auditod Internet Solutions

How to Add Security Headers on Apache, Nginx, WordPress and CDNs

15. září 2026Čtení: 8 minZabezpečení a SSL
How to Add Security Headers on Apache, Nginx, WordPress and CDNs

Short answer: Add security headers where responses are generated or passed through: in the Apache virtual host or .htaccess with Header always set, in the Nginx server block with add_header … always, or as response header rules in your CDN. A solid baseline for most HTTPS sites is Strict-Transport-Security, X-Content-Type-Options, X-Frame-Options with CSP frame-ancestors, Referrer-Policy and Permissions-Policy, with a full Content-Security-Policy added later after testing. Set each header in one place only, then verify with curl -sI on several page types.

Most explanations of security headers stop at “add this header”. In practice, the hard part is knowing where to add it on your particular setup, and making sure it appears on every page without duplicates. This guide collects copy-ready configurations for the most common environments – Apache and LiteSpeed, Nginx, WordPress hosting and CDNs – with the pitfalls that cause headers to go missing. If you want to understand what each header does first, see the related reading at the end.

The baseline set

These values are safe for most sites that already run fully on HTTPS:

Strict-Transport-Security: max-age=31536000
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'; upgrade-insecure-requests
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Adjust before deploying: start HSTS with a short max-age if you are unsure every page works over HTTPS; allow payment or geolocation for self if your checkout or store locator uses them; allow partner domains in frame-ancestors if they embed your pages. A complete Content-Security-Policy that restricts scripts needs its own report-only testing phase and is best added as a separate project.

Before changing anything, record what your site sends today with curl -sI https://example.com. Some hosts, CDNs and CMS platforms already add a few of these headers, and knowing the starting point makes it easy to spot duplicates and to confirm that your change actually made a difference. Save the output in your site notes together with the date.

Apache and LiteSpeed

Make sure mod_headers is enabled (on Debian and Ubuntu: a2enmod headers, then reload). Add the headers to the HTTPS virtual host, or to .htaccess in the web root on shared hosting:

<IfModule mod_headers.c>
  Header always set Strict-Transport-Security "max-age=31536000"
  Header always set X-Content-Type-Options "nosniff"
  Header always set X-Frame-Options "SAMEORIGIN"
  Header always set Content-Security-Policy "frame-ancestors 'self'; upgrade-insecure-requests"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"
</IfModule>

Notes:

Nginx

Add the headers to each HTTPS server block, or to an include file used by all of them:

add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self'; upgrade-insecure-requests" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

The most important Nginx pitfall: add_header directives are inherited from the server block into a location block only if that location has no add_header of its own. A location that adds, for example, a Cache-Control header for images or a CORS header for fonts silently drops all your security headers for those URLs. Solutions: repeat the security headers in such locations, or put them in a snippet file and include it everywhere. Run nginx -t before reloading.

WordPress and other CMS hosting

WordPress itself sends only a few headers (for example X-Frame-Options on the login and admin pages). You have three options:

Server configuration or .htaccess (preferred)

Use the Apache or Nginx examples above. This covers every response, including images, feeds and plugin endpoints, and does not depend on PHP running.

A security or header plugin

On hosting where you cannot edit server files, a plugin can add headers to pages generated by WordPress. It will not cover static files served directly by the server, and it stops working if the plugin is disabled. Choose one plugin for this job; two plugins setting the same header create conflicts.

Hosting panel settings

Some managed WordPress hosts offer header settings in their dashboard or apply sensible defaults. Check what is already sent before adding your own, to avoid duplicates.

IIS and Windows hosting

On Microsoft IIS, custom response headers are set in the site’s web.config file or through IIS Manager under “HTTP Response Headers”. A web.config section looks like this:

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Strict-Transport-Security" value="max-age=31536000" />
      <add name="X-Content-Type-Options" value="nosniff" />
      <add name="X-Frame-Options" value="SAMEORIGIN" />
      <add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

While you are there, remove the X-Powered-By header with a <remove name="X-Powered-By" /> line, since it reveals the framework in use.

CDNs and reverse proxies

If a CDN sits in front of your site, you can add headers there with response header rules or edge functions. Advantages: headers apply to cached and uncached responses alike, and you manage them in one place even across several origin servers. Things to check:

Verify on every page type

After deploying, check headers on a representative set of URLs, not just the home page:

for u in / /about/ /contact/ /wp-login.php /wp-content/uploads/logo.png /nonexistent-page/; do
  echo "== $u"; curl -sI "https://example.com$u" | grep -i -E "strict-transport|x-content-type|x-frame|content-security|referrer-policy|permissions-policy"
done

Look for three problems: headers missing on some URLs (location blocks, subfolder overrides, static files), headers appearing twice with different values (server plus plugin or CDN), and typing mistakes in names or values. Browsers ignore malformed headers silently, so a typo means no protection. Then open the site in a browser and check the console for Content-Security-Policy or Permissions-Policy violations that indicate something legitimate was blocked. The OWASP Secure Headers Project maintains current recommended values if you want to compare.

Troubleshooting common problems

Keep headers from disappearing

Headers are easy to lose. A server rebuild resets configuration to defaults, a hosting migration leaves the old .htaccess behind, a CDN change drops custom rules, a developer adds a new Nginx location block. A few habits prevent this:

How Site AI Audit helps

Site AI Audit checks which security headers your site sends as part of every report, alongside the SSL certificate, HTTPS redirect and exposed software versions. Each missing or weak header comes with a plain-language explanation and the line to add, ranked by impact. After deploying your headers, a re-check confirms they are in place, and monitoring on paid plans alerts you if something breaks later. Run a free check.

Related reading

The bottom line

Adding security headers is mostly about putting a handful of lines in the right place: Header always set on Apache, add_header … always on Nginx, a single plugin or server rule on WordPress, or response header rules at your CDN. Set each header once, watch out for Nginx location blocks and duplicate sources, verify on several page types, and make the check part of every deployment so the headers stay in place.

FAQ

Where is the best place to add security headers?

As close to the edge as practical and in one place only: the web server configuration or the CDN. Plugins work too, but they only cover pages generated by the application and stop working if disabled.

Why are my Nginx headers missing on some pages?

Usually because a location block has its own add_header directive, which stops inheritance from the server block. Repeat the security headers in that location or include them from a shared snippet.

Can I add security headers on shared hosting?

Usually yes, through .htaccess on Apache or LiteSpeed hosting, or through the hosting panel. If .htaccess changes cause errors, ask the host whether mod_headers is enabled.

Is it a problem if a header appears twice?

It can be. Browsers may combine or reject duplicate values, and two different Content-Security-Policy headers are both enforced. Keep one source for each header.

Do security headers need to be on images and other files?

The most important protection applies to HTML pages, but headers such as X-Content-Type-Options and HSTS are also useful on other responses. Server-level configuration covers all of them automatically.

#HTTPS#Security headers#WordPress security
Zkontrolujte svůj web — zdarma.Co na webu opravit — a čím začít.
Začít zdarma

Další z blogu

Všechny články →
Internet Solutions

Další od našeho týmu

Vytvořilo Internet Solutions. Vyzkoušejte i naše další produkty — každý vám ušetří čas jiným způsobem.

internet-solutions.net ↗
Site AI Audit
Přehled soukromí

Tento web používá cookies, abychom vám mohli poskytnout co nejlepší uživatelský zážitek. Informace z cookies se ukládají ve vašem prohlížeči a slouží například k tomu, aby vás web při návratu poznal a náš tým viděl, které části webu jsou pro vás nejzajímavější a nejužitečnější.