Generate Now

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 nginx

2. 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: nosniff

3. Browser DevTools Check

  1. Open DevTools (F12) ? Network tab
  2. Reload your page
  3. Find favicon.ico in network list
  4. Check Headers tab for Cache-Control
  5. Second reload should show "from cache"

Common Nginx Favicon Issues

Causes:
  • File not in correct location
  • Wrong root directory configured
  • Permissions issue
Solutions:
# 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.ico

Problem: Cache-Control headers not appearing.
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

Related Articles

An unhandled error has occurred. Reload 🗙