Configuring HTTP Security Headers: ‘Armor’ for Nginx and Apache to Achieve A+ Standard

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Why is SSL Alone Not Enough?

Many people assume that as long as the green SSL padlock is visible, the website is 100% secure. In reality, SSL only encrypts the connection between the user and the server. It is completely powerless against hackers embedding your website in a malicious iframe or injecting third-party Javascript.

I personally spent a sleepless night dealing with a brute-force attack. After that lesson, I realized that security must be a multi-layered system. HTTP Security Headers are those ‘small but mighty’ layers of protection. They are instructions sent by the server to tell the browser: ‘Don’t run malicious scripts’ or ‘Only allow connections over HTTPS’.

Without these headers, your website is extremely vulnerable to Clickjacking or Cross-Site Scripting (XSS). According to statistics, XSS accounts for nearly 40% of web application attacks. Setting them up only takes 5 minutes, but the value provided is immense.

Installation and Preparation

Before starting the configuration, determine whether you are using Nginx or Apache. These are the two dominant web servers today.

With Nginx

Nginx handles headers efficiently via the ngx_http_headers_module. You only need sudo privileges to edit the configuration file at /etc/nginx/sites-available/.

With Apache

On Apache, make sure you have activated the headers module. If you forget this step, the server will immediately return a 500 error. Run the following command in your terminal:

sudo a2enmod headers
sudo systemctl restart apache2

6 Essential Security Headers You Need to Install Now

Below is the list of ‘bodyguards’ I always install for every project, from simple landing pages to complex e-commerce systems.

1. HTTP Strict Transport Security (HSTS)

This header forces the browser to use HTTPS only. Even if a user types http://, the browser automatically switches to https:// before sending the request. It completely eliminates downgrade attacks.

  • Nginx: add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
  • Apache: Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Pro tip: max-age=31536000 is equivalent to 1 year. Only add preload when you are certain your SSL is consistently stable.

2. X-Frame-Options

This header is the nemesis of Clickjacking. It instructs the browser: ‘Strictly forbid embedding this website in a stranger’s iframe’.

  • Nginx: add_header X-Frame-Options "SAMEORIGIN" always;
  • Apache: Header always set X-Frame-Options "SAMEORIGIN"

Using SAMEORIGIN allows you to still embed your own iframes on the same domain.

3. X-Content-Type-Options

Many browsers have a feature that ‘guesses’ the file format (MIME sniffing). Hackers can exploit this by uploading an image file containing malicious Javascript. The nosniff header forces the browser to adhere to the format declared by the server.

  • Nginx: add_header X-Content-Type-Options "nosniff" always;
  • Apache: Header always set X-Content-Type-Options "nosniff"

4. Referrer-Policy

When a user clicks a link from your site to another, the browser usually sends the original URL. This could expose sensitive information. I often use strict-origin-when-cross-origin to balance security and SEO data integrity.

  • Nginx: add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  • Apache: Header always set Referrer-Policy "strict-origin-when-cross-origin"

5. Permissions-Policy

This header helps you control access to hardware. If your blog is only for reading text, disable the Camera or Microphone to prevent covert exploitation.

# Nginx example to disable Camera and Mic
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

6. Content Security Policy (CSP) – ‘The Steel Shield’

CSP is the most powerful header but also the hardest to configure. It specifies which sources (domains) are allowed to load scripts, images, or CSS. A strict CSP can block 99% of XSS attacks.

Below is a basic yet secure CSP framework to get you started:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google-analytics.com; img-src 'self' data:; style-src 'self' 'unsafe-inline';" always;

Sample Configuration File for Nginx

For easy implementation, you can copy the following code into your Nginx server block:

server {
    listen 443 ssl;
    server_name itfromzero.com;

    # Security Headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
}

Verifying the Results

Once configured, how do you know if it’s correct? Use the following tools to ‘grade’ your setup:

  1. SecurityHeaders.com: Simply enter your domain, and the tool will scan and grade it. Your goal is an A or A+ rating.
  2. DevTools (F12): Open the Network tab, select any request, and check the Headers section. If you see the lines you just configured, you have succeeded.

Security is a never-ending journey. However, with 5 minutes spent configuring these headers, your website is significantly more secure than the majority of sites today. Don’t wait until the damage is done. Good luck with your configuration!

Share: