I would like to avoid having to repeat all the virtualhost server {} blocks in nginx just to have custom ssl settings that vary slightly from plain http requests.

Most ssl directives can be placed right in the main block, except one hurdle I cannot find a workaround for: different keep-alive for https vs http

Is there any way I can use $scheme to dynamically change the keepalive_timeout ?

I've even considered that I can use more_set_input_headers -r 'Keep-Alive: timeout=60'; to conditionally replace the keep-alive timeout only if it already exists, but the problem is $scheme cannot be used in location ie. this is invalid location ^https {}


I'm pretty sure you can use a map :

map $scheme $myCustomTTL {
   default     90;
   http        90;
   https       60;

add_header Keep-Alive timeout=$myCustomTTL;
| improve this answer | |
  • Ohh! Didn't know about that one, it's a very basic switch/case, thank you. – ck_ Nov 27 '12 at 9:29
  • 1
    This will not work. You just set a header for browser, but it will not affect nginx behavior. Clients may ignore this header. – VBart Nov 28 '12 at 3:43
  • 1
    You're right. I've just followed what @ck_ was suggesting with headers, without asking myself if it was a good practice. keepalive_timeout is the directive used by nginx to control the KeepAlive behavior. So what should be written is : keepalive_timeout ${myCustomTTL}s ${myCustomTTL}s – Mickaël Le Baillif Nov 28 '12 at 7:53
  • Actually: keepalive_timeout" directive invalid value in /etc/nginx/nginx.conf what I think is happening is how nginx cannot use variables during load time, only runtime. – ck_ Nov 29 '12 at 9:08

As it seems that keepalive_timeout cannot be used with parameters but only with fixed values, another solution would be to use nginx as a SSL endpoint.

Your SSL requests will be handled by a specific server{} block, that would only manage the SSL handshake and the specific Keep-Alive value, then forward the plain-HTTP request to the main server {} block.

Your nginx configuration would include something like the following:

upstream plain_http {

server {
   listen   443;
   server_name  *.yourdomain.com;
   ssl                       on;
   ssl_certificate           /etc/nginx/ssl/mycert.pem;
   ssl_certificate_key       /etc/nginx/ssl/mykey.key;
   ssl_protocols             SSLv3 TLSv1;
   ssl_ciphers               ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM;
   ssl_prefer_server_ciphers on;

   keepalive_timeout 90;

   location / {
     proxy_pass              http://plain_http;
     proxy_redirect http:// https://;  

The proxy_redirect directive tells nginx to rewrite URI found in Location and Refresh headers in the plain-HTTP response.

| improve this answer | |
  • Can nginx proxy_pass to another proxy_pass? ie. daisy chain the ssl to an apache reverse proxy? – ck_ Nov 29 '12 at 14:38
  • There's no reason you couldn't do that, since the plain-HTTP nginx server is quite independant from its SSL sibling. – Mickaël Le Baillif Nov 29 '12 at 14:56

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.