How to create and install self-signed SSL certificate on Nginx in CentOS 6

Google starts to love https from months back and recommends all websites to be encrypted with SSL over HTTP. Rumor said google gives higher rank to those websites have https than websites without ssl. If you have budget, go ahead and buy signed certificates comodo, geotrust, thawte, godaddy, symantec, etc… If you just want to have SSL for testing servers or non critical websites, self-signed SSL certificates are a great choice since you don’t need to spend a dime. The only problem with self-signed ssl certificates is web browsers won’t validate self-signed certificates unless you import them.

What are the differences between signed and self-signed SSL certificates?

CA (Certificate Authorities) signed certs:

  • You have to pay a fee to get CA signed certs
  • CA guaranteed you/your website is legit
  • Web browsers knows/accepts CA certs
  • No security warning from web browsers

Self-signed certs:

  • No cost certs
  • Web browsers won’t recognize self-signed certs unless you import them
  • Anyone can issue self-signed certs by themselves
  • Web browsers will warns clients SSL is not trusted

Install Nginx 1.6.x on CentOS 6

Enough talking, first let’s install nginx by adding nginx’s official repository

# nano /etc/yum.repos.d/nginx.repo

with the content

name=nginx repo

Install nginx web server / proxy server

# yum install nginx

To start nginx

# service nginx start

To start nginx automatically at boot/reboot

# chkconfig nginx on

Allow HTTP and HTTPS on iptables

To make sure you allow http and https traffic on your server, allow port 80 and 443 with iptables rules

# iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
# iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables-save

Create SSL directory in the Nginx directory

We are going to store our private key and self-signed ssl certificate in /etc/nginx/ssl. You can change this location to wherever you want, but I like to keep them inside nginx directory since we only use the key and certificate for nginx. So let’s create the new ssl directory inside nginx

# mkdir /etc/nginx/ssl

Generate private key and self-signed ssl certificate

# openssl req -x509 -nodes -sha256 -days 356 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
  • openssl: it’s the command to generate, check, debug, convert, and mange openssl certificates, keys and other files
  • reg: openssl reg is one of openssl’s tool/utility to create a certificate request (CSR)
  • -x509: is a certificate display and signing tool,  rather creating certificate signing request (CSR), we use -x509 option to tell openssl reg to create a self-signed certificate.
  • -nodes: this option tells openssl not to encrypt private key so nginx can read the file.
  • -sha256: to create sha256 fingerprint/signatures instead of sha1 (openssl uses sha1 by default). SHA-256 has been improved to enhance the certificate’s security (stronger and longer hash)
  • -days: to set the number of days that the ssl certificate will be valid for. Default value is 30 days, in our sample I used 365 days which is a year. You can set it much longer if you want to.
  • -newkey rsa:2048: to create a new self-signed certificate with a new 2048 bit rsa private key at the same time.
  • -keyout: this option tells openssl where to save the generated private key.
  • -out: tells openssl where to save the self-signed certificate.

openssl will ask you to enter for Country, State, Location, Organization name & unit, hostname, and email address. You don’t have to type in anything and leave those fields empty by hitting enter since the certificate is self-signed.

Generating a 2048 bit RSA private key
writing new private key to 'nginx.key'
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [XX]:us
State or Province Name (full name) []:california
Locality Name (eg, city) [Default City]:westminster
Organization Name (eg, company) [Default Company Ltd]
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []
Email Address []:

Generate DHE parameter

Even though we are using self-signed ssl certificate, it does not mean we can’t do anything to improve security. I stumble upon an article talks about Strong SSL Security on nginx, the address to that article is at the end of this article in References section. In Strong SSL Security on nginx, wrote about various SSL attacks and ways to deal with them. In that article he mentioned about Ephemeral Diffie-Hellman (DHE) which I’m interested in. Diffie-Hellman (DH) has been around for a while but not many people use it. Diffie-Hellman is a key agreement protocol means SSL client and SSL server use the same protocol with a pre-master key using the Diffie-Hellman algorithm.The server will send the client a prime number and a generator. The keys are in clear text and it’s not a secret key, but they must be signed.

So it’s time for us to generate some DHE permanent. (this process may take a long time since we are going to generate 4096 bit key). You can grab a cup of tea while waiting for openssl generate DH parameters.

# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

Configure Nginx to accept SSL/HTTPS

You can insert this nginx’s configurations to your current Nginx site configure file or create a new Nginx configure file just for SSL. For our article, I will just create a new Nginx configure file for ssl.

# nano /etc/nginx/conf.d/ssl.conf

with the content

server {
 listen youripaddress:443 ssl;
 server_name yourdomainname;

ssl on;
 ssl_certificate /etc/nginx/ssl/nginx.crt;
 ssl_certificate_key /etc/nginx/ssl/nginx.key;
 ssl_dhparam /etc/nginx/ssl/dhparam.pem;

ssl_session_timeout 60m;
 ssl_session_cache shared:SSL:10m;

ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
 ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;
 ssl_prefer_server_ciphers on;

add_header Strict-Transport-Security max-age=63072000;
 add_header X-Frame-Options DENY;
 add_header X-Content-Type-Options nosniff;

location / {
 root /var/www/html;
 index index.html index.htm index.php;

Don’t forget to adjust server_name, location block, and .php block if you run PHP. Replace youripaddress and yourdomainname to yours, if you don’t have an dedicated IP address for your website, you can leave youripaddress empty and just use

 listen 443 ssl;

Test and Restart Nginx
You will have to restart Nginx for the configurations to take affect.

# nginx -t
# service nginx restart


Well because the ssl certificate is self-signed, web browsers can’t verify and firefox gives the error “could not verify this certificate because the issuer is unknown ” or google chrome gives “The identity of this website has not been verified. Server’s certificate is not trusted”


Redirect HTTP traffic to HTTPS

If you decide you use https as default rather than http for your website, you can redirect all http traffic to https permanently on nginx with this configure

server {
 listen ipaddress:80;
 return 301 https://$server_name$request_uri;

server {
 listen ipaddress:443 ssl;

# the rest of your nginx's configures go here. 

Using openssl to verify SSL Certificate

This is just for your information, after digging about SSL topic, I found out it’s interesting what information openssl verification process give out about the certificate. So I guess it’s good to share the info. You can see exactly what kind of SSL certificate the server is running, protocol, cipher, and such with openssl verify command.

You can use this command below to verify your SSL certificates, it’s obviously we are creating/using self-signed ssl certificate so openssl gives back return code: 18 (self signed certificate) 🙂

# openssl s_client -showcerts -connect < /dev/null

Sample output

depth=0 C = us, ST = california, L = westminster, O =, CN =
verify error:num=18:self signed certificate
verify return:1
depth=0 C = us, ST = california, L = westminster, O =, CN =
verify return:1
Certificate chain
0 s:/C=us/ST=california/L=westminster/
Server certificate
No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits
SSL handshake has read 1606 bytes and written 375 bytes
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
Protocol  : TLSv1.2
Cipher    : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 5E21EAF10F4C8F982868B404A941D2771DD67D5E49103CDFF069EBF0285214B5
Master-Key: 1D63417742EE7D696330CD14FE67C619E78B0918818AD2F10D4BBDB4EC4005634EBD5D1A145FBBF031F636D953341FEB
Key-Arg   : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
TLS session ticket lifetime hint: 3600 (seconds)
TLS session ticket:
0000 - 61 21 58 c7 1c 5f b5 db-39 d3 10 85 f6 c6 cf e4   a!X.._..9.......
0010 - 1a b3 7a a6 00 f0 b1 22-d6 15 12 6b eb 05 5b 27   ..z...."...k..['
0020 - d7 9f 77 89 47 94 8e 57-ab 46 e9 7f eb 0b cb ec   ..w.G..W.F......
0030 - 3d aa ef 61 93 1e 58 79-a0 40 b6 b2 38 ec 2e db   =..a..Xy.@..8...
0040 - 15 56 d8 74 4c 06 b9 14-e3 cd bc cf e0 18 77 bc   .V.tL.........w.
0050 - 57 e6 09 a9 f8 14 7d 2a-54 22 5d c3 2d 52 49 21   W.....}*T"].-RI!
0060 - 56 fd 96 0e f2 fa c4 66-51 b9 2f d9 5f da d2 68   V......fQ./._..h
0070 - 0e 0b 2d 8a 72 2a a9 b8-b7 13 7c 86 55 5d 9c fb   ..-.r*....|.U]..
0080 - 0f d8 b4 1f 43 a0 c7 67-70 4d c7 29 6e 18 47 21   ....C..gpM.)n.G!
0090 - 02 d0 19 2d fe 35 17 95-00 b2 a9 19 cd 4a 3a 40   ...-.5.......J:@
00a0 - 7a b3 3f ed 74 a0 90 b3-6f 1d 68 4d fb ee 8e 42   z.?.t...o.hM...B

Start Time: 1418043711
Timeout   : 300 (sec)
Verify return code: 18 (self signed certificate)


  • “X509.” Openssl. N.p., n.d. Web. 08 Dec. 2014. <>.
  • “Strong SSL Security on Nginx –” Raymii, n.d. Web. 08 Dec. 2014. <>.
  • Pornin, Thomas. “Diffie-Hellman and Its TLS/SSL Usage.” N.p., n.d. Web. 26 Aug. 2013. <>.
  • “Security/Server Side TLS.” – MozillaWiki. N.p., n.d. Web. 09 Dec. 2014. <>.

Related Articles

Notify of

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Inline Feedbacks
View all comments
Back to top button