Server configuration

NGINX and Apache config snippets

Tested snippets for the changes almost every site needs.

6 snippets for NGINX and Apache, plus a checklist

Redirect HTTP to HTTPS

Send every plain-HTTP request to HTTPS with a permanent (301) redirect. Replace example.com with your domain.

NGINX, in the site's config:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

Apache, in .htaccess (mod_rewrite enabled):

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Notes

  • Use 301 for permanent moves
  • Install the SSL certificate first
  • Check that the redirect does not loop

Redirect www to the bare domain

Pick one address for your site, so search engines do not see two copies of every page.

NGINX:

server {
    listen 443 ssl;
    server_name www.example.com;
    # ssl_certificate and ssl_certificate_key lines here
    return 301 https://example.com$request_uri;
}

Apache, in .htaccess:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,R=301]

Notes

  • One canonical address
  • The certificate must cover www too
  • Swap the rules to force www instead

Compress responses

Compressing text responses makes pages smaller and faster to load.

NGINX, in the http or server block:

gzip on;
gzip_min_length 1024;
gzip_types text/css application/javascript application/json image/svg+xml;

Apache, in .htaccess (mod_deflate enabled):

AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json image/svg+xml

Notes

  • Compress text, not images
  • NGINX compresses text/html by default
  • Skip very small files

Cache static files

Tell browsers to keep images, CSS and scripts, so repeat visits load faster.

NGINX, in the server block:

location ~* \.(css|js|png|jpg|jpeg|gif|svg|webp|woff2)$ {
    expires 30d;
    add_header Cache-Control "public";
}

Apache, in .htaccess (mod_expires enabled):

ExpiresActive On
ExpiresByType text/css "access plus 30 days"
ExpiresByType application/javascript "access plus 30 days"
ExpiresByType image/webp "access plus 30 days"

Notes

  • Cache files whose names change when they change
  • Do not cache HTML for long
  • 30 days is a safe start

Add security headers

These headers stop common browser attacks, such as clickjacking and content sniffing.

NGINX, in the server block:

add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Apache, in .htaccess (mod_headers enabled):

Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

Notes

  • Safe defaults for most sites
  • Add a Content-Security-Policy once you know your sources
  • Check headers in the browser's dev tools

Test and reload

Check the syntax before you reload, so a typo does not take the site down. On a server you manage:

sudo nginx -t
sudo systemctl reload nginx

sudo apachectl configtest
sudo systemctl reload apache2

On Debian and Ubuntu the Apache service is apache2; on other systems it is often httpd. A .htaccess change applies on the next request, with no reload.

Notes

  • Test before every reload
  • Reload, do not restart
  • Keep a copy of the working config

Checklist

Editing server config: do and avoid.

Do

  • Back up the file first

    Copy the working config before you change it.

  • Test the syntax

    Run nginx -t or apachectl configtest.

  • Try changes on staging

    Then copy them to the live server.

  • Comment your rules

    Say why a rule exists, for the next person.

Avoid

  • Editing the live server blind

    One typo can stop every site on it.

  • Restarting when a reload will do

    A reload keeps connections open.

  • Copying snippets you do not understand

    Know what each line does before you use it.

  • Using IfModule-free rules without the module

    Apache returns an error if the module is not enabled.

FAQ

Server config questions

Where do I put NGINX snippets?

In your site's server block, usually a file under /etc/nginx/sites-available/ or /etc/nginx/conf.d/. Settings such as gzip can also go in the http block of nginx.conf.

Can I use these on shared hosting?

Only the Apache .htaccess rules, and only where your host runs Apache and allows them. Editing NGINX or the main Apache config needs a server you control, such as a VPS.

What is the difference between a 301 and a 302 redirect?

A 301 is permanent, and search engines move the old page's ranking to the new address. A 302 is temporary.

My site shows an error after a .htaccess change. Why?

Usually a typo or a directive for a module that is not enabled. Undo the change, then add it back line by line.

Do I need a VPS to edit server config?

For NGINX or the main Apache config, yes. A VPS or a Droplet gives you root access.

Want full control of your web server?

A VPS with root access, billed by the hour.