How to run HTTPS with Nginx

Posted by in Devops

How to setup SSL certificates with Nginx to run HTTPS on your servers.


This is what we get from the provider after purchasing the SSL certficate. File my-domain.crt stands for public server certificate which is sent to every client that connects to the server. The private key is stored in the my-domain.key file and the access to it should be restricted.

├── my-domain.crt
├── my-domain.key
└── my-domain_chain.txt

The my-domain_chain.txt file contains chain of intermediate certificates, usually it is called bundle.crt, so we will just rename it for the sake of the good habits.

mv my-domain_chain.txt bundle.crt

Now we can merge the server certificate with the chained certificates. Do not forget to add newline at the end of the my-domain.crt and make sure that the server certificate is at the beginning. This should ensure that the browsers wont complain about certificate signed by well known authority.

cat my-domain.crt bundle.crt > my-domain.chained.crt

We can then copy the certificates over to our server.

scp my-domain.chained user@host.com:/path/to/my-domain.chained.crt
scp my-domain.key user@host.com:/path/to/my-domain.key

Here is the example Nginx configuration for custom subdomain, we are redirecting all traffic to run over HTTPS on port 443.

# redirect all traffic running plain HTTP on port 80 to HTTPS
server {
  listen 80;
  server_name subdomain.domain.com;
  return 301 https://$server_name$request_uri;
}

# handle HTTPS on port 443
server {
  # listen on port 443, enable SSL
  listen 443 default ssl;
  server_name subdomain.domain.com;

  # share session cache across all workers, use 10M of memory
  # set cache timeout to 10 minutes
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;

  # set certificate paths
  ssl_certificate /path/to/my-domain.chained.crt;
  ssl_certificate_key /path/to/my-domain.key;

  # we dont want to perform the actual certificate validation
  ssl_verify_client off;

  # use the latest protocols
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  # try to get best possible encryption in all browsers
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;

  # server ciphers should be preferred over client ciphers
  ssl_prefer_server_ciphers on;

  # proxy all traffic to some backend
  location / {
    proxy_pass http://10.10.10.10:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

Read more

Social

About the author

Juraj Bubniak

CORETEQ Research & Development

Co-founder and Software engineer.