We use Nginx as a reverse proxy to our web application server. Nginx handles our SSL and such but otherwise just acts as a reverse proxy.

We want to require a valid client cert for requests to /jsonrpc but not require them anywhere else. The best way we've found is to

server {
  listen       *:443 ssl;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

  ssl_verify_client optional;

  location /jsonrpc {
    if ($ssl_client_verify != "SUCCESS") { return 403; }

    proxy_pass          http://localhost:8282/jsonrpc-api;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}

This works fine for most browsers, but some browsers such as Safari and Chrome-on-Android end up prompting the user to provide a client cert no matter where on the website they go.

How do we get Nginx to accept but not really care about a client cert everywhere except our /jsonrpc location?

up vote 6 down vote accepted

Why not to try second server block instead? Code duplication is bad but sometimes unavoidable. I assume /jsonrpc represents an API so it can use its own subdomain if not already use it:

server {
  listen       *:443 ssl;
  server_name api.example.com;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

  ssl_verify_client on;

  location =/jsonrpc {
    proxy_pass          http://localhost:8282/jsonrpc-api;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}

server {
  listen       *:443 ssl;

  ssl on;
  ssl_certificate         /etc/nginx/server.crt;
  ssl_certificate_key     /etc/nginx/server.key;
  ssl_client_certificate  /etc/nginx/client-ca.crt;

  ssl_verify_client off;

  location / {
    proxy_pass          http://localhost:8282/;
    proxy_read_timeout  90;
    proxy_redirect      http://localhost/ $scheme://$host:$server_port/;
  }
}
  • This is what we'll probably end up doing if we can't figure out a way to put the right configuration all in the same server block. We haven't had this same issue when using Apache, so I'd hoped there was some setting that would work here. – Eli Courtwright Sep 13 '15 at 19:03
  • 1
    @EliCourtwright I know this question was a long time ago, but did you ever find a solution better than two server blocks? – N Jones May 31 '17 at 0:00
  • 2
    @NJones: unfortunately no, that's what we had to go with. – Eli Courtwright Jun 29 '17 at 18:51

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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