{"id":3167,"date":"2025-12-08T14:34:52","date_gmt":"2025-12-08T11:34:52","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/http-security-headers-guide-how-to-correctly-set-hsts-csp-x-frame-options-and-referrer-policy\/"},"modified":"2025-12-08T14:34:52","modified_gmt":"2025-12-08T11:34:52","slug":"http-security-headers-guide-how-to-correctly-set-hsts-csp-x-frame-options-and-referrer-policy","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/http-security-headers-guide-how-to-correctly-set-hsts-csp-x-frame-options-and-referrer-policy\/","title":{"rendered":"HTTP Security Headers Guide: How to Correctly Set HSTS, CSP, X-Frame-Options and Referrer-Policy"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><p>When we harden customer websites at dchost.com, HTTP security headers are always among the first things we check. They are small pieces of text added to HTTP responses, but they dramatically change how browsers treat your site. With a few correctly configured headers, you reduce the impact of XSS attacks, prevent clickjacking, avoid leaking sensitive URLs in the referrer and make sure visitors always use HTTPS. In this guide, we will focus on four of the most important headers: <strong>HSTS<\/strong>, <strong>CSP<\/strong>, <strong>X-Frame-Options<\/strong> and <strong>Referrer-Policy<\/strong>. We will walk through what each one does, when to enable it, common pitfalls, and how to configure them on Apache, Nginx and typical shared hosting environments. Whether you run a small business site on shared hosting or manage multiple <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> and <a href=\"https:\/\/www.dchost.com\/dedicated-server\">dedicated server<\/a>s, you can implement these headers in a structured, low-risk way and make your security posture much stronger.<\/p>\n<div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#What_Are_HTTP_Security_Headers_and_Why_They_Matter\"><span class=\"toc_number toc_depth_1\">1<\/span> What Are HTTP Security Headers and Why They Matter<\/a><\/li><li><a href=\"#The_Four_Headers_We_Will_Configure\"><span class=\"toc_number toc_depth_1\">2<\/span> The Four Headers We Will Configure<\/a><\/li><li><a href=\"#HSTS_Strict-Transport-Security\"><span class=\"toc_number toc_depth_1\">3<\/span> HSTS: Strict-Transport-Security<\/a><ul><li><a href=\"#What_HSTS_Does\"><span class=\"toc_number toc_depth_2\">3.1<\/span> What HSTS Does<\/a><\/li><li><a href=\"#Preconditions_Before_Enabling_HSTS\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Preconditions Before Enabling HSTS<\/a><\/li><li><a href=\"#Enabling_HSTS_on_Nginx\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Enabling HSTS on Nginx<\/a><\/li><li><a href=\"#Enabling_HSTS_on_Apache_Including_htaccess\"><span class=\"toc_number toc_depth_2\">3.4<\/span> Enabling HSTS on Apache (Including .htaccess)<\/a><\/li><li><a href=\"#HSTS_Preload_Considerations\"><span class=\"toc_number toc_depth_2\">3.5<\/span> HSTS Preload Considerations<\/a><\/li><\/ul><\/li><li><a href=\"#CSP_Content-Security-Policy\"><span class=\"toc_number toc_depth_1\">4<\/span> CSP: Content-Security-Policy<\/a><ul><li><a href=\"#What_CSP_Does\"><span class=\"toc_number toc_depth_2\">4.1<\/span> What CSP Does<\/a><\/li><li><a href=\"#Key_CSP_Concepts\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Key CSP Concepts<\/a><\/li><li><a href=\"#Rolling_Out_CSP_Safely_with_Report-Only\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Rolling Out CSP Safely with Report-Only<\/a><\/li><li><a href=\"#Example_CSP_for_a_Typical_Site\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Example CSP for a Typical Site<\/a><\/li><li><a href=\"#Configuring_CSP_on_Nginx\"><span class=\"toc_number toc_depth_2\">4.5<\/span> Configuring CSP on Nginx<\/a><\/li><li><a href=\"#Configuring_CSP_on_Apache\"><span class=\"toc_number toc_depth_2\">4.6<\/span> Configuring CSP on Apache<\/a><\/li><\/ul><\/li><li><a href=\"#X-Frame-Options_Protecting_Against_Clickjacking\"><span class=\"toc_number toc_depth_1\">5<\/span> X-Frame-Options: Protecting Against Clickjacking<\/a><ul><li><a href=\"#What_X-Frame-Options_Does\"><span class=\"toc_number toc_depth_2\">5.1<\/span> What X-Frame-Options Does<\/a><\/li><li><a href=\"#X-Frame-Options_vs_CSP_frame-ancestors\"><span class=\"toc_number toc_depth_2\">5.2<\/span> X-Frame-Options vs CSP frame-ancestors<\/a><\/li><li><a href=\"#Configuring_X-Frame-Options_on_Nginx\"><span class=\"toc_number toc_depth_2\">5.3<\/span> Configuring X-Frame-Options on Nginx<\/a><\/li><li><a href=\"#Configuring_X-Frame-Options_on_Apache\"><span class=\"toc_number toc_depth_2\">5.4<\/span> Configuring X-Frame-Options on Apache<\/a><\/li><\/ul><\/li><li><a href=\"#Referrer-Policy_Controlling_What_Your_Users_Leak\"><span class=\"toc_number toc_depth_1\">6<\/span> Referrer-Policy: Controlling What Your Users Leak<\/a><ul><li><a href=\"#What_the_Referrer_Header_Is\"><span class=\"toc_number toc_depth_2\">6.1<\/span> What the Referrer Header Is<\/a><\/li><li><a href=\"#Common_Referrer-Policy_Values\"><span class=\"toc_number toc_depth_2\">6.2<\/span> Common Referrer-Policy Values<\/a><\/li><li><a href=\"#Configuring_Referrer-Policy_on_Nginx\"><span class=\"toc_number toc_depth_2\">6.3<\/span> Configuring Referrer-Policy on Nginx<\/a><\/li><li><a href=\"#Configuring_Referrer-Policy_on_Apache\"><span class=\"toc_number toc_depth_2\">6.4<\/span> Configuring Referrer-Policy on Apache<\/a><\/li><\/ul><\/li><li><a href=\"#Implementing_These_Headers_on_Shared_Hosting_VPS_and_Dedicated_Servers\"><span class=\"toc_number toc_depth_1\">7<\/span> Implementing These Headers on Shared Hosting, VPS and Dedicated Servers<\/a><ul><li><a href=\"#Where_to_Configure_Headers\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Where to Configure Headers<\/a><\/li><li><a href=\"#Combined_Example_for_Apache_htaccess-Friendly\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Combined Example for Apache (.htaccess-Friendly)<\/a><\/li><li><a href=\"#Combined_Example_for_Nginx\"><span class=\"toc_number toc_depth_2\">7.3<\/span> Combined Example for Nginx<\/a><\/li><\/ul><\/li><li><a href=\"#Testing_Monitoring_and_Avoiding_Surprises\"><span class=\"toc_number toc_depth_1\">8<\/span> Testing, Monitoring and Avoiding Surprises<\/a><ul><li><a href=\"#How_to_Test_Your_Headers\"><span class=\"toc_number toc_depth_2\">8.1<\/span> How to Test Your Headers<\/a><\/li><li><a href=\"#Common_Pitfalls\"><span class=\"toc_number toc_depth_2\">8.2<\/span> Common Pitfalls<\/a><\/li><li><a href=\"#Deployment_Strategy_We_Like_in_Real_Projects\"><span class=\"toc_number toc_depth_2\">8.3<\/span> Deployment Strategy We Like in Real Projects<\/a><\/li><\/ul><\/li><li><a href=\"#How_We_See_Customers_Apply_This_on_dchostcom\"><span class=\"toc_number toc_depth_1\">9<\/span> How We See Customers Apply This on dchost.com<\/a><\/li><li><a href=\"#Next_Steps_Turn_Security_Headers_into_a_Habit\"><span class=\"toc_number toc_depth_1\">10<\/span> Next Steps: Turn Security Headers into a Habit<\/a><\/li><\/ul><\/div>\n<h2><span id=\"What_Are_HTTP_Security_Headers_and_Why_They_Matter\">What Are HTTP Security Headers and Why They Matter<\/span><\/h2>\n<p>HTTP security headers are instructions your server sends to the browser along with every page. Instead of changing your HTML, CSS or JavaScript, you are changing the <strong>rules<\/strong> the browser must follow while rendering your site.<\/p>\n<p>They help with:<\/p>\n<ul>\n<li><strong>Enforcing HTTPS<\/strong> and preventing insecure HTTP access<\/li>\n<li><strong>Limiting where content can be loaded from<\/strong> (scripts, images, fonts, iframes)<\/li>\n<li><strong>Blocking clickjacking attacks<\/strong> where your site is framed inside a malicious page<\/li>\n<li><strong>Reducing how much data is leaked<\/strong> via the <code>Referer<\/code> header when users follow links<\/li>\n<\/ul>\n<p>Headers are one layer in a broader security stack. They complement TLS\/SSL, WAF rules, secure cookies, and DNS protections such as DNSSEC. If you are new to HTTPS configuration itself, you may want to review our articles on <a href=\"https:\/\/www.dchost.com\/blog\/en\/ssl-sertifika-guvenlik-guncellemeleri-ne-zaman-nasil-ve-neyi-degistirmelisiniz\/\">keeping SSL\/TLS security settings up to date on your servers<\/a> and <a href=\"https:\/\/www.dchost.com\/blog\/en\/ssl-sertifikasi-nedir-web-sitenizi-guvence-altina-almanin-yollari\/\">what an SSL certificate is and how it secures your website<\/a> before you commit to strict HSTS.<\/p>\n<h2><span id=\"The_Four_Headers_We_Will_Configure\">The Four Headers We Will Configure<\/span><\/h2>\n<p>In this guide we will focus on four key headers that we use widely across dchost.com hosting environments:<\/p>\n<ul>\n<li><strong>Strict-Transport-Security (HSTS)<\/strong> \u2013 tells browsers to always use HTTPS for your domain.<\/li>\n<li><strong>Content-Security-Policy (CSP)<\/strong> \u2013 defines which sources of scripts, styles, images, iframes, etc. are allowed.<\/li>\n<li><strong>X-Frame-Options<\/strong> \u2013 controls whether your pages may be embedded in an iframe.<\/li>\n<li><strong>Referrer-Policy<\/strong> \u2013 controls how much referrer information your users\u2019 browsers send to other sites.<\/li>\n<\/ul>\n<p>For a broader overview of related headers like <code>X-Content-Type-Options<\/code> and <code>Permissions-Policy<\/code>, you can later dive into our more advanced article <a href=\"https:\/\/www.dchost.com\/blog\/en\/http-guvenlik-basliklari-rehberi-hsts-csp-ve-digerlerini-ne-zaman-nasil-uygulamalisin\/\">about HTTP security headers configuration best practices<\/a>. Here, we will stay focused on getting these four high-impact headers right, with realistic examples.<\/p>\n<h2><span id=\"HSTS_Strict-Transport-Security\">HSTS: Strict-Transport-Security<\/span><\/h2>\n<h3><span id=\"What_HSTS_Does\">What HSTS Does<\/span><\/h3>\n<p><strong>HSTS<\/strong> (HTTP Strict Transport Security) tells browsers: \u201cFrom now on, only connect to this site over HTTPS. Never over plain HTTP.\u201d After a browser sees a valid HSTS header once, it will automatically upgrade any future <code>http:\/\/<\/code> requests to <code>https:\/\/<\/code> before sending them. This helps prevent downgrade attacks and cookie theft on insecure connections.<\/p>\n<p>A typical HSTS header looks like this:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\n<\/code><\/pre>\n<ul>\n<li><strong>max-age<\/strong>: How long (in seconds) the browser should remember to enforce HTTPS. One year is <code>31536000<\/code> seconds.<\/li>\n<li><strong>includeSubDomains<\/strong>: Apply HSTS to all subdomains as well (e.g. <code>www.<\/code>, <code>cdn.<\/code>, <code>api.<\/code>).<\/li>\n<li><strong>preload<\/strong>: Indicates you want to be added to browser HSTS preload lists (requires an extra submission step).<\/li>\n<\/ul>\n<h3><span id=\"Preconditions_Before_Enabling_HSTS\">Preconditions Before Enabling HSTS<\/span><\/h3>\n<p>Before we enable a strong HSTS policy for any customer, we always double-check:<\/p>\n<ul>\n<li><strong>HTTPS is fully working<\/strong> on the main domain and all relevant subdomains.<\/li>\n<li><strong>HTTP to HTTPS redirects<\/strong> are in place (301 redirects, not 302).<\/li>\n<li><strong>No mixed content<\/strong> remains (HTTP images, scripts or CSS on HTTPS pages).<\/li>\n<li>Any <strong>legacy systems or subdomains<\/strong> that still require HTTP are separated.<\/li>\n<\/ul>\n<p>Once HSTS with <code>includeSubDomains<\/code> and <code>preload<\/code> is deployed, you cannot go back to HTTP easily. That\u2019s why we often combine this step with a full HTTPS migration plan. If you are planning a protocol migration, our article <a href=\"https:\/\/www.dchost.com\/blog\/en\/httpden-httpse-gecis-rehberi-301-yonlendirme-hsts-ve-seoyu-korumak\/\">on moving from HTTP to HTTPS with 301 redirects and HSTS while preserving SEO<\/a> is a good companion read.<\/p>\n<h3><span id=\"Enabling_HSTS_on_Nginx\">Enabling HSTS on Nginx<\/span><\/h3>\n<p>On Nginx, add the header inside the server block that serves HTTPS:<\/p>\n<pre class=\"language-nginx line-numbers\"><code class=\"language-nginx\">server {\n    listen 443 ssl http2;\n    server_name example.com www.example.com;\n\n    # Your SSL configuration here\n\n    add_header Strict-Transport-Security &quot;max-age=31536000; includeSubDomains; preload&quot; always;\n\n    ...\n}\n<\/code><\/pre>\n<p>The <code>always<\/code> keyword ensures the header is added even on error pages (4xx\/5xx), which is recommended.<\/p>\n<h3><span id=\"Enabling_HSTS_on_Apache_Including_htaccess\">Enabling HSTS on Apache (Including .htaccess)<\/span><\/h3>\n<p>On Apache 2.4+, you can use:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&lt;IfModule mod_headers.c&gt;\n    Header always set Strict-Transport-Security &quot;max-age=31536000; includeSubDomains; preload&quot;\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n<p>You may place this in the main virtual host configuration or in <code>.htaccess<\/code> if you are on a shared hosting plan that allows it. On many dchost.com shared hosting accounts, customers manage headers via <code>.htaccess<\/code>, while VPS and dedicated server users typically configure them directly in the virtual host file for better performance and centralised control.<\/p>\n<h3><span id=\"HSTS_Preload_Considerations\">HSTS Preload Considerations<\/span><\/h3>\n<p><strong>HSTS Preload<\/strong> is a browser-maintained list of domains that must always use HTTPS, even on first visit. To be eligible you must:<\/p>\n<ul>\n<li>Serve a valid certificate for your domain.<\/li>\n<li>Redirect all HTTP traffic to HTTPS.<\/li>\n<li>Serve an HSTS header with <code>max-age &gt;= 31536000<\/code>, <code>includeSubDomains<\/code> and <code>preload<\/code> tokens.<\/li>\n<\/ul>\n<p>Preload is powerful but sticky. If you later decide to remove HTTPS from a subdomain, you must first remove <code>includeSubDomains<\/code> and <code>preload<\/code>, wait for HSTS to expire in clients, and then request removal from the preload list. For most small and medium sites, we recommend starting without <code>preload<\/code>, then enabling it when you are confident your HTTPS setup and renewal automation are stable.<\/p>\n<h2><span id=\"CSP_Content-Security-Policy\">CSP: Content-Security-Policy<\/span><\/h2>\n<h3><span id=\"What_CSP_Does\">What CSP Does<\/span><\/h3>\n<p><strong>Content-Security-Policy<\/strong> (CSP) is one of the most powerful web security headers you can deploy. It tells the browser exactly which sources are allowed for scripts, styles, images, fonts, frames, AJAX calls and more. If an attacker manages to inject malicious JavaScript into your page, a properly configured CSP can prevent that script from running.<\/p>\n<p>A very simple CSP example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Content-Security-Policy: default-src 'self'; img-src 'self' https:\/\/images.examplecdn.com; script-src 'self'; style-src 'self' 'unsafe-inline';\n<\/code><\/pre>\n<p>This policy means:<\/p>\n<ul>\n<li>By default (<code>default-src<\/code>), only load resources from the same origin.<\/li>\n<li>Images may also load from <code>images.examplecdn.com<\/code>.<\/li>\n<li>Scripts must come from the same origin only.<\/li>\n<li>Styles may come from the same origin, and inline styles are temporarily allowed (<code>'unsafe-inline'<\/code>).<\/li>\n<\/ul>\n<h3><span id=\"Key_CSP_Concepts\">Key CSP Concepts<\/span><\/h3>\n<ul>\n<li><strong>default-src<\/strong>: Fallback source list for directives you do not explicitly set.<\/li>\n<li><strong>script-src \/ style-src \/ img-src \/ font-src \/ connect-src<\/strong>: Finer-grained directives for each resource type.<\/li>\n<li><strong>&#8216;self&#8217;<\/strong>: Allows content from the same origin (same scheme, host and port).<\/li>\n<li><strong>&#8216;none&#8217;<\/strong>: Disallow all sources.<\/li>\n<li><strong>&#8216;unsafe-inline&#8217;<\/strong>: Allows inline scripts or styles; convenient but unsafe for scripts.<\/li>\n<li><strong>&#8216;nonce-&#8230;&#8217;<\/strong>: A random token you attach to allowed inline scripts\/styles per request.<\/li>\n<\/ul>\n<p>The most robust CSP setups use <strong>nonces or hashes<\/strong> instead of <code>'unsafe-inline'<\/code>. For advanced nonce\/hash-based CSP patterns on frameworks like WordPress and Laravel, we have a dedicated article: <a href=\"https:\/\/www.dchost.com\/blog\/en\/cspyi-dogru-kurmak-wordpress-laravelde-nonce-hash-report-to-ve-inline-scriptleri-tatli-tatli-ehlilestirmek\/\">how to implement CSP correctly using nonces, hashes and reporting<\/a>.<\/p>\n<h3><span id=\"Rolling_Out_CSP_Safely_with_Report-Only\">Rolling Out CSP Safely with Report-Only<\/span><\/h3>\n<p>CSP can easily break your site if you are too strict on day one. The recommended rollout process is:<\/p>\n<ol>\n<li><strong>Start with a Report-Only policy.<\/strong><br \/>Use <code>Content-Security-Policy-Report-Only<\/code> instead of <code>Content-Security-Policy<\/code>. Browsers will log violations but will not block anything.<\/li>\n<li><strong>Review violation reports and browser console.<\/strong><br \/>Open the browser dev tools (Console and Network tabs) and note which domains are being blocked in theory.<\/li>\n<li><strong>Adjust your policy iteratively.<\/strong><br \/>Add legitimate domains (CDNs, analytics, payment gateways) to the appropriate directives.<\/li>\n<li><strong>Switch to enforcing CSP.<\/strong><br \/>Once you are confident, change the header name to <code>Content-Security-Policy<\/code> and keep monitoring.<\/li>\n<\/ol>\n<h3><span id=\"Example_CSP_for_a_Typical_Site\">Example CSP for a Typical Site<\/span><\/h3>\n<p>Here is a moderate CSP example that works for many sites using a CDN and an analytics provider:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Content-Security-Policy: \n    default-src 'self'; \n    script-src 'self' https:\/\/cdn.examplecdn.com https:\/\/analytics.example-analytics.com; \n    style-src 'self' 'unsafe-inline' https:\/\/cdn.examplecdn.com; \n    img-src 'self' data: https:\/\/cdn.examplecdn.com; \n    font-src 'self' https:\/\/cdn.examplecdn.com; \n    connect-src 'self' https:\/\/analytics.example-analytics.com; \n    frame-ancestors 'self';\n<\/code><\/pre>\n<p>Notes:<\/p>\n<ul>\n<li><strong>data:<\/strong> is allowed for <code>img-src<\/code> in case you use small inline data URLs.<\/li>\n<li><strong>frame-ancestors<\/strong> controls who can embed your site; this overlaps with <code>X-Frame-Options<\/code> (see below).<\/li>\n<li>We still allow <code>'unsafe-inline'<\/code> for styles as a transitional compromise; for scripts we avoid it.<\/li>\n<\/ul>\n<h3><span id=\"Configuring_CSP_on_Nginx\">Configuring CSP on Nginx<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">add_header Content-Security-Policy \n&quot;default-src 'self'; \n script-src 'self' https:\/\/cdn.examplecdn.com; \n style-src 'self' 'unsafe-inline'; \n img-src 'self' data:; \n frame-ancestors 'self'&quot; always;\n<\/code><\/pre>\n<p>For readability, you can keep the policy in a separate file and include it in your server block, or use a single-line version if your Nginx version complains about line breaks.<\/p>\n<h3><span id=\"Configuring_CSP_on_Apache\">Configuring CSP on Apache<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&lt;IfModule mod_headers.c&gt;\n    Header always set Content-Security-Policy &quot;default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'self'&quot;\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n<p>If you are testing a policy, simply change <code>Content-Security-Policy<\/code> to <code>Content-Security-Policy-Report-Only<\/code> during the trial period.<\/p>\n<h2><span id=\"X-Frame-Options_Protecting_Against_Clickjacking\">X-Frame-Options: Protecting Against Clickjacking<\/span><\/h2>\n<h3><span id=\"What_X-Frame-Options_Does\">What X-Frame-Options Does<\/span><\/h3>\n<p><strong>X-Frame-Options<\/strong> tells the browser whether your page is allowed to be displayed inside an iframe or frame. This is important because of <strong>clickjacking<\/strong> attacks, where an attacker loads your site in a transparent frame on top of their own page and tricks the user into clicking on hidden buttons (for example, \u201cBuy now\u201d or \u201cDelete account\u201d).<\/p>\n<p>The main values are:<\/p>\n<ul>\n<li><strong>DENY<\/strong> \u2013 Never allow your site to be framed.<\/li>\n<li><strong>SAMEORIGIN<\/strong> \u2013 Allow framing only from the same origin as your site.<\/li>\n<li><strong>ALLOW-FROM uri<\/strong> \u2013 Allow only specific origins (obsolete and poorly supported).<\/li>\n<\/ul>\n<p>For most sites, <strong>SAMEORIGIN<\/strong> is a safe default. If your site is never legitimately framed at all, you can use <strong>DENY<\/strong>.<\/p>\n<h3><span id=\"X-Frame-Options_vs_CSP_frame-ancestors\">X-Frame-Options vs CSP frame-ancestors<\/span><\/h3>\n<p>Modern CSP provides <code>frame-ancestors<\/code>, which is a more flexible and standardised way to control framing. For example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Content-Security-Policy: frame-ancestors 'self' https:\/\/partner.example.com;\n<\/code><\/pre>\n<p>Because some older browsers still honour <code>X-Frame-Options<\/code> but not CSP, the common pattern is:<\/p>\n<ul>\n<li>Use <strong>CSP frame-ancestors<\/strong> as the primary control.<\/li>\n<li>Also set <strong>X-Frame-Options<\/strong> for backwards compatibility.<\/li>\n<\/ul>\n<h3><span id=\"Configuring_X-Frame-Options_on_Nginx\">Configuring X-Frame-Options on Nginx<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">add_header X-Frame-Options &quot;SAMEORIGIN&quot; always;\n<\/code><\/pre>\n<h3><span id=\"Configuring_X-Frame-Options_on_Apache\">Configuring X-Frame-Options on Apache<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&lt;IfModule mod_headers.c&gt;\n    Header always set X-Frame-Options &quot;SAMEORIGIN&quot;\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n<p>Remember to adjust this if you intentionally embed certain pages in iframes on other domains (for example, a white-label widget). In that case, you will likely move toward a CSP <code>frame-ancestors<\/code>-only model and drop <code>X-Frame-Options<\/code>.<\/p>\n<h2><span id=\"Referrer-Policy_Controlling_What_Your_Users_Leak\">Referrer-Policy: Controlling What Your Users Leak<\/span><\/h2>\n<h3><span id=\"What_the_Referrer_Header_Is\">What the Referrer Header Is<\/span><\/h3>\n<p>When a user clicks a link from site A to site B, browsers typically send a <code>Referer<\/code> header (yes, misspelled historically) that contains the URL of the page they came from. This can unintentionally leak sensitive data:<\/p>\n<ul>\n<li>Internal paths or query parameters revealing structure of your app.<\/li>\n<li>Session tokens or one-time URLs if they are included in the query string (which they should not be).<\/li>\n<li>Campaign tags and internal tracking parameters.<\/li>\n<\/ul>\n<p><strong>Referrer-Policy<\/strong> lets you control how much of that information is sent.<\/p>\n<h3><span id=\"Common_Referrer-Policy_Values\">Common Referrer-Policy Values<\/span><\/h3>\n<ul>\n<li><strong>no-referrer<\/strong>: Never send a referrer header.<\/li>\n<li><strong>no-referrer-when-downgrade<\/strong>: Send full URL to HTTPS sites, but not when going from HTTPS to HTTP (older default behaviour).<\/li>\n<li><strong>origin<\/strong>: Send only the scheme + host + port (e.g. <code>https:\/\/example.com<\/code>), without path or query.<\/li>\n<li><strong>strict-origin-when-cross-origin<\/strong>: Full URL on same-origin requests; only origin for cross-origin requests; nothing when downgrading from HTTPS to HTTP. This is an excellent privacy-conscious default.<\/li>\n<li><strong>same-origin<\/strong>: Full referrer for same-origin, no referrer for cross-origin.<\/li>\n<\/ul>\n<p>For most modern websites we host, we recommend:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Referrer-Policy: strict-origin-when-cross-origin\n<\/code><\/pre>\n<p>This still gives you useful analytics for internal navigation, while limiting how much information is leaked externally.<\/p>\n<h3><span id=\"Configuring_Referrer-Policy_on_Nginx\">Configuring Referrer-Policy on Nginx<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">add_header Referrer-Policy &quot;strict-origin-when-cross-origin&quot; always;\n<\/code><\/pre>\n<h3><span id=\"Configuring_Referrer-Policy_on_Apache\">Configuring Referrer-Policy on Apache<\/span><\/h3>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&lt;IfModule mod_headers.c&gt;\n    Header always set Referrer-Policy &quot;strict-origin-when-cross-origin&quot;\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n<h2><span id=\"Implementing_These_Headers_on_Shared_Hosting_VPS_and_Dedicated_Servers\">Implementing These Headers on Shared Hosting, VPS and Dedicated Servers<\/span><\/h2>\n<h3><span id=\"Where_to_Configure_Headers\">Where to Configure Headers<\/span><\/h3>\n<p>Where you add these headers depends on your hosting architecture:<\/p>\n<ul>\n<li><strong>Shared hosting with cPanel\/DirectAdmin:<\/strong> Typically via <code>.htaccess<\/code> (Apache) or via a control panel UI if provided.<\/li>\n<li><strong>VPS \/ Dedicated servers:<\/strong> Directly in your Nginx\/Apache virtual host configuration for better performance and consistency.<\/li>\n<li><strong>Reverse proxy setups:<\/strong> On the edge server (e.g. Nginx in front of Apache or PHP-FPM) so headers are applied to all backends.<\/li>\n<\/ul>\n<p>If you are currently on shared hosting and planning to move to a VPS to gain more control over server-level security, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/paylasimli-hostingden-vpse-sorunsuz-gecis-rehberi\/\">migrating from shared hosting to a VPS without downtime<\/a> walks through the typical transition path we see with growing projects.<\/p>\n<h3><span id=\"Combined_Example_for_Apache_htaccess-Friendly\">Combined Example for Apache (.htaccess-Friendly)<\/span><\/h3>\n<p>Here is a minimal but strong header set you can drop into <code>.htaccess<\/code> (if allowed) or into your Apache virtual host config:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&lt;IfModule mod_headers.c&gt;\n    # HSTS (only on HTTPS vhost)\n    Header always set Strict-Transport-Security &quot;max-age=31536000; includeSubDomains&quot; env=HTTPS\n\n    # Clickjacking protection\n    Header always set X-Frame-Options &quot;SAMEORIGIN&quot;\n\n    # Basic CSP (adjust for your site)\n    Header always set Content-Security-Policy &quot;default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'self'&quot;\n\n    # Referrer control\n    Header always set Referrer-Policy &quot;strict-origin-when-cross-origin&quot;\n&lt;\/IfModule&gt;\n<\/code><\/pre>\n<p>Make sure you place this on your HTTPS virtual host only for HSTS. Some configurations use an environment variable like <code>HTTPS=on<\/code> to avoid accidentally sending HSTS over HTTP.<\/p>\n<h3><span id=\"Combined_Example_for_Nginx\">Combined Example for Nginx<\/span><\/h3>\n<p>In your TLS server block:<\/p>\n<pre class=\"language-nginx line-numbers\"><code class=\"language-nginx\">server {\n    listen 443 ssl http2;\n    server_name example.com www.example.com;\n\n    # ... SSL\/TLS config ...\n\n    # HSTS\n    add_header Strict-Transport-Security &quot;max-age=31536000; includeSubDomains&quot; always;\n\n    # Clickjacking protection\n    add_header X-Frame-Options &quot;SAMEORIGIN&quot; always;\n\n    # CSP (start simple and tighten later)\n    add_header Content-Security-Policy \n    &quot;default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'self'&quot; always;\n\n    # Referrer control\n    add_header Referrer-Policy &quot;strict-origin-when-cross-origin&quot; always;\n\n    # ... rest of config ...\n}\n<\/code><\/pre>\n<p>After reloading Nginx, verify the headers using <code>curl -I https:\/\/example.com\/<\/code> or the Network tab in your browser\u2019s developer tools.<\/p>\n<h2><span id=\"Testing_Monitoring_and_Avoiding_Surprises\">Testing, Monitoring and Avoiding Surprises<\/span><\/h2>\n<h3><span id=\"How_to_Test_Your_Headers\">How to Test Your Headers<\/span><\/h3>\n<p>After configuring your headers:<\/p>\n<ul>\n<li>Use <strong>curl<\/strong>: <code>curl -I https:\/\/example.com\/<\/code> and check that each header is present once (no duplicates with different values).<\/li>\n<li>Use <strong>browser dev tools<\/strong>: Open the Network tab, click a request, and inspect the Response Headers section.<\/li>\n<li>Use online scanners: Tools like security header checkers can help spot missing or misconfigured headers. They are a complement to your own tests, not a replacement.<\/li>\n<\/ul>\n<p>Whenever we roll out new headers for customers, we also keep an eye on access and error logs. If you are new to log analysis, our guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/hosting-sunucu-loglarini-okumayi-ogrenin-apache-ve-nginx-ile-4xx-5xx-hatalarini-teshis-rehberi\/\">reading web server logs to diagnose 4xx\u20135xx errors on Apache and Nginx<\/a> is a practical reference.<\/p>\n<h3><span id=\"Common_Pitfalls\">Common Pitfalls<\/span><\/h3>\n<ul>\n<li><strong>Overly strict CSP on day one:<\/strong> Blocking legitimate scripts from CDNs, analytics or payment gateways. Roll out using Report-Only first.<\/li>\n<li><strong>HSTS on domains without stable HTTPS:<\/strong> If certificates expire or a subdomain is misconfigured, users may be locked out.<\/li>\n<li><strong>Multiple conflicting header values:<\/strong> For example, a CMS plugin adding one CSP and the server adding another. Consolidate into a single, well-managed policy.<\/li>\n<li><strong>Different headers on different paths:<\/strong> Inconsistent policies between the main site and admin areas can create confusing behaviour and troubleshooting difficulties.<\/li>\n<\/ul>\n<h3><span id=\"Deployment_Strategy_We_Like_in_Real_Projects\">Deployment Strategy We Like in Real Projects<\/span><\/h3>\n<p>In many real-world deployments, we follow this sequence:<\/p>\n<ol>\n<li><strong>Enable X-Frame-Options and Referrer-Policy<\/strong> \u2013 these are usually low-risk and easy wins.<\/li>\n<li><strong>Confirm HTTPS is solid<\/strong> (valid certificates, redirects, no mixed content), then <strong>enable HSTS without preload<\/strong>.<\/li>\n<li><strong>Introduce CSP in Report-Only mode<\/strong>, tune policies, then switch to enforcing mode when stable.<\/li>\n<li>After a few weeks of smooth operation, <strong>consider adding includeSubDomains and preload<\/strong> to HSTS for long-lived domains you fully control.<\/li>\n<\/ol>\n<p>We treat HTTP security headers as part of a broader hardening checklist together with firewall rules, secure cookies and application-level security. If you want a bigger picture of hosting-side protections to configure when launching a new website, check our <a href=\"https:\/\/www.dchost.com\/blog\/en\/yeni-acilan-web-siteleri-icin-hosting-guvenlik-check-listi-ilk-gunden-yapilmasi-gereken-20-ayar\/\">security checklist for new sites with 20 essential hosting settings<\/a>.<\/p>\n<h2><span id=\"How_We_See_Customers_Apply_This_on_dchostcom\">How We See Customers Apply This on dchost.com<\/span><\/h2>\n<p>Across shared hosting, VPS, dedicated servers and colocation environments, we see a similar pattern: once teams grasp how HSTS, CSP, X-Frame-Options and Referrer-Policy work, they begin treating headers as <strong>versioned configuration<\/strong> rather than one-off tweaks. On simpler shared hosting setups, that may mean a carefully maintained <code>.htaccess<\/code> snippet committed to their project repo. On VPS and dedicated servers, it usually becomes a part of Ansible playbooks or Nginx\/Apache include files, deployed consistently across staging and production.<\/p>\n<p>From our side as a hosting provider, the important part is that your platform does not get in the way. Whether you run a single corporate site, a WooCommerce store, or a fleet of custom apps, you should be able to define your security headers once and trust that your web server serves them reliably. Combined with modern TLS settings, DNS hardening and good backup discipline, these headers close many of the common gaps we still see on otherwise well-built sites.<\/p>\n<p>If you ever feel unsure where to start, you can begin with the conservative examples in this article, test them in a staging environment, and gradually evolve your policies as you gain more confidence and visibility.<\/p>\n<h2><span id=\"Next_Steps_Turn_Security_Headers_into_a_Habit\">Next Steps: Turn Security Headers into a Habit<\/span><\/h2>\n<p>HSTS, CSP, X-Frame-Options and Referrer-Policy are not magic bullets, but together they remove entire classes of attacks or at least make them significantly harder to exploit. The key is to treat them as <strong>living configuration<\/strong>: start with safer defaults, test carefully, monitor logs and reports, and iterate as your site and third-party integrations evolve. When you move to a new server, change a CDN, or redesign your front-end, reviewing your headers should be part of the release checklist, just like reviewing redirects or cache settings.<\/p>\n<p>If your current hosting environment makes it difficult to control headers at the server level, that can be a signal it is time to move to a more flexible setup where you own the web server configuration. At dchost.com, we see customers get the best results when security headers are managed alongside TLS, WAF rules and application configs, not as isolated one-off changes. Take the example configurations in this article, adapt them to your stack, and add them to your next deployment plan. In a few iterations, you will have a clean, repeatable security header setup that quietly protects every visitor, every day.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>When we harden customer websites at dchost.com, HTTP security headers are always among the first things we check. They are small pieces of text added to HTTP responses, but they dramatically change how browsers treat your site. With a few correctly configured headers, you reduce the impact of XSS attacks, prevent clickjacking, avoid leaking sensitive [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3168,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-3167","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3167","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=3167"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/3167\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/3168"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=3167"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=3167"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=3167"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}