Nginx: set up a LetsEncrypt SSL certificate with auto-renewal in 3 easy steps

Unless you have been living under a rock for the past year, you should know by now that you can get SSL certificates free of charge from LetsEncrypt, without registration, and with automatic renewal! This is one of the best thing that's happened to web admins and the web in general in the recent years. The certificates are authentic and work great in all browsers (you get the little green lock icon like everywhere else).

Let's get straight to the point. The three steps are summarized here:
1) Download LetsEncrypt (the application) for your Linux server
2) Run the application to generate a certificate for your domain and set up the monthly auto-renew cron job
3) Add the certificate to your Nginx configuration.

Step 1: download LetsEncrypt

Install git if you haven't done so yet:
# apt-get install git

Use git to get the application and store it somewhere (ie: /root/temp)
# git clone https://github.com/letsencrypt/letsencrypt /root/temp/letsencrypt

Step 2: generate your certificate

The first time you run the command below, you will be asked to provide an e-mail address to be associated to the domain or subdomain, in case you should ever need to recover the key or something. The next time you run the same command (to renew the certificate) it won't be asked.

So run the following command to generate the certificate:
# /root/temp/letsencrypt/letsencrypt-auto certonly -a webroot --agree-tos --renew-by-default --webroot-path=XXX -d YYY
Where: XXX is the full path to your website's root folder. For example /home/www/website.com
And YYY is the domain name or subdomain name (ie: website.com, or something.website.com)

At the time of running the command, your domain must be available to visitors already, because LetsEncrypt's servers will make a verification to ascertain that you are actually the owner of the domain. It will place a hidden /.well-known/ folder with some files in it at the root of your web directory (specified above with --webroot-path).

Certificates generated by LetsEncrypt are valid 3 months at the moment. Also, wildcards are not supported; you can get certificates for domain names and subdomains one by one. Since we don't want to manually renew the certificate every month for every domain and subdomain, we can set up a simple cron job to be ran monthly (it should be run every 3 months ideally but LetsEncrypt are talking about reducing the validity of their certificates so I'd rather not be caught off guard).

Open /etc/cron.monthly and create a new file, make sure to chmod +x to give executable permissions. The first line of the file should be:
And then put the exact same command you ran before to generate the certificate. You can also add  >>/root/temp/certificate-update.log at the end of the command if you want to keep a log of the updates (although I imagine LetsEncrypt generates its own log somewhere too).

Step 3: configuring Nginx

After running the command that generates the certificates, you should have several files in /etc/letsencrypt/live/website.com/ (replace website.com by your own domain). We are going to need just two of them for Nginx: fullchain.pem and privkey.pem.

The beginning of your server block should look like this:
server {
server_name www.website.com website.com;
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/website.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/website.com/privkey.pem;
ssl_session_cache shared:SSL:20m;

Don't forget that last line, otherwise Safari and iOS devices won't be able to visit your website (see my recent blog post about it). Save configuration, reload, visit your site and voila, you're done. To make sure the automatic renewal script works, try running it now with the new configuration.


Nginx and LetsEncrypt SSL certificate problem with iOS and Safari (fixed)

I have recently started using LetsEncrypt as my main SSL certificate supplier, it's amazing! With the auto-renew cron task, I have literally 0 work to do to keep certificates up to date, and of course, it's free.

I recently noticed an issue though: when I visit my websites over HTTPS on my iPhone (and reportedly the problem exists with Safari on Mac OS X as well), the sites simply will not load. This is the error I get:

The error reads: "Safari cannot open the page because the network connection was reset. The server may be busy". After trying to sort out the problem for hours and Googling up the error everywhere, I finally stumbled upon this forum thread. Well thank you Mr. Duckson because that really did fix the problem!

The solution: in your server {  ... } block, insert the ssl_session_cache directive with whatever value you deem fit. Example from Nginx documentation: ssl_session_cache shared:SSL:10m;

Save your configuration, reload Nginx, try it again - voila, it's fixed. Kudos to koren on IRC for finding the solution, you have amazing Google skills, my friend. If anyone has an explanation as to why this directive is required for Safari/iOS browsers specifically with LetsEncrypt certificate, I'm all ears!


HTML5 video capture from browser: error with "stop() not a function"

A quick blog post about recent changes in the MediaStream API support in modern browsers. I had previously developed a function allowing users to capture images from their webcam, based on tutorials found on the web.

Here was my code to initialize the capture canvas:

function CaptureImageBeginCapture() {
   CaptureImageCanvas = $("#ImageCaptureCanvas")[0];
   var videoObj = { "video": true },
      errBack = function(error) {
         console.log("Video capture error: ", error.code);

   CaptureImageVideo = $("#ImageCapturePreviewFrame")[0];
   CaptureImageContext = CaptureImageCanvas.getContext("2d");

   // Put video listeners into place   if(navigator.getUserMedia) { // Standard      navigator.getUserMedia(videoObj, function(stream) {
         CaptureImageStream = stream;
         CaptureImageVideo.src = stream;
      }, errBack);
   } else if(navigator.webkitGetUserMedia) { // WebKit-prefixed      navigator.webkitGetUserMedia(videoObj, function(stream){
         CaptureImageStream = stream;
         CaptureImageVideo.src = window.webkitURL.createObjectURL(stream);
      }, errBack);
   else if(navigator.mozGetUserMedia) { // Firefox-prefixed      navigator.mozGetUserMedia(videoObj, function(stream){
         CaptureImageStream = stream;
         CaptureImageVideo.src = window.URL.createObjectURL(stream);
      }, errBack);
And this code was used to react to the pressing of a "Capture" button which froze the image and then saved it.
// Snapping up the picture$("#ImageCaptureSnap").click(function() {
   CaptureImageContext.drawImage(CaptureImageVideo, 0, 0, 640, 480, -95,0,448,330);
Unfortunately, the MediaStream.stop() function recently became depreciated. After a quick search, I found only one article explaining what I need to do to fix it. The fix is to get a "track" instance from your MediaStream and stop the track instead of stopping the MediaStream itself.
// Snapping up the picture$("#ImageCaptureSnap").click(function() {
   CaptureImageContext.drawImage(CaptureImageVideo, 0, 0, 640, 480, -95,0,448,330);
   try { CaptureImageStream.stop(); } catch(e) { }
   try {
       var track = CaptureImageStream.getTracks()[0];
} catch(e) { }
$("#ImageCaptureStep1").hide(); $("#ImageCaptureStep2").show(); });
Hopefully it won't change further, but as we know HTML5 APIs are evolving all the time.


3 PHP quizzes for testing your knowledge: beginner, medium, and advanced levels

Hello everyone,

I have created three short quizzes for testing your PHP knowledge. They were meant to be used before job interviews as a way to provide a quick evaluation of the skill level of the applicant. They have served their purpose so I am releasing them to the public. If you really want to know your level, don't google up the answers while playing.

Beginner : http://goo.gl/H9seNQ

What was your score? Also, did you notice any errors in the questions? I know some of the answers can be up to debate (the regexp one in particular) but obviously if you know the answer you will pick the one that best matches what you think is the truth. 

Also, keep in mind that while I consider these to be "beginner", "medium", and "advanced" levels, depending on your own skills you could laugh and consider me a newbie. It's just that from my perspective, if an interviewee is able to get a 10/10 at the advanced quiz, they are welcome to join my development team. That's all these quizzes really mean. 

Finally, I would be curious to see if anyone could create a "hardcore" quiz. I don't consider myself quite up to the task and would probably fail miserably at the test. So be my guest!


Get Nginx HTTP Server 3rd Edition and any other book from Packt Publishing for just $5

Dear readers, bloggers, fellow administrators, I have been informed by my excellent publisher Packt Publishing that they are currently running an amazing offer: you can get any of their books for just $5. This includes my recent publication - Nginx HTTP server 3rd edition. The promotion started yesterday and will last until New Year. Hurry up and get as many books as you can before the promotion ends!


Outlook 2010 stuck in safe mode - just uninstall KB3114409

Yesterday (December 9th, 2015) Microsoft rolled out a faulty update for Microsoft Office 2010 (KB3114409) which accidentally causes Outlook 2010 to start in safe mode systematically, ignoring registry and computer settings.

To solve the problem, simply go to the "Programs and features" control panel applet, click on "View installed updates", search for KB3114409, and uninstall it. After you reboot your computer, Outlook will start normally again.

This solution has been tested successfully at work for dozens of users.

Microsoft stated: “After you install this update, Outlook 2010 may start only in safe mode. If this issue occurs, uninstall the update. This update is no longer available now."

Source: Microsoft message boards


Nginx HTTP Server - Third Edition now available!

I am glad to announce that the third edition of "Nginx HTTP Server" (the book) is now available! You can already buy the ebook over at Amazon.com or directly from Packt Publishing. Paperback version will follow on December 1st.

Aside from the numerous corrections, chapter overhauls, and section rewrites, this new edition comes with two entirely new chapters:
  • an introduction to load balancing and optimization
  • real life case studies, starting from scratch
It is much more practice-oriented, focusing on examples rather than endless directive bullet lists. We learned a lot from reader reviews and I can safely say that this edition is the best by far! Congratulations to everyone who's been working hard on the project over the past months - especially Siddhesh, Kirti, and Indrajit! If you are interested in getting a free copy of this book (ebook version), please feel free to post a comment here. I will get back to you quickly!


Disqus comments, 3rd edition, 2 million page views

Just a quick update that most likely no one will read, but here it is anyway:
  • I have switched comment systems, we're now with Disqus. Blogger did a terrible job at preventing spam so I'm hoping I'll get luckier with Disqus. I removed about 2000 spam comments so far.
  • Nginx HTTP Server, 3rd edition is coming up soon! The first draft is complete. After checking out user reviews online we decided that this edition should focus on examples and case studies, rather than standing for the ultimate directive reference or index. The first edition from 2009/2010 was meant as an exhaustive reference that people could use at all times, but several readers complained that the information was readily available online. We never pretended otherwise but we tried to make the documentation in the book more accessible and legible. Hopefully this new edition will prove satisfying to all.
  • 2 million page views on the blog - we're almost there! In a couple of days the amazing milestone of 2,000,000 page views will be reached, I never thought it would go this far when I started the blog a few years back. I haven't posted much lately but that's because I have been busy working on all sorts of projects. I try to post at least 8 to 10 times a year.
Thanks for visiting! Clement


How to fix: jQuery UI progress bar not animating when indeterminate value

Once again I find myself in this situation:
- I run into a small problem
- I google it: can't find a solution
- Try to fix it myself: success
I am hoping that by posting this article I will help out a person or two.

UPDATE: a day later, the problem is back, this post is thereby useless. If you know a proper solution I'm all ears! ;-(

What's the problem?

The jQuery UI progress bar widget is useful in a lot of situations and it's easy to use. When you set its value to "false" (indeterminate/unset), the progress bar animates nicely. The end user feels like something is actually happening. 

The problem I've been having is that the progress bar RANDOMLY doesn't animate in my project. I'm sure I must have done something wrong at some point, but the project is so huge that it would take too long to root out the issue on my end. As a result, my users are under the impression that my application has crashed and they reload the page (while they should just be waiting for the operation to complete).

This is a simple fix. When animated, the progress bar uses the CSS class "ui-progressbar-overlay". This class gets its background from an inline GIF (base 64 encoded within the CSS file).

How to fix it?

Open your jQuery UI CSS file, look for the "ui-progressbar-overlay" class, and replace the inline GIF by an external image (the original image can be found here). 

That's it! Save your files, refresh your cache and voila.

NOTE: this article has been updated. This did not actually solve the problem. I thought it did because it worked for a while, but now it has stopped working again.


Word 2007/2010/2013: attaching a template (containing custom styles) to a document

As I am writing the third edition of Nginx HTTP Server I often find myself in a situation where I have to apply a specific variety of styles, which are supplied to me by my publisher under the form of a .dot file. There are two operations to perform if you want to be able to see all the styles when editing your document:
  • attaching the .dot / .dotm template file to your document
  • editing the settings to display all styles (not only the "recommended" ones)

Attaching a .dot or .dotm file to your document

Open the Options dialog in Word. This is usually achieved by going in the "File" (1) menu then clicking "Options". Then open the Add-ins section at the bottom (2). Select "Templates" (3) and click "Go" (4)

In the window that pops up, click the "Attach..." button to attach your template file. That's the first step.

Editing the settings to display all styles

At the bottom right corner of the style selection box there is a small arrow (1), click it to reveal a floating or side bar with a larger selection of styles. At the bottom of that bar, click the "Options" link (2). A window shows up (3), select the following options:
  • All styles
  • Alphabetical
  • Tick all check boxes
Press OK to apply the changes. There you go! A full list of styles from your imported template.

Search This Blog