Repository navigation
Separate HTTP/HTTPS server blocks needed for HSTS and proper redirect chains #62
Copy link
Copy link
Open
Description
Issue: Separate HTTP/HTTPS server blocks needed for HSTS and proper redirect chains
Current Behavior
The current vhost template creates combined server blocks listening on both port 80 and 443, using if ($scheme != "https") for HTTP→HTTPS redirects. This causes two issues:
- NCSC/Internet.nl compliance tests fail for HTTP→HTTPS redirect detection
- HSTS headers cannot be set reliably on the first contact (before any redirect)
Current Template Structure (simplified)
server {
listen 80;
listen [::]:80;
listen 443 ssl;
# ... SSL config
server_name www.example.com;
return 301 https://example.com $request_uri; # Redirects to different domain
}
server {
listen 80;
listen [::]:80;
listen 443 ssl;
# ... SSL config
server_name example.com;
if ($scheme != "https") {
rewrite ^ https://$host$request_uri permanent; # Same-block HTTPS redirect
}
# ... content
}Expected Behavior
Per NCSC-NL guideline U/WA.05 and Internet.nl tests:
- Strict separation: One server block for HTTP (port 80 only), separate blocks for HTTPS (port 443 only)
- HSTS on every response, including redirect responses
- Redirect chain: HTTP domain → HTTPS same domain → HTTPS target domain (if canonicalization needed)
Proposed Template Structure
# === HTTP: All domains → HTTPS (same domain) ===
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com alias1.com www.alias1.com;
return 301 https://$host$request_uri;
}
# === HTTPS: www.example.com → example.com (canonicalization) ===
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# ... SSL config
server_name www.example.com;
add_header Strict-Transport-Security "max-age=300; includeSubDomains" always;
return 301 https://example.com$request_uri;
}
# === HTTPS: alias1.com → example.com (domain consolidation) ===
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# ... SSL config
server_name alias1.com www.alias1.com;
add_header Strict-Transport-Security "max-age=300; includeSubDomains" always;
return 301 https://example.com$request_uri;
}
# === HTTPS: Main host (content) ===
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
# ... SSL config
server_name example.com;
add_header Strict-Transport-Security "max-age=300; includeSubDomains" always;
# ... root, logs, locations
}Template Variables Needed
| Variable | Purpose |
|---|---|
{{server_name_main}} |
Primary domain (content server) |
{{server_name_redirects}} |
List of domains that redirect to main (www, aliases) |
{{hsts_max_age}} |
HSTS max-age value (default: 300, stages: 604800, 2592000, 31536000) |
{{hsts_include_subdomains}} |
includeSubDomains directive (optional) |
Use Cases
- SEO canonicalization:
www.→ non-www or vice versa - Domain consolidation: Multiple TLDs (.com, .de) → primary domain
- HSTS preload readiness: Proper header placement for hstspreload.org
References
- Internet.nl test: https://internet.nl/site/example.com/
- NCSC-NL Web Application Guidelines (U/WA.05)
- RFC 6797 (HTTP Strict Transport Security)
Environment
- CloudPanel version: 2.x
- Web server: Nginx
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity