Favicon Nginx Configuration Guide
Complete Nginx server configuration for optimal favicon delivery: cache headers, MIME types, compression, and performance optimization.
Nginx Favicon Optimization
- Cache Control: Long expiration headers
- Compression: Gzip/Brotli enabled
- MIME Types: Properly configured
- Performance: Optimized delivery
- Security: Proper headers
- HTTP/2: Enabled for parallel loading
Complete Nginx Favicon Configuration
Full nginx.conf or site config
# Nginx Favicon Configuration
# Add to your nginx.conf or site-specific config file
server {
listen 80;
listen [::]:80;
server_name yourdomain.com;
# Root directory
root /var/www/html;
index index.html;
# ============================================
# FAVICON CONFIGURATION
# ============================================
# 1. Favicon.ico (legacy support)
location = /favicon.ico {
alias /var/www/html/favicon.ico;
access_log off;
log_not_found off;
expires 1y;
add_header Cache-Control "public, immutable";
}
# 2. All favicon files in root
location ~* ^/(favicon-16x16\.png|favicon-32x32\.png|favicon-96x96\.png|favicon-512x512\.png|apple-touch-icon\.png|android-chrome-.*\.png|site\.webmanifest|browserconfig\.xml)$ {
access_log off;
expires 1y;
add_header Cache-Control "public, immutable";
}
# 3. Dedicated favicons folder (optional)
location /favicons/ {
access_log off;
expires 1y;
add_header Cache-Control "public, immutable";
}
# 4. SVG favicons
location ~* \.svg$ {
add_header Content-Type image/svg+xml;
access_log off;
expires 1y;
add_header Cache-Control "public, immutable";
}
# ============================================
# COMPRESSION
# ============================================
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 256;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
image/svg+xml
image/x-icon
application/manifest+json
application/xml;
# Brotli compression (if module installed)
# brotli on;
# brotli_comp_level 6;
# brotli_types
# image/svg+xml
# image/x-icon
# application/manifest+json;
# ============================================
# MIME TYPES
# ============================================
# Ensure correct MIME types
types {
image/x-icon ico;
image/png png;
image/svg+xml svg svgz;
application/manifest+json webmanifest;
application/xml xml;
}
# ============================================
# SECURITY HEADERS
# ============================================
# Add security headers for favicon files
location ~* \.(ico|png|svg|webmanifest|xml)$ {
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
}
# ============================================
# ERROR HANDLING
# ============================================
# Don't log 404 for missing favicons
location ~ ^/(apple-touch-icon|android-chrome|mstile).*\.(png|ico)$ {
access_log off;
log_not_found off;
return 404;
}
# Rest of your configuration...
location / {
try_files $uri $uri/ =404;
}
}Minimal Configuration (Quick Setup)
Essential Configuration Only
If you just need the basics, add this to your server block:
# Minimal favicon configuration
location ~* \.(ico|png|svg|webmanifest)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Don't log favicon 404s
location = /favicon.ico {
log_not_found off;
access_log off;
}Cache Headers Explained
| Header | Value | Purpose |
|---|---|---|
expires 1y; |
1 year | Sets Expires header (HTTP/1.0 compatibility) |
Cache-Control: public |
public | Allow caching by browsers and CDNs |
Cache-Control: immutable |
immutable | File never changes, skip revalidation |
max-age=31536000 |
1 year (seconds) | Cache duration in seconds |
Best Practice: Use
expires 1y + Cache-Control: "public, immutable" for favicons. They rarely change, and you can use versioned URLs (favicon.ico?v=2) when updating.
MIME Type Configuration
Correct MIME Types for Favicons
Add to /etc/nginx/mime.types or include in server block:
types {
# Favicon formats
image/x-icon ico;
image/png png;
image/svg+xml svg svgz;
# Manifest files
application/manifest+json webmanifest;
application/xml xml;
# Windows tiles
application/xml browserconfig.xml;
}| File | MIME Type | Why Important |
|---|---|---|
| *.ico | image/x-icon | Standard ICO format |
| *.png | image/png | PNG favicons |
| *.svg | image/svg+xml | Scalable vector icons |
| *.webmanifest | application/manifest+json | PWA manifest |
| browserconfig.xml | application/xml | Windows tile config |
Compression Configuration
Gzip Compression
Standard compression (always available):
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
image/svg+xml
image/x-icon
application/manifest+json;Savings: 60-80% for SVG, 40-60% for manifest.json
Brotli Compression
Better compression (requires module):
brotli on;
brotli_comp_level 6;
brotli_types
image/svg+xml
image/x-icon
application/manifest+json;Savings: 15-20% better than gzip. Install: nginx-module-brotli
Note: PNG and ICO files are already compressed. Don't compress them (wastes CPU). Only compress SVG and JSON files.
HTTP/2 Configuration
Enable HTTP/2 for Faster Favicon Loading
HTTP/2 allows parallel loading of multiple favicons:
server {
# Enable HTTP/2
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name yourdomain.com;
# SSL certificates required for HTTP/2
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# SSL optimization
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
# Rest of config...
}Benefits:
- Parallel loading of multiple favicons
- Reduced latency (multiplexing)
- Header compression
- Better mobile performance
Requirements:
- Nginx 1.9.5+
- SSL/TLS certificate (Let's Encrypt free)
- Modern browser (95%+ support)
Security Headers
Security Configuration for Favicons
# Security headers for favicon files
location ~* \.(ico|png|svg|webmanifest|xml)$ {
# Prevent MIME type sniffing
add_header X-Content-Type-Options "nosniff" always;
# Prevent framing (clickjacking protection)
add_header X-Frame-Options "SAMEORIGIN" always;
# CORS (if serving favicons from CDN)
# add_header Access-Control-Allow-Origin "*" always;
# Cache headers
expires 1y;
add_header Cache-Control "public, immutable";
}CORS Note: Only add
Access-Control-Allow-Origin if serving favicons from a different domain (CDN). For same-origin, it's not needed.
Testing Your Configuration
1. Test Nginx Configuration
# Test config for syntax errors
sudo nginx -t
# Reload Nginx if test passes
sudo systemctl reload nginx
# Or restart if needed
sudo systemctl restart nginx2. Test Headers with curl
# Check cache headers
curl -I https://yourdomain.com/favicon.ico
# Check compression
curl -H "Accept-Encoding: gzip" -I https://yourdomain.com/favicon.svg
# Expected response:
# Cache-Control: public, immutable, max-age=31536000
# Content-Encoding: gzip (for SVG)
# X-Content-Type-Options: nosniff3. Browser DevTools Check
- Open DevTools (F12) ? Network tab
- Reload your page
- Find favicon.ico in network list
- Check Headers tab for Cache-Control
- Second reload should show "from cache"
Common Nginx Favicon Issues
Causes:
- File not in correct location
- Wrong root directory configured
- Permissions issue
# Check file exists
ls -la /var/www/html/favicon.ico
# Fix permissions
sudo chmod 644 /var/www/html/favicon.ico
sudo chown www-data:www-data /var/www/html/favicon.icoProblem: Cache-Control headers not appearing.
Solution: Make sure add_header is in correct location block and use
Solution: Make sure add_header is in correct location block and use
always flag:
add_header Cache-Control "public, immutable" always;Check:
- gzip module enabled:
nginx -V | grep gzip - File size > gzip_min_length (default 20 bytes)
- MIME type listed in gzip_types
- Browser sends Accept-Encoding: gzip
Production Deployment Checklist
Configuration:
Testing:
Need Favicons for Your Nginx Server?
Generate optimized favicon packages ready for Nginx deployment
Generate Favicons