How do I make my nginx proxy connect to a Heroku app behind Heroku SSL?

Issue

You want to have an Nginx proxy connect to a Heroku app behind Heroku SSL but it keeps reporting errors like error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:s3_pkt.c:1262:SSL alert number 80 during the SSL handshake. This applies to the SNI certs used in Private Spaces apps also.

Resolution

Heroku SSL uses Server Name Indication (SNI). Configure nginx with specifying proxy_ssl_server_name on and proxy_ssl_name with the custom domain name assigned for the SSL server certificate on the Heroku SSL endpoint.

 

For those using the Fastly addon service, under the config for your backend you will need to set the ssl_sni_hostname to the custom domain name assigned for the SSL server certificate on the Heroku SSL endpoint.


Here is an example /app/config/nginx.conf.erb for use with the nginx buildpack:

daemon off;
# Heroku dynos have at least 4 cores
worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>;

events {
    use epoll;
    accept_mutex on;
    worker_connections <%= ENV['NGINX_WORKER_CONNECTIONS'] || 1024 %>;
}

http {
    gzip on;
    gzip_comp_level 2;
    gzip_min_length 512;
    server_tokens off;

    log_format main '$time_iso8601 - $status $request - client IP: $http_x_forwarded_for - to $upstream_addr - upstream status: $upstream_status, upstream_response_time $upstream_response_time, request_time $request_time';
    access_log /dev/stdout main;
    # set the following to "debug" when diagnosing an issue
    error_log /dev/stdout notice;
    log_not_found on;

    include mime.types;
    default_type application/octet-stream;
    sendfile on;

    # Must read the body in 5 seconds.
    client_body_timeout <%= ENV['NGINX_CLIENT_BODY_TIMEOUT'] || 5 %>;

    # handle SNI
    proxy_ssl_server_name on;
    # resolver needs to be set because we're using dynamic proxy_pass
    resolver 8.8.8.8;

    upstream upstream_app_a {
        server app-a.herokuapp.com:443;
    }

    upstream upstream_app_b {
        server app-b.herokuapp.com:443;
    }

    server {
        listen <%= ENV["PORT"] %>;
        server_name _;

        location / {
            set $upstream upstream_app_a;
            proxy_pass https://$upstream;
            proxy_ssl_name app-a.herokuapp.com;
            proxy_set_header x-forwarded-host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host app-a.herokuapp.com;
        }

        location /other {
            set $upstream upstream_app_b;
            proxy_pass https://$upstream;
            proxy_ssl_name app-b.herokuapp.com;
            proxy_set_header x-forwarded-host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Host app-b.herokuapp.com;
        }
    }
}

Ask on Stack Overflow

Engage with a community of passionate experts to get the answers you need

Ask on Stack Overflow

Heroku Support

Create a support ticket and our support experts will get back to you

Contact Heroku Support