# NGINX Installation

**URL:** <https://community.letsencrypt.org/t/nginx-installation/3502>\
**Category:** Server\
**Created:** [November 10, 2015, 4:30pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502 "2015-11-10T16:30:03Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![DrPain](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/drpain/32/1860_2.png) [@DrPain](https://community.letsencrypt.org/u/DrPain)\
**Post date:** [November 10, 2015, 4:30pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/1 "2015-11-10T16:30:03Z")

</div>

Hi All,

I tried finding a definitive answer, but couldn’t find one. Does Let’s Encrypt currently support NGINX, and if so how exactly do I go about installing a cert on it? Can someone provide a guide to do this manually if needs be?

Cheers,  
Rudi

**EDIT:** For those looking for my solution, scroll down 😃

---

<div class="post-metadata">

**Author:** ![renchap](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/renchap/32/1855_2.png) [@renchap](https://community.letsencrypt.org/u/renchap)\
**Post date:** [November 10, 2015, 5:16pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/2 "2015-11-10T17:16:11Z")

</div>

Hi @DrPain

I posted a quick howto today on how to do it : [Howto: easy cert generation and renewal with nginx](https://community.letsencrypt.org/t/howto-easy-cert-generation-and-renewal-with-nginx/3491/6) 😄

---

<div class="post-metadata">

**Author:** ![mlp](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/mlp/32/1781_2.png) [@mlp](https://community.letsencrypt.org/u/mlp)\
**Post date:** [November 10, 2015, 5:55pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/3 "2015-11-10T17:55:17Z")

</div>

Thanks a lot, it’s going to be really useful 🙂

---

<div class="post-metadata">

**Author:** ![DrPain](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/drpain/32/1860_2.png) [@DrPain](https://community.letsencrypt.org/u/DrPain)\
**Post date:** [November 10, 2015, 8:03pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/4 "2015-11-10T20:03:58Z")

</div>

Awesome thank you so much, I will give it a read over. Good man!

---

<div class="post-metadata">

**Author:** ![DrPain](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/drpain/32/1860_2.png) [@DrPain](https://community.letsencrypt.org/u/DrPain)\
**Post date:** [November 11, 2015, 7:26pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/5 "2015-11-11T19:26:21Z")

</div>

Ok so, maybe this will shed some light for others. I did try and use the documentation provided, but what confused the hell out of me was the naming convention. Now I am not a sysadmin, rather a developer “sysadmin-light”. I tried setting up the VHOST as suggested, but it just didn’t want to access that file. I watched the folder and they were being generated in there, and NGINX was serving them, but it just didn’t want to auth.

So I went back and I redid everything. This is what worked for me, using my example domain of “[www.allroundtraders.co.za](http://www.allroundtraders.co.za)”

**1. Clone into the “letsencrypt” repo as per docs**

```
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto --server \
https://acme-v01.api.letsencrypt.org/directory --help

```

**2. Stop NGINX and run the standalone verification server, ok so not ideal but it worked. Follow the prompts**

```
service nginx stop

./letsencrypt-auto certonly \
-a standalone \
-d www.allroundtraders.co.za \
-d allroundtraders.co.za \
--server https://acme-v01.api.letsencrypt.org/directory \
--agree-dev-preview

```

**NOTE** I noticed that when you run the above command it does indeed create the directory called “/etc/letsencrypt/live/www.allroundtraders.co.za/”, but if you have multiple domains in 1 request, the directory will be called after the first domain in the command.

**IE:** If I had “-d [thatguy.co.za](http://thatguy.co.za) -d [www.thatguy.co.za](http://www.thatguy.co.za) -d [allroundtraders.co.za](http://allroundtraders.co.za) -d www.allroundtraders” Then it creates 1 cert containing all the domains as an alias, but it would be in the “/etc/letsencrypt/live/thatguy.co.za/”. It’s just something to keep in mind, keep the order in which you specify your multiple domains the same. Otherwise you will need to update all the certificate references in NGINX.

**3. Start NGINX again**

```
service nginx start

```

Now what got me confused was the naming convention of the key, cert and chain. After this succeeds, a fresh set of certs and keys are generated. Hazaaaa:

```
root@TheDirector:/ # ls /etc/letsencrypt/live/www.allroundtraders.co.za/
cert.pem chain.pem fullchain.pem privkey.pem
root@TheDirector:/ # 

```

Note the `cert.pem` is what others may be familiar with as `server.crt`, the `privkey.pem` would then be what some are used to seeying as `server.key`. And then the `chain.pem` if you do SSL stapling, which you should. Would be the entire cert chain.

Now these are merely symlinks, which point to the new certs and keys as they get renewed / issued. This means that NGINX only needs point to these files ever. And will automatically point to the most current certificate set. Pretty cool guys!

**4. Update NGINX VHOST as needed**

Now you will need to update your NGINX VHOST to point to this cert set. This is what mine looks like, keep in mind that I reverse proxy to other servers, but the important part to note is the SSL specific parts:

```
# NON-SSL
server {
        server_name allroundtraders.co.za www.allroundtraders.co.za img.allroundtraders.co.za;
        if ($scheme = http) {
               return 301 https://$server_name$request_uri;
        }   
}

# SSL
server {

        listen 443;
        server_name allroundtraders.co.za www.allroundtraders.co.za img.allroundtraders.co.za;

        ssl on;
        ssl_certificate /etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.allroundtraders.co.za/privkey.pem;

        ssl_stapling on;
        ssl_stapling_verify on;
        add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";            
              

	location ~* /\.\./ {
                deny all;
                return 404;
        }

	location / {
	        proxy_pass http://app_servers;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
       	}
}

```

**NOTE:** Remember to run `nginx -t` to test your NGINX config, before assuming everything you did is valid. It’s pretty good at pointing out mistakes.

Like I mentioned, I am a developer by trade, not a sysadmin. Rather a sysadmin-light, so if I am wrong in my statements above please feel free to correct me and help others by doing so.

So far I am pretty impressed guys! So close indeed!

---

<div class="post-metadata">

**Author:** ![riniah](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/riniah/32/2593_2.png) [@riniah](https://community.letsencrypt.org/u/riniah)\
**Post date:** [December 4, 2015, 8:53am UTC](https://community.letsencrypt.org/t/nginx-installation/3502/6 "2015-12-04T08:53:04Z")

</div>

Hi thanks for this it worked perfectly for me.  
Now that I’ve used this method what command should I run in 90 days to renew them?

---

<div class="post-metadata">

**Author:** ![sleeps](https://avatars.discourse-cdn.com/v4/letter/s/c37758/32.png) [@sleeps](https://community.letsencrypt.org/u/sleeps)\
**Post date:** [December 5, 2015, 4:17pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/7 "2015-12-05T16:17:51Z")

</div>

Just a small change, to help get A+ rating on SSL Checker I had to make the following changes:

Change:

`ssl_certificate /etc/letsencrypt/live/<YOUR_DOMAIN>/cert.pem;`

To

`ssl_certificate /etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem;`

And remove:

`ssl_trusted_certificate /etc/letsencrypt/live/<YOUR_DOMAIN>/fullchain.pem;`

Then turn on HSTS

`add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";`

You can also add a redirect from http to https if you want by adding the following to your http (non-secure) server config:

`if ($scheme = http) { return 301 https://$server_name$request_uri; }`

For those that are interested, my full ssl config for nginx is:

`listen 443 ssl spdy; ssl_certificate /etc/letsencrypt/live/<YOUR_SITE>/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<YOUR_SITE>/privkey.pem; ssl_stapling on; ssl_stapling_verify on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA'; ssl_dhparam /etc/nginx/ssl/dhparams.pem; ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m;`

Feel free to point out any mistakes I’ve made 😄

---

<div class="post-metadata">

**Author:** ![DrPain](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/drpain/32/1860_2.png) [@DrPain](https://community.letsencrypt.org/u/DrPain)\
**Post date:** [December 5, 2015, 4:53pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/8 "2015-12-05T16:53:30Z")

</div>

I am glad to hear this has helped you as well. Hopefully the NGINX automation will be sorted soon. But if you need to **–renew** the certs for whatever reason. You would run the same command with one extra property

Using the example from the original post, this would then be:

```
./letsencrypt-auto certonly \
-a standalone \
--renew \
-d www.allroundtraders.co.za \
-d allroundtraders.co.za \
--server https://acme-v01.api.letsencrypt.org/directory \
--agree-dev-preview
```

---

<div class="post-metadata">

**Author:** ![DrPain](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/drpain/32/1860_2.png) [@DrPain](https://community.letsencrypt.org/u/DrPain)\
**Post date:** [December 5, 2015, 5:02pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/9 "2015-12-05T17:02:31Z")

</div>

Thank you for the feedback, I have added some of the changes you suggested. It’s more concise thank you!

---

<div class="post-metadata">

**Author:** ![tlawal](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/tlawal/32/1633_2.png) [@tlawal](https://community.letsencrypt.org/u/tlawal)\
**Post date:** [December 5, 2015, 11:07pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/10 "2015-12-05T23:07:51Z")

</div>

I’m using elastic beanstalk, and I don’t understand the last step (4) that you outlined. How do I update the NGINX VHOST?

---

<div class="post-metadata">

**Author:** ![sleeps](https://avatars.discourse-cdn.com/v4/letter/s/c37758/32.png) [@sleeps](https://community.letsencrypt.org/u/sleeps)\
**Post date:** [December 6, 2015, 1:59pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/11 "2015-12-06T13:59:49Z")

</div>

You need to get a shell open, sudo edit the nginx config file for your website/domain…

I’m guessing you can ssh in? Never used elastic beanstalk myself.

---

<div class="post-metadata">

**Author:** ![amilajack](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/amilajack/32/3588_2.png) [@amilajack](https://community.letsencrypt.org/u/amilajack)\
**Post date:** [December 22, 2015, 11:44pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/12 "2015-12-22T23:44:56Z")

</div>

How can I create a certificate on my host machine and copy the certificates to docker containers that I am using? Is that possible? I’m really new to all of this so any advice would help. Thanks!

---

<div class="post-metadata">

**Author:** ![DrPain](https://sea3.discourse-cdn.com/letsencrypt/user_avatar/community.letsencrypt.org/drpain/32/1860_2.png) [@DrPain](https://community.letsencrypt.org/u/DrPain)\
**Post date:** [January 5, 2016, 12:18pm UTC](https://community.letsencrypt.org/t/nginx-installation/3502/13 "2016-01-05T12:18:33Z")

</div>

I know a bit of docker, but my current setup doesn't use it. You can generate the certs on the host and mount them into Docker with the "-v" volume switch. You would also renew them on the host itself.

This will work with the standalone version which tried to start a webserver, but you will need to stop nginx while doing this as you can only have 1 thing listening on port 80 at a time.

The documentation on mounting volumes on Docker:

> **[Volumes](https://docs.docker.com/storage/volumes/)**
>
> Learn how to create, manage, and use volumes instead of bind mounts for persisting data generated and used by Docker.

**BETTER**

I better solution is to mount a common directory and a vhost on nginx to handle the incoming challenge request. An example vhost for me is:

```
server {
        listen 80;
        server_name heroesofthestorm.co.za www.heroesofthestorm.co.za img.heroesofthestorm.co.za;

	location '/.well-known/acme-challenge' {
  		default_type "text/plain";
		root /tmp/letsencrypt-auto;
  	}

        # .... Rest of the locations
}

```

Give this article a read, this uses NGINX to manage the incomming request with the location mapping above:

> [@Howto: easy cert generation and renewal with nginx](https://community.letsencrypt.org/t/howto-easy-cert-generation-and-renewal-with-nginx/3491):
>
> A…
