View contents
HTTPS Implementation Guide: Complete Security Configuration
Introduction
Implementing HTTPS correctly goes beyond simply installing an SSL certificate. A proper implementation requires understanding TLS configuration, security headers, certificate management, and ongoing maintenance. This guide provides a comprehensive approach to securing your website with HTTPS following industry best practices.
According to Let’s Encrypt and the Internet Security Research Group (ISRG), proper Transport Layer Security implementation is critical for protecting data in transit and maintaining user trust.
TLS Fundamentals
TLS Version Selection
TLS (Transport Layer Security) has evolved through several versions. Not all versions are considered secure today:
| Version | Status | Recommendation |
|---|---|---|
| SSL 2.0 | Deprecated | Do not use - Known vulnerabilities |
| SSL 3.0 | Deprecated | Do not use - POODLE vulnerability |
| TLS 1.0 | Legacy | Avoid - Deprecated by major browsers |
| TLS 1.1 | Legacy | Avoid - Deprecated by major browsers |
| TLS 1.2 | Current | Acceptable - Still widely supported |
| TLS 1.3 | Current | Preferred - Latest and most secure |
Recommended configuration: Support TLS 1.2 and TLS 1.3 only.
TLS Handshake Process
Understanding the TLS handshake helps diagnose connection issues:
1. Client Hello
├── Client sends supported TLS versions
├── Supported cipher suites
└── Random number for key generation
2. Server Hello
├── Server selects TLS version
├── Selects cipher suite
└── Sends certificate
3. Certificate Verification
├── Client verifies certificate chain
├── Checks expiration date
└── Validates domain match
4. Key Exchange
├── Session keys generated
└── Encrypted channel established
5. Secure Communication
└── All data encrypted with session keys
Certificate Types and Selection
Domain Validation (DV)
- Verification: Domain ownership only
- Issuance time: Minutes to hours
- Cost: Free (Let’s Encrypt) to low cost
- Use case: Blogs, personal sites, small business sites
- Visual indicator: Padlock icon
Organization Validation (OV)
- Verification: Domain ownership + organization identity
- Issuance time: 1-3 days
- Cost: Moderate
- Use case: Business websites, corporate sites
- Visual indicator: Padlock icon (organization name in certificate details)
Extended Validation (EV)
- Verification: Extensive legal and physical verification
- Issuance time: 1-2 weeks
- Cost: Higher
- Use case: E-commerce, banking, high-trust sites
- Visual indicator: Padlock icon (historically showed green bar, now organization in certificate)
Wildcard Certificates
Wildcard certificates secure a domain and all its subdomains:
*.example.com covers:
├── www.example.com
├── blog.example.com
├── shop.example.com
└── api.example.com
Does NOT cover:
├── example.com (root domain - needs separate or SAN entry)
└── sub.blog.example.com (multi-level subdomains)
Multi-Domain (SAN) Certificates
Subject Alternative Name (SAN) certificates cover multiple specific domains:
Single certificate covers:
├── example.com
├── www.example.com
├── example.net
└── shop.example.org
Server Configuration
Apache Configuration
Complete Apache HTTPS configuration:
# Enable SSL module
LoadModule ssl_module modules/mod_ssl.so
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
# SSL Certificate
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/chain.crt
# TLS Protocol Versions
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
# Cipher Suite Configuration
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder on
# HSTS Header
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Additional Security Headers
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
</VirtualHost>
# HTTP to HTTPS Redirect
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
Nginx Configuration
Complete Nginx HTTPS configuration:
# HTTP redirect
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
# HTTPS server
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
# SSL Certificate
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# TLS Protocol Versions
ssl_protocols TLSv1.2 TLSv1.3;
# Cipher Suite Configuration
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
# SSL Session Caching
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/chain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
root /var/www/html;
index index.html;
}
HTTP Strict Transport Security (HSTS)
HSTS Deep Dive
HSTS prevents protocol downgrade attacks and cookie hijacking by instructing browsers to only use HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Directive breakdown:
| Directive | Value | Purpose |
|---|---|---|
| max-age | 31536000 (1 year) | How long browsers remember HTTPS-only |
| includeSubDomains | (flag) | Apply to all subdomains |
| preload | (flag) | Allow browser preload list inclusion |
HSTS Implementation Strategy
Implement HSTS gradually to avoid lockouts:
Week 1: max-age=300 (5 minutes)
└── Test for issues
Week 2: max-age=86400 (1 day)
└── Verify no problems
Week 3: max-age=604800 (1 week)
└── Monitor for issues
Week 4+: max-age=31536000 (1 year)
└── Add includeSubDomains if applicable
Final: Add preload directive
└── Submit to browser preload lists
HSTS Preload Submission
Requirements for HSTS preload list inclusion:
- Valid certificate: Must have a valid, trusted certificate
- HTTPS redirect: All HTTP must redirect to HTTPS
- HSTS header: Must include
max-ageof at least 1 year (31536000) - includeSubDomains: Must be present
- preload: Directive must be present
- All subdomains: All subdomains must support HTTPS
Submit at: hstspreload.org
Warning: Preload removal takes months. Only submit when fully committed to HTTPS.
Certificate Management
Let’s Encrypt with Certbot
Automated certificate management with Let’s Encrypt:
# Install Certbot (Ubuntu/Debian)
sudo apt update
sudo apt install certbot python3-certbot-nginx
# Obtain certificate for Nginx
sudo certbot --nginx -d example.com -d www.example.com
# Obtain certificate for Apache
sudo certbot --apache -d example.com -d www.example.com
# Certificate renewal (automatic via cron)
sudo certbot renew
# Test renewal
sudo certbot renew --dry-run
Certificate Monitoring
Key metrics to monitor:
Certificate Health Checks:
├── Expiration date (alert at 30, 14, 7 days)
├── Certificate chain validity
├── Domain name match
├── Key strength (minimum 2048-bit RSA or 256-bit ECC)
└── Revocation status (OCSP/CRL)
Monitoring Tools:
├── SSL Labs Server Test
├── certbot certificates (local check)
├── OpenSSL commands
└── Certificate monitoring services
OpenSSL Verification Commands
# Check certificate expiration
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates
# View full certificate details
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -text
# Verify certificate chain
openssl s_client -connect example.com:443 -showcerts
# Check specific TLS version support
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
Mixed Content Resolution
Identifying Mixed Content
Mixed content occurs when HTTPS pages load HTTP resources:
Active mixed content (blocked by browsers):
- Scripts (
<script src="http://...">) - Stylesheets (
<link href="http://...">) - iframes (
<iframe src="http://...">) - XMLHttpRequest/Fetch requests
Passive mixed content (warning, may be loaded):
- Images (
<img src="http://...">) - Audio (
<audio src="http://...">) - Video (
<video src="http://...">)
Finding Mixed Content
Browser Developer Tools method:
1. Open Chrome DevTools (F12)
2. Go to Console tab
3. Look for "Mixed Content" warnings
4. Network tab shows blocked resources
Or use Security tab:
1. DevTools > Security tab
2. View "Mixed Content" section
3. See list of insecure resources
Fixing Mixed Content
Update hardcoded URLs:
<!-- Before -->
<img src="http://example.com/image.jpg">
<script src="http://cdn.example.com/app.js"></script>
<link href="http://fonts.googleapis.com/css?family=Open+Sans">
<!-- After -->
<img src="https://example.com/image.jpg">
<script src="https://cdn.example.com/app.js"></script>
<link href="https://fonts.googleapis.com/css?family=Open+Sans">
Protocol-relative URLs (use cautiously):
<img src="//example.com/image.jpg">
Content Security Policy for detection:
Content-Security-Policy-Report-Only: default-src https:; report-uri /csp-report
Security Headers Beyond HTTPS
Content Security Policy (CSP)
Control which resources can be loaded:
Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.googleapis.com
Additional Security Headers
# Prevent MIME type sniffing
X-Content-Type-Options: nosniff
# Clickjacking protection
X-Frame-Options: SAMEORIGIN
# XSS filter (legacy browsers)
X-XSS-Protection: 1; mode=block
# Referrer policy
Referrer-Policy: strict-origin-when-cross-origin
# Permissions policy
Permissions-Policy: geolocation=(), microphone=(), camera=()
Performance Optimization
TLS Session Resumption
Reduce handshake overhead with session caching:
# Nginx
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off; # Disable for perfect forward secrecy
OCSP Stapling
Improve certificate verification performance:
# Nginx
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/chain.crt;
resolver 8.8.8.8 8.8.4.4 valid=300s;
HTTP/2 Benefits
HTTP/2 requires HTTPS and provides:
- Multiplexing: Multiple requests over single connection
- Header compression: Reduced overhead
- Server push: Proactive resource delivery
- Binary protocol: More efficient parsing
Enable HTTP/2:
# Nginx
listen 443 ssl http2;
# Apache
Protocols h2 http/1.1
Migration Checklist
Pre-Migration
□ Audit all internal links and resources
□ Identify third-party integrations requiring updates
□ Obtain and test SSL certificate
□ Configure staging environment with HTTPS
□ Test all functionality on staging
□ Plan redirect implementation
□ Notify third-party services of URL change
Migration
□ Install SSL certificate on production
□ Implement HTTP to HTTPS redirects
□ Update all internal links to HTTPS
□ Update canonical URLs
□ Update XML sitemaps
□ Update robots.txt references
□ Update structured data URLs
□ Test for mixed content issues
Post-Migration
□ Submit new sitemaps to search engines
□ Add HTTPS property in Google Search Console
□ Monitor for crawl errors
□ Check analytics for tracking issues
□ Verify third-party integrations working
□ Implement HSTS header (gradually)
□ Monitor certificate expiration
□ Schedule regular security audits
Troubleshooting Common Issues
Certificate Chain Errors
Problem: “Certificate chain incomplete” or “Unknown authority”
Solution: Ensure intermediate certificates are included:
# Correct certificate chain order
cat domain.crt intermediate.crt > full_chain.crt
Mixed Content Warnings
Problem: Page shows “Not fully secure”
Solution:
- Use browser DevTools to identify HTTP resources
- Update all resources to HTTPS
- Use CSP report-only mode to find issues
HSTS Issues
Problem: Cannot access site after enabling HSTS with error
Solution:
- Clear browser HSTS cache
- Chrome: chrome://net-internals/#hsts
- Start with short max-age values
Redirect Loops
Problem: “Too many redirects”
Solution:
- Check for conflicting redirects in server config and application
- Ensure redirect rules don’t create loops
- Verify CDN redirect settings
How to Verify with UXR SEO Analyzer
The UXR SEO Analyzer extension provides comprehensive HTTPS verification:
- Install the UXR SEO Analyzer extension in Chrome
- Navigate to any page on your website
- Open the extension
- Go to the “Basic SEO” tab
- Check the “HTTPS” evaluator
What the extension checks:
- Protocol (HTTPS vs HTTP)
- Certificate validity
- Mixed content presence
- Redirect implementation
- Security header presence
Related Articles
- HTTPS Explained - Basic HTTPS concepts and importance
- Canonical URLs Explained - URL canonicalization after migration
- XML Sitemaps: Complete Guide - Updating sitemaps for HTTPS
Additional Resources
- Let’s Encrypt Documentation - Free, automated SSL/TLS certificates
- ISRG Certificate Policy v3.1 - Certificate standards and requirements
- SSL Labs Server Test - Test your server’s SSL configuration
- web.dev Security Guidance - Google’s web development best practices
Note: This article is part of our SEO analysis series. Explore all articles in the Basic SEO Hub.
Sources: Let’s Encrypt Documentation (Internet Security Research Group Certificate Policy v3.1)