0

When I setup a website with ssl, I almost always have this boilerplate nginx config (instructions in comments):

# Redirect both (http/https) non www. to www.
server {
  listen 80;
  listen               443 ssl;
  ssl_certificate      /etc/ssl/certs/www.example.com.pem;
  ssl_certificate_key  /etc/ssl/private/www.example.com.key;

  server_name example.com;

  return 301 $scheme://www.example.com$request_uri;
}

# Redirect www. http traffic to www. https
server {
  listen      80;
  server_name www.example.com;
  return 301  https://$host$request_uri;
}

# Serve www. website over https
server {
  listen               443 ssl;
  ssl_certificate      /etc/ssl/certs/www.example.com.pem;
  ssl_certificate_key  /etc/ssl/private/www.example.com.key;

  server_name     www.example.com;
  root            /home/example/apps/site;

  server_tokens off;

  index index.php index.html index.htm;

  location / {
    try_files $uri $uri/ =404;
  }

  # ...
}

Anybody has suggestion make this simpler and remove some duplication?

3
  • 1
    That is the simpler solution! Oct 17 '14 at 13:56
  • 1
    Still i do not see the point of your second server block. Why can't you remove it, add www.example.com to the first block and substitute $scheme:// with https:// ? As far as i see you'lee have the same functionality.
    – Glueon
    Oct 17 '14 at 13:58
  • @Glueon I get nginx: [warn] conflicting server name "www.example.com" on 0.0.0.0:443, ignored when I put server_name example.com www.example.com; in the first server block with https:// instead of $scheme://
    – allaire
    Oct 17 '14 at 15:24
1

If you have a wildcard certificate for *.example.com, this is possible to write it under this form :

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    ssl_certificate /etc/ssl/certs/www.example.com.pem;
    ssl_certificate_key /etc/ssl/private/www.example.com.key;
    return 301 https://www.example.com$request_uri;
}

server {
    listen 443;
    server_name www.example.com;

    root /home/example/apps/site;
    index index.php index.html index.htm;
    server_tokens off;

    location / {
        try_files $uri $uri/ =404;
    }

    [ ... ]

}

The SSL handshake will always occur in the first block thus providing the wildcard domain certificate.

The server_name election, as it's SSL, is done after the handshake and allows this form of configuration where the right server block is not necessarily the one in which the handshake occured.

The default_server directive will force redirection of unknown/empty/non-existent Host headers to the HTTPS domain.

8
  • What is the first server block for? It seems to be redundant. The third one can be used as a default SSL virtual host.
    – Glueon
    Oct 17 '14 at 14:09
  • @Glueon No it can't because you want to redirect between two domains. The first server block is a "catch all traffic" for SSL handshake. Oct 17 '14 at 14:10
  • And if i use the "default" keyword?
    – Glueon
    Oct 17 '14 at 14:13
  • @Glueon then you need to test with a if block the $host for each request going through this server block. Oct 17 '14 at 14:16
  • 1
    @Glueon Oh I think I got what you say, yes we can factorize this more by removing the second block and merging it into the first one. Updated answer. Oct 17 '14 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.