
In addition to https://ssl-config.mozilla.org/ when setting up your website, there is another wonderful free tool by Mozilla: https://developer.mozilla.org/en-US/observatory
Unlike the Mozilla configurator it’s not as succinct with helping you configure but it is very good nevertheless.
A nice analysis is https://vaibhav.co.uk/2025/03/08/implementing-secure-headers-using-mozilla-observatory/ by Vaibhav Jain.
So a leg up is to start here with this:
<VirtualHost *:443>
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), camera=(), microphone=()"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';"
</IfModule>
</VirtualHost>
Like the excellent (and free) Qualys SSL Test site it gives you a grade which is a useful metric.
Here is a python program to allow you to run it on the command line:
#!/usr/bin/env python3
import requests
import time
import argparse
def analyze_site(hostname):
url = "https://observatory-api.mdn.mozilla.net/api/v2/scan"
params = {
"host": hostname,
"rescan": True
}
response = requests.post(url, params=params)
try:
response.raise_for_status() # Check if the request was successful
return response.json() # Attempt to parse the JSON response
except requests.exceptions.HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
except requests.exceptions.RequestException as req_err:
print(f"Request error occurred: {req_err}")
except ValueError as json_err:
print(f"JSON decode error occurred: {json_err}")
return None
def get_scan_results(scan_id):
url = f"https://observatory-api.mdn.mozilla.net/api/v2/results?id={scan_id}"
print(f"Fetching results from URL: {url}") # Debugging information
response = requests.get(url)
try:
response.raise_for_status() # Check if the request was successful
return response.json() # Attempt to parse the JSON response
except requests.exceptions.HTTPError as http_err:
print(f"HTTP error occurred: {http_err}")
except requests.exceptions.RequestException as req_err:
print(f"Request error occurred: {req_err}")
except ValueError as json_err:
print(f"JSON decode error occurred: {json_err}")
return None
parser = argparse.ArgumentParser(description="Analyze a website using Mozilla HTTP Observatory API v2")
parser.add_argument("hostname", help="The hostname of the site to analyze")
args = parser.parse_args()
hostname=args.hostname
analysis = analyze_site(hostname)
if analysis and "grade" in analysis:
if analysis['error'] == None:
print("Scan Results:", analysis['grade'])
print("Scan Results:", analysis['details_url'])
else:
print("None")
So here is how you run it:
$ ./observatory.py www.mozilla.org
Scan Results: B+
Scan Results: https://developer.mozilla.org/en-US/observatory/analyze?host=www.mozilla.org