Showing posts with label nginx. Show all posts
Showing posts with label nginx. Show all posts

Saturday, August 27, 2016

Letsencrypt SSL certificates with nginx's proxypass

I was not able to directly use the instructions from the certbot site to successfully request an SSL certificate, instead I had to use their webroot plugin plus a few tweaks to my nginx configuration.

Background

For this project we were deploying a Pyramid based system which uses nginx's reverse proxy (proxypass). This approach will be useful in any scenario where nginx is using proxypass. The OS used is Ubuntu Trusty 14.04 but should work on Debian as well (some things are more straight forward on Ubuntu 16.04).

Here are all the key concerns:
  • Certbot/Letencrypt expects to find your certificate challenge data served under a folder called '.well-known'
  • By default all requests for my project are passed via a reverse proxy to our application.
This means that, in the context of my project, when a request is passed to /.well-known  instead of serving my certbot challenge information from a folder on the filesystem the request is handled by the proxy and passes it as a request to my application. 

The Procedure

The steps below assume that nginx is configured as follows:
A special configuration file located at /etc/nginx/sites-enabled/myproject.example.com which looks like this (be sure to change the server name to match the server you're working with):

Step 1 - Make nginx serve static files when requests are sent to /.well-known

To achieve this I created a folder /var/www/letsencrypt and made sure that it was owned by the webserver user.
sudo mkdir -p /var/www/letsencrypt
chown www-data:www-data  /var/www/letsencrypt

Then in my nginx configuration for my project I added the configuration below to ensure that requests made to myproject.example.com/.well-known would skip the proxy and be read from our /var/www/letsencrypt folder.

server {
       listen         80;
       server_name myproject.example.com;
       location /.well-known {
          alias /var/www/letsencrypt/.well-known;
       } 

Once that was in place I restarted nginx.

service nginx reload

Step 2 - Install Certbot


The part of the documentation that I read was silent about where to put the certbot-auto script. I decided to install certbot-auto in /usr/local/sbin, this means that it is in the system path and can be run as a command by itself (which feels nicer than needing to be in the folder when running the script).
cd /usr/local/sbin/
sudo wget https://dl.eff.org/certbot-auto
sudo chmod a+x certbot-auto

Step 3 - Request a certificate against the /var/www/letsencrypt 

Now you can easily request a certificate.

Note the use of --webroot in the command below, this ensures that the challenge information is added to the /var/www/letsencrypt folder. Also, I precede the command with sudo because installation of the actual certificates requires admin privileges. 
sudo certbot-auto certonly --webroot -w /var/www/letsencrypt -d myproject.example.com

Expected response

If everything was done properly you'll get a message like this:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/myproject.example.com/fullchain.pem.
   Your cert will expire on 2016-11-25. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"

Step 4 - Configuring Auto-renewal of certificates

Once setup properly the auto renewal steps that I took were near identical to the documentation.
I first tested to see that an auto renewal would work without issue:

certbot-auto renew --dry-run

Once the dry run was succesfull I added a renewal command as a cronjob using the crontab -e command:

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
@monthly certbot-auto renew --quiet --no-self-upgrade

Additional Notes

I ran across a few issues, mostly because I had a previous manual setup. As a result when I ran certbot-auto I ended up with multiple configuration files and certificates in the /etc/letsencrypt/renewal/ and /etc/letsencrypt/live/ folders.
I assume you have a basic understanding of Unix system administration, nowadays this is becoming more of a bad assumption but I mention it here for what it's worth.


Wednesday, September 17, 2008

NGINX entity too large, no more

Sometimes a simple sentence can make a world of difference. It did that for my nginx configuration this morning. Since setting nginx in front of Plone, I've had an "413 entity too large" error for files bigger than 1 MB.

My configuration uses a special conf/proxy.conf file which looks like this::

# proxy.conf
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 30m;
client_body_buffer_size 2m;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 2m;
proxy_buffers 4 1m;
proxy_busy_buffers_size 2m;
proxy_temp_file_write_size 2m;

The wrong way

Previously my 'server' section in my nginx.conf used to look like this:

server {
listen 1.2.3.4;
server_name example.com www.example.com;
location / {
rewrite ^/(.*)$ /VirtualHostBase/http/www.example.com:80/example/plone/VirtualHostRoot/$1;
}
location /VirtualHostBase/ {
proxy_pass http://sharedhosting;
include conf/proxy.conf; #this is apparently a bad place to put this
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}


The right way

So I read the following comment at the slicehost forums:

"Try moving the directive from inside the location block to just inside the server block."


So now I've moved it to "just inside the server block" so my 'server' section in my nginx.conf now looks like this:

server {
listen 1.2.3.4;
server_name example.com www.example.com;
include conf/proxy.conf; #now it works, phew!
location / {
rewrite ^/(.*)$ /VirtualHostBase/http/www.example.com:80/example/plone/VirtualHostRoot/$1;
}
location /VirtualHostBase/ {
proxy_pass http://sharedhosting;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

}

Sign up for my upcoming Plone 5 Book & Video tutorials

plone 5 for newbies book and videos