Bird
Raised Fist0
Nginxdevops~10 mins

HSTS header in Nginx - Step-by-Step Execution

Choose your learning style10 modes available
Process Flow - HSTS header
Client makes HTTPS request
↓
Server responds with HSTS header
↓
Client stores HSTS policy
↓
Future requests forced to HTTPS
↓
No HTTP fallback allowed
↓
Secure connection enforced
The server sends the HSTS header to tell browsers to always use HTTPS for future requests, improving security by preventing HTTP fallback.
Execution Sample
Nginx
server {
    listen 443 ssl;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
This nginx config adds the HSTS header to HTTPS responses, telling browsers to enforce HTTPS for 1 year including subdomains.
Process Table
StepActionHeader SentClient BehaviorResult
1Client sends HTTPS requestNoNo HSTS policy yetServer processes request
2Server responds with HSTS headerStrict-Transport-Security: max-age=31536000; includeSubDomainsClient stores HSTS policyClient remembers to use HTTPS
3Client sends HTTP request next timeNoClient upgrades to HTTPS automaticallyConnection is secure
4Client sends HTTPS request againNo new header neededUses HTTPS directlySecure connection maintained
5Client tries HTTP after max-age expiresNoHSTS policy expired, may allow HTTPPotential insecure connection
💡 HSTS header instructs client to enforce HTTPS until max-age expires
Status Tracker
VariableStartAfter Step 2After Step 3After Step 4After Step 5
HSTS Policy StoredFalseTrueTrueTrueFalse (expired)
Connection ProtocolHTTPSHTTPSUpgraded to HTTPSHTTPSHTTP possible
Key Moments - 2 Insights
Why does the client upgrade HTTP requests to HTTPS after receiving the HSTS header?
Because the client stores the HSTS policy at Step 2 (see execution_table row 2), it automatically upgrades any HTTP requests to HTTPS to follow the security rule.
What happens if the max-age time expires?
After max-age expires (Step 5), the client no longer enforces HTTPS strictly and may allow HTTP connections again, as shown by the HSTS Policy Stored variable becoming False.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution table, at which step does the client store the HSTS policy?
AStep 2
BStep 1
CStep 3
DStep 4
💡 Hint
Check the 'Client Behavior' column in execution_table row 2
According to variable_tracker, what is the value of 'Connection Protocol' after Step 3?
AHTTP
BHTTPS
CUpgraded to HTTPS
DNo connection
💡 Hint
Look at the 'Connection Protocol' row under 'After Step 3' in variable_tracker
If the server did not send the HSTS header at Step 2, what would happen to the client behavior?
AClient would store HSTS policy anyway
BClient would not enforce HTTPS automatically
CClient would upgrade HTTP requests to HTTPS
DClient would block all HTTP requests
💡 Hint
Refer to execution_table row 2 where header is sent and client stores policy
Concept Snapshot
HSTS header in nginx:
add_header Strict-Transport-Security "max-age=SECONDS; includeSubDomains" always;
Sends policy to browsers to enforce HTTPS
Browsers upgrade HTTP to HTTPS automatically
max-age defines how long policy lasts
Improves security by preventing downgrade attacks
Full Transcript
HSTS header is a security feature where the server tells browsers to always use HTTPS for future requests. In nginx, you add it with add_header Strict-Transport-Security and set max-age for how long the browser should remember this. When a client first connects over HTTPS, the server sends this header. The client stores the policy and upgrades any HTTP requests to HTTPS automatically. This prevents insecure connections and downgrade attacks. After the max-age expires, the client may allow HTTP again. This trace shows each step from request to client enforcing HTTPS.

Practice

(1/5)
1. What is the main purpose of the Strict-Transport-Security (HSTS) header in nginx?
easy
A. To force browsers to use HTTPS instead of HTTP for the site
B. To redirect HTTP requests to a different domain
C. To enable caching of static files in the browser
D. To compress responses sent to the client

Solution

  1. Step 1: Understand HSTS header purpose

    The HSTS header tells browsers to only use HTTPS for the site, improving security.
  2. Step 2: Compare options with HSTS function

    Only To force browsers to use HTTPS instead of HTTP for the site matches this purpose; others describe unrelated features.
  3. Final Answer:

    To force browsers to use HTTPS instead of HTTP for the site -> Option A
  4. Quick Check:

    HSTS = Force HTTPS [OK]
Hint: HSTS means browsers must use HTTPS always [OK]
Common Mistakes:
  • Confusing HSTS with redirects
  • Thinking HSTS controls caching
  • Assuming HSTS compresses data
2. Which of the following is the correct nginx syntax to add an HSTS header that lasts for 1 year and applies to all subdomains?
easy
A. add_header Strict-Transport-Security max-age=31536000 includeSubDomains always;
B. add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
C. add_header Strict-Transport-Security "max-age=31536000 includeSubDomains";
D. add_header Strict-Transport-Security max-age=31536000; includeSubDomains always;

Solution

  1. Step 1: Check correct syntax for add_header

    The header value must be a quoted string with directives separated by semicolons, and 'always;' ensures it is added on all responses.
  2. Step 2: Validate option formatting

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; correctly quotes the value and uses semicolon between directives with 'always;'. Others miss quotes or semicolons or misplace 'always'.
  3. Final Answer:

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; -> Option B
  4. Quick Check:

    Quotes + semicolon + always = add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; [OK]
Hint: Use quotes and semicolons inside add_header value [OK]
Common Mistakes:
  • Missing quotes around header value
  • Forgetting semicolon between directives
  • Placing 'always' inside quotes
3. Given this nginx config snippet:
add_header Strict-Transport-Security "max-age=86400; includeSubDomains" always;

What is the effect on browsers visiting the site?
medium
A. Browsers will enforce HTTPS for 1 day on the site and all subdomains
B. Browsers will enforce HTTPS for 1 year on the site only
C. Browsers will ignore the header because max-age is too low
D. Browsers will enforce HTTPS for 1 day on the site only

Solution

  1. Step 1: Interpret max-age and includeSubDomains

    max-age=86400 means 86400 seconds = 1 day. includeSubDomains applies to all subdomains.
  2. Step 2: Understand browser behavior

    Browsers will enforce HTTPS for 1 day on the site and all its subdomains as per header.
  3. Final Answer:

    Browsers will enforce HTTPS for 1 day on the site and all subdomains -> Option A
  4. Quick Check:

    86400 seconds = 1 day + includeSubDomains = Browsers will enforce HTTPS for 1 day on the site and all subdomains [OK]
Hint: max-age in seconds; 86400 = 1 day [OK]
Common Mistakes:
  • Confusing seconds with days
  • Ignoring includeSubDomains effect
  • Assuming max-age too low disables HSTS
4. You added this line in nginx:
add_header Strict-Transport-Security max-age=31536000 includeSubDomains always;

Why is the HSTS header not sent to clients?
medium
A. includeSubDomains is not a valid directive
B. The 'always' directive must be inside the quotes
C. max-age value is too large and rejected by nginx
D. The header value is missing quotes, causing syntax error

Solution

  1. Step 1: Check syntax for add_header directive

    The header value must be enclosed in quotes. Missing quotes cause nginx to ignore the header.
  2. Step 2: Validate other parts

    'always' must be outside quotes, max-age=31536000 is valid, includeSubDomains is valid directive.
  3. Final Answer:

    The header value is missing quotes, causing syntax error -> Option D
  4. Quick Check:

    Quotes missing = header not sent [OK]
Hint: Always quote header values in add_header [OK]
Common Mistakes:
  • Placing 'always' inside quotes
  • Not quoting header value
  • Misunderstanding valid directives
5. You want to preload your site in browsers' HSTS preload list. Which nginx header configuration is correct to achieve this for 6 months including subdomains?
hard
A. add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
B. add_header Strict-Transport-Security "max-age=15768000; preload" always;
C. add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
D. add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

Solution

  1. Step 1: Calculate max-age for 6 months

    6 months ≈ 15768000 seconds (6 * 30 * 24 * 3600).
  2. Step 2: Include required directives for preload

    Preload requires max-age, includeSubDomains, and preload directive all present.
  3. Step 3: Verify syntax correctness

    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always; correctly quotes the value, uses semicolons, includes all directives, and uses 'always;'.
  4. Final Answer:

    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always; -> Option C
  5. Quick Check:

    Preload + includeSubDomains + 6 months = add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always; [OK]
Hint: Preload needs max-age, includeSubDomains, preload keywords [OK]
Common Mistakes:
  • Using wrong max-age for 6 months
  • Omitting preload directive
  • Not quoting header value
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard