233

Is there a way to share configuration directives across two nginx server {} blocks? I'd like to avoid duplicating the rules, as my site's HTTPS and HTTP content are served with the exact same config.

Currently, it's like this:

server {
  listen 80;
  ...
}

server {
  listen 443;

  ssl on; # etc.
  ...
}

Can I do something along the lines of:

server {
  listen 80, 443;
  ...

  if(port == 443) {
    ssl on; #etc
  }
}

5 Answers 5

323

You can combine this into one server block like so:

server {
    listen 80;
    listen 443 default_server ssl;

    # other directives
}

Official How-To

12
  • 8
    Ah, I had no idea nginx was intelligent enough to ignore the SSL directives if loaded over port 80. Awesome!
    – ceejayoz
    May 21, 2009 at 19:34
  • 79
    nginx is all sorts of WIN.
    – Jauder Ho
    May 21, 2009 at 19:38
  • 7
    and if you have several sites at one server, it's worth mentioning that "default" is not obligatory
    – luchaninov
    Jul 1, 2011 at 15:32
  • 7
    So elegant it hurts...
    – Alix Axel
    Nov 24, 2012 at 1:39
  • 5
    not working here... "The plain HTTP request was sent to HTTPS port"
    – gcstr
    Aug 18, 2014 at 3:55
95

To clarify the accepted answer, you need to omit

SSL on;

and you just need the following for nginx version after 0.8.21

listen 443 ssl;

Reference:

Nginx Docs - Configuring A single HTTP/HTTPS server

1
  • 2
    Thank you! I could not figure out why nothing on http was working. Removing SSL on; worked. Feb 14, 2014 at 16:27
32

I don't know of a way like you suggest, but there's certainly an easy and maintainable way.

Move common server settings into a separate file, i.e. "serverFoo.conf" and then include it in separate server {} blocks like so:

server {
    listen 80;
    include serverFoo.conf;
}
server {
    listen 443 ssl;
    include serverFoo.conf;
}
6
  • 2
    +1 = works for me. (Couldn't get it to work with the other method.)
    – user11480
    Jul 3, 2009 at 15:44
  • Also, the other example doesn't account for 'proxy_pass' if acting as a load balancer. Apr 24, 2013 at 23:34
  • This option is great if your server_name is different for each port
    – iDev247
    Oct 3, 2013 at 6:40
  • 5
    Don't use ssl on, use listen 443 ssl; from now one. Mar 22, 2016 at 21:47
  • This seems to be the only solution that is working with recent nginx 1.10.1. For some reason two listen lines are not interpreted correctly, but moving them to separate server{} fixes it. Aug 1, 2016 at 10:54
12

Expanding on the already helpful answers, here is a more complete example:

server {

    # Listen on port 80 and 443
    # on both IPv4 and IPv6
    listen 80;
    listen [::]:80 ipv6only=on;
    listen 443 ssl;
    listen [::]:443 ipv6only=on ssl;

    # Set website folder
    root /path/to/your/website;

    # Enable SSL
    ssl_certificate your-cert.pem;
    ssl_certificate_key your-cert.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
    ssl_prefer_server_ciphers on;
}
1
  • 2
    I know this is a pretty old answer, but as it's very complete I just wanted to point out for others who may use it that you should disable the SSLv3 protocol as its vulnerable to the POODLE vulnerability: disablessl3.com Instead use: ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    – user147787
    Jan 6, 2015 at 23:32
6

Just to add to Igor/Jauder's post, if you're listening to a specific IP you can use:

listen xxx.xxx.xxx.xxx;
listen xxx.xxx.xxx.xxx:443 default ssl;

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .