tag:blogger.com,1999:blog-5121887034565950112024-03-17T15:14:58.427+08:00Clement Nedelcu's Development JournalMy goal is to find solutions to undocumented or unsolved issues to help people out. Main topics are: Nginx, PHP, MySQL, and Windows.Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.comBlogger64125tag:blogger.com,1999:blog-512188703456595011.post-27476204095041041372022-12-28T13:48:00.003+08:002022-12-28T13:48:22.718+08:00Talk-to-ChatGPT: a Google Chrome extension to actually talk to the AI<p dir="auto" style="background-color: white; box-sizing: border-box; color: #24292f; font-size: 16px; margin-bottom: 16px; margin-top: 0px !important; text-align: justify;"><span style="font-family: inherit;"><span style="box-sizing: border-box; font-weight: var(--base-text-weight-semibold, 600);">Talk-to-ChatGPT</span> is a Google Chrome extension that allows users to talk with the ChatGPT AI using their voice (speech recognition), and listen to the bot's answer with a voice (text-to-speech), rather than just by typing. With this tool, users can speak to the AI and receive spoken responses, making the interaction feel more natural and conversational. This could be useful in a variety of settings where it would be helpful to have a more human-like interaction with an AI.</span></p><div class="separator" style="clear: both; text-align: center;"><iframe allowfullscreen="" class="BLOG_video_class" height="266" src="https://www.youtube.com/embed/vr-6L7Ix9FM" width="320" youtube-src-id="vr-6L7Ix9FM"></iframe></div><br /><p dir="auto" style="background-color: white; box-sizing: border-box; color: #24292f; font-size: 16px; margin-bottom: 16px; margin-top: 0px; text-align: justify;"><span style="font-family: inherit;">After installing the Google Chrome extension, open or reload the ChatGPT page ( <a href="https://chat.openai.com/chat" rel="nofollow" style="background-color: transparent; box-sizing: border-box; text-decoration-line: none;">https://chat.openai.com/chat</a> ) and you should be seeing a 'Start' button on the top right corner of the page. After you click Start, you will be asked for permission to use your Microphone. This is required to enable voice recognition.</span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4Qb2EA71kQwWE5FBY1-iVw1VqXswRkrxptsHVOm7pVWnD2qtxbP4fwyZzfh-gZUpicHTbGhH986WTGD3iQT7Ae_E2HAQUJgW-6sQqDi6wArfbrlmSgR7qkOlk0jy8-r4jibEpksCJMPB2ZqxZYmyUdITuX_qcIrutMjcCsVdXNBsNc8Ckp6xMTMiM/s1301/menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="203" data-original-width="1301" height="100" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4Qb2EA71kQwWE5FBY1-iVw1VqXswRkrxptsHVOm7pVWnD2qtxbP4fwyZzfh-gZUpicHTbGhH986WTGD3iQT7Ae_E2HAQUJgW-6sQqDi6wArfbrlmSgR7qkOlk0jy8-r4jibEpksCJMPB2ZqxZYmyUdITuX_qcIrutMjcCsVdXNBsNc8Ckp6xMTMiM/w640-h100/menu.png" width="640" /></a></div><div><br /></div><div>Get the extension here from the Chrome Web Store: <a href="https://chrome.google.com/webstore/detail/talk-to-chatgpt/hodadfhfagpiemkeoliaelelfbboamlk">https://chrome.google.com/webstore/detail/talk-to-chatgpt/hodadfhfagpiemkeoliaelelfbboamlk</a></div><p> Not to be confused with the other extension with the same name on the Google web store (by Stefan Risic) who used my code without authorization and without crediting me. 😅</p>Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com8tag:blogger.com,1999:blog-512188703456595011.post-18229056606595038172021-06-10T16:08:00.002+08:002021-06-10T16:08:08.915+08:00Page Title Change Detector: a simple Windows program to detect changes in web page titles at regular intervals<div style="text-align: left;"><div>Page Title Change Detector is a tiny Windows utility program written in C# that downloads a web page's source code at a regular interval and alerts you when the title changes.</div></div><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj90xg3IMypVCKUQtugh9hV-O-EZkMafycA8s2syOOofZCPDAd1iRXrv2DQIFpRSmDKhhQq-OsL0jA6DhVWduxt_50wQZMKTywc88H7a7LbTzz4x5sN-ySW0h2t-HEUvVSRtFKvVqDI1W4/s579/nochange.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="310" data-original-width="579" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj90xg3IMypVCKUQtugh9hV-O-EZkMafycA8s2syOOofZCPDAd1iRXrv2DQIFpRSmDKhhQq-OsL0jA6DhVWduxt_50wQZMKTywc88H7a7LbTzz4x5sN-ySW0h2t-HEUvVSRtFKvVqDI1W4/w400-h214/nochange.png" width="400" /></a></div><p>This program offers one simple functionality:</p><p></p><ul style="text-align: left;"><li>Select an interval (in seconds)</li><li>Enter the URL of a web page</li><li>Press 'Start'</li></ul><p></p><p>When you press 'Start', the program will retrieve the page title once and set it as 'Initial page title'. Then it will redownload the same page regularly at the specified interval. If a change is detected, the program stops checking, emits a sound, and displays an alert message box.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHXAgOwPThq_gjyrlCJQD7QE6Oot92eFuW3VKyb7NnI_lBtZrG47FLRc-uILq_a6-Z-_O_N2elFsNee5GjaWN0XgmtpFrNWZ_u-fWBb4txJ2cYmQbL8l3JnaDKEJo1yf_pzoLULzx7MIw/s859/changed.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="493" data-original-width="859" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHXAgOwPThq_gjyrlCJQD7QE6Oot92eFuW3VKyb7NnI_lBtZrG47FLRc-uILq_a6-Z-_O_N2elFsNee5GjaWN0XgmtpFrNWZ_u-fWBb4txJ2cYmQbL8l3JnaDKEJo1yf_pzoLULzx7MIw/w400-h230/changed.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><p style="background-color: white; box-sizing: border-box; margin-bottom: 16px; margin-top: 0px; text-align: left;">Requirements:</p><p style="background-color: white; box-sizing: border-box; margin-bottom: 16px; margin-top: 0px; text-align: left;"></p><ul style="text-align: left;"><li>Microsoft Windows</li><li>.NET Framework 4.5.1+</li><li>Internet connection</li></ul><p></p><p style="background-color: white; box-sizing: border-box; margin-bottom: 16px; margin-top: 0px; text-align: left;">This program does not require any installation. It doesn't save any settings, or file, or anything anywhere. Just download the .exe file and run it.</p></div><p style="background-color: white; box-sizing: border-box; margin-bottom: 16px; margin-top: 0px;"><a href="https://github.com/C-Nedelcu/page-title-change-detector/releases/download/1.0.0/PageTitleChangeDetector.zip" style="background-color: transparent; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; font-size: 16px;" target="_blank">Download by clicking here (.zip)</a></p><div><span style="color: #24292e; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;"><a href="https://github.com/C-Nedelcu/page-title-change-detector/tree/main/PageTitleChangeDetector" target="_blank">The full source is available on GitHub</a> if anyone wants to make improvements or check out the code.</span></div><div><span style="color: #24292e; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji;"><br /></span></div>Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com9tag:blogger.com,1999:blog-512188703456595011.post-35305989682093384812020-03-26T09:21:00.002+08:002020-03-26T10:56:48.234+08:00Top 3 fixes for: Lenovo Yoga S730 shuts down without warning under Windows 10<div dir="ltr" style="text-align: left;" trbidi="on">
I've recently purchased this nice little beast: the <a href="https://psref.lenovo.com/Detail/Yoga/Yoga_S730_13IML?M=81U40018SB" target="_blank">Lenovo Yoga S730-13IML laptop (81U40018SB)</a><br />
<ul style="text-align: left;">
<li>10th-generation Intel Core i7-10510U (4C / 8T, 1.8 / 4.9GHz, 8MB)</li>
<li>16 GB RAM</li>
<li>1 TB SSD</li>
<li>13.3" 1080p screen</li>
<li>3x USB-C ports</li>
<li>42W battery</li>
<li>Fingerprint sensor</li>
</ul>
<div>
<div style="text-align: justify;">
I've been using the standard Windows 10 Home OS that came with it and set the power plan to 'Maximum performance'. I wanted to ensure I'd get my money worth in terms of computing power. I noticed the laptop was getting a bit hot but without any particular issue.</div>
</div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
After a few weeks of use, I started getting <b>unexpected shutdowns</b>. In a single morning three consecutive shutdowns without warning. The screen goes black, power LED goes off, it's like the juice is gone. I can turn it back on immediately but once it gets hot again (or so I suspect) it shuts down again. <span style="text-align: left;">I tried changing settings back and forth and finally found a configuration that doesn't crash anymore, so I thought I would share it with the community. No crash for several days now. Here is what I changed, I recommend you apply all of these together to maximize your chances:</span></div>
</div>
<div>
<br /></div>
<div>
1) enabled '<b>Intelligent cooling</b>' in Lenovo Vantage (not certain this did the trick but I have it enabled anyway)</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX1cNugDZ8cooZZ_UIWjm8e9sPUklDvr8UUz7x7-9o6Rg7r6us-PySGDlAB18pYGn10bQxShmW_MMz0FdX6YLrOAMPdq7pGnqxS1dUw8OOBmYwc0z8BUvJhDFWeqctzvBAtD6hnyghbDQ/s1600/icool.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="921" data-original-width="1324" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX1cNugDZ8cooZZ_UIWjm8e9sPUklDvr8UUz7x7-9o6Rg7r6us-PySGDlAB18pYGn10bQxShmW_MMz0FdX6YLrOAMPdq7pGnqxS1dUw8OOBmYwc0z8BUvJhDFWeqctzvBAtD6hnyghbDQ/s320/icool.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
2) my <b>battery settings</b> are as follow (again not certain that this is what did the trick but I'm showing you anyway):</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcdkRF-Rfm8pD3lhXjG4HrbWhyuJmo5AV9JudY8ffD1WUfm0Z6-8JC2Yhh-lKYPF2FzvjHRC8qVlTGwezfvvKnWWVeDmXUX2nWbn2Z6fapAeT6VkH9X5tZV1bejvTSj1H8RwUbZ2D1aPc/s1600/batt.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="383" data-original-width="1234" height="99" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcdkRF-Rfm8pD3lhXjG4HrbWhyuJmo5AV9JudY8ffD1WUfm0Z6-8JC2Yhh-lKYPF2FzvjHRC8qVlTGwezfvvKnWWVeDmXUX2nWbn2Z6fapAeT6VkH9X5tZV1bejvTSj1H8RwUbZ2D1aPc/s320/batt.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
3) the Windows power plan: I think this is the most important setting here. <b>Do NOT set it to 'best performance' on the far right</b>. I changed it back to 'Better performance' several days ago and haven't had a crash since.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjblVjs3w21p5vqgWTT1AB9oxEYSgpRY3GG9STdnGAVAUk_Vwq3DHNTneM80A5uXC-V-VhhwlhTrDaw8aw4fr-mDllkyb-AmRQ09A2_0GTknKYI8vIulVUSMgSz2nLn9VISKfZP3tnV3E/s1600/pow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="318" data-original-width="447" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjblVjs3w21p5vqgWTT1AB9oxEYSgpRY3GG9STdnGAVAUk_Vwq3DHNTneM80A5uXC-V-VhhwlhTrDaw8aw4fr-mDllkyb-AmRQ09A2_0GTknKYI8vIulVUSMgSz2nLn9VISKfZP3tnV3E/s320/pow.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
This reminds me of an issue I had with the Macbook Air under Windows (with Bootcamp) it would crash if I <i>didn't </i>set it to 'best performance', so kind of the opposite of what's happening here! Anyway, been monitoring CPU temperatures and it seems like my Yoga was really getting too hot under the 'Best performance' plan, so that may explain the issue. Franckly, performance wise I don't see much difference with the new plan I'm using. Hope this helped someone.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
If this did not help you, maybe check this article <a href="https://forums.tomsguide.com/faq/how-to-solve-random-shutdown-issues-in-lenovo-laptops.188341/" target="_blank">from Tom's hardware about Lenovo computers crashing at random</a>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Other than that I'm quite happy with this new laptop overall! Very sleek design, lightweight, and still quite the powerhouse. Good job Lenovo!</div>
</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com6tag:blogger.com,1999:blog-512188703456595011.post-24660369031791350292019-03-28T07:49:00.000+08:002019-03-28T07:49:26.122+08:00Singap.FR: une communauté en ligne pour les touristes et expatriés francophones<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Un petit coup de main pour un ami: je fais passer le message. Le site <a href="https://singap.fr/">Singap.FR</a> vient d'ouvrir: il s'agit d'un site communautaire dédiée à la diaspora française et francophone de Singapour, ayant également un but informatif pour les touristes visitant ou souhaitant visiter Singapour.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhprEOQj45QHPPTXAeSSdjp3lANPAjYA45hSef3u-ucE8AP5hbxoZTlwzzlhQqu875ZgKli1WD7e_YQdslzydm2Q9q3EXrVLz6PMjsX0-fjSo0uKPHEglHsBkDTI1tzQQ5mg-IzQrxRUlM/s1600/Screenshot_2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="851" data-original-width="1386" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhprEOQj45QHPPTXAeSSdjp3lANPAjYA45hSef3u-ucE8AP5hbxoZTlwzzlhQqu875ZgKli1WD7e_YQdslzydm2Q9q3EXrVLz6PMjsX0-fjSo0uKPHEglHsBkDTI1tzQQ5mg-IzQrxRUlM/s320/Screenshot_2.jpg" width="320" /></a></div>
<br />
<div style="text-align: justify;">
Cette <a href="https://singap.fr/">communauté française de Singapour</a>, riche de 15 000 résidents permanents et de nombreux touristes, se dote donc d'un vrai forum de discussion ouvert à tous, d'une page Facebook pour relayer ses articles, et même d'un <a href="https://singap.fr/forums/les-condos-de-singapour.48/">catalogue des condos/résidences privées</a> de Singapour, pour ceux qui cherchent plus d'informations ou souhaitent donner leur avis sur une résidence. Bon courage à mon ami Jimmy A. dans cette grande aventure.</div>
</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com3tag:blogger.com,1999:blog-512188703456595011.post-16046338023229795292018-09-29T11:22:00.002+08:002018-09-29T11:24:53.927+08:00How to fix: Nginx proxy or fastcgi cache always MISS or EXPIREDI've recently had an issue with my Nginx setup: it wasn't caching or serving cached pages properly. Every time I would visit, I'd get "MISS" or "EXPIRED".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr5G0WMRgHAYFFS8qekMOSyhrCJnyqXy6rtRoJKbdiqGVns-Ux9-rSjyjOaaVSx4jFlU8dPq414zqlBuQWPZQVBtDdyyydhgpOBhd3Bz-1GfgqXvrnZAqjDx1zSVK5SQwM8gNi3_4EE_E/s1600/Screenshot_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="241" data-original-width="481" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr5G0WMRgHAYFFS8qekMOSyhrCJnyqXy6rtRoJKbdiqGVns-Ux9-rSjyjOaaVSx4jFlU8dPq414zqlBuQWPZQVBtDdyyydhgpOBhd3Bz-1GfgqXvrnZAqjDx1zSVK5SQwM8gNi3_4EE_E/s320/Screenshot_2.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
What I found online is that you have to instruct Nginx to ignore browser request headers relative to caching, therefore allowing Nginx to determine whether it should serve cache, all by itself.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
This is done by inserting the following directive:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both;">
<span style="font-family: Courier New, Courier, monospace;"><i># ignore headers to let Nginx control its own cache</i></span></div>
<div class="separator" style="clear: both;">
<span style="font-family: Courier New, Courier, monospace;"><b>fastcgi_ignore_headers</b> Cache-Control Expires;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
However, I already had this in my configuration and it wasn't helping.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
After investigating the issue, I determined that my PHP scripts were updating cookies at every request. Nginx was forced to execute the PHP scripts via FastCGI (ie. not serving them from cache) because the cookie data had changed. When PHP sets a cookie, Nginx will not hit the cache, which is normal behavior. I wouldn't recommend changing this behavior. What I did is fix my PHP scripts so that they wouldn't update cookies at every request. Once I did that, I started hitting the cache again!</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibuKfZfcHBC9Z1mq9ddFHfOxW5_zOg89OedF8fIuO-eJLXdl66DQxar-ezwiH2l8BvIbh37m9YRyIF36pKM-BK47ABEfyQLreQsQG7u4PuTM4Oj4Ktrkm2IFc76kA8OhkUNy9xd7oHdJc/s1600/Screenshot_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="307" data-original-width="715" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibuKfZfcHBC9Z1mq9ddFHfOxW5_zOg89OedF8fIuO-eJLXdl66DQxar-ezwiH2l8BvIbh37m9YRyIF36pKM-BK47ABEfyQLreQsQG7u4PuTM4Oj4Ktrkm2IFc76kA8OhkUNy9xd7oHdJc/s320/Screenshot_1.png" width="320" /></a></div>
<br />
One last thing: if you turn off fastcgi or proxy buffering, caching may not work properly, so make sure buffering is on (it should be on by default).Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com4tag:blogger.com,1999:blog-512188703456595011.post-52863926460410132972018-05-03T13:11:00.000+08:002018-05-03T13:24:07.331+08:00Clickatell vs MessageBird vs Nexmo vs Plivo vs Tropo vs Twilio: outbound SMS pricing comparison<div style="text-align: justify;">
<b>DISCLAIMER</b>: I am not affiliated in any way to any of those companies. I'm an independent software developer. This article is based on pricing data collected on May 2018.</div>
<br />
<div style="text-align: justify;">
As I was looking for a provider to send SMS internationally from a web application (one-way), I was recommended a variety of services by friends and colleagues. My main concern was the pricing: which of them would offer me the cheapest rates in the most countries? Obviously the answer isn't that simple, so I decided to collect pricing information from major providers to compare. I tried including <b>SMSGlobal </b>in this comparison but they wouldn't provide me with a full list so I had to exclude them.</div>
<div style="text-align: justify;">
<br /></div>
<h2 style="text-align: justify;">
Methodology</h2>
<div style="text-align: justify;">
There are three important pieces of information that you absolutely need to grasp before you continue reading this article:</div>
<br />
<div style="text-align: justify;">
• <span style="text-align: justify;">The prices I have collected </span><b style="text-align: justify;">do not include bulk discounts</b><span style="text-align: justify;">. Most, if not all providers offer such discounts if you talk to their sales department. The rates I have retained in my comparison are standard rates and have been collected off the provider's sites. In half the cases I had to obtain the list by talking to the sales department directly - I asked for standard rates for low volumes.</span><br />
<span style="text-align: justify;"><br /></span></div>
<div style="text-align: justify;">
<span style="text-align: justify;">• <span style="text-align: justify;">Some providers offer a flat rate per country, while others offer </span><b style="text-align: justify;">different rates based on the destination carrier</b><span style="text-align: justify;">. In order to establish a comparison that would be as fair as possible, for those operators that have different rates per carrier I compared prices based on </span><span style="text-align: justify;">AVG/MIN/MAX</span><span style="text-align: justify;">: AVG being the average rate for all carriers combined, MIN being the rate of the cheapest carrier, and MAX being the rate of the most expensive carrier.</span></span><br />
<span style="text-align: justify;"><span style="text-align: justify;"><br /></span></span></div>
<div style="text-align: justify;">
<span style="text-align: justify;">• <span style="text-align: justify;">This article compares providers </span><b style="text-align: justify;">solely based on pricing</b><span style="text-align: justify;">. But keep in mind that the pricing isn't the only thing that matters to select a provider: delivery rates, reliability, customer support, API, documentation, etc. can be equally important.</span></span></div>
<br />
<h2>
Contenders</h2>
The contenders are: (listed in alphabetical order)<br />
<br />
<div style="text-align: justify;">
1) <a href="https://www.clickatell.com/" target="_blank"><b>Clickatell</b></a>: based in South Africa. Flat rates. Pricing sheet obtained from sales department on May 2nd, 2018. Prices were given in USD.</div>
<br />
<div style="text-align: justify;">
2) <a href="http://messagebird/" target="_blank"><b>Messagebird</b></a>: based in the Netherlands (Europe). Flat rates. Pricing sheet obtained from sales department on April 30th, 2018. Prices were given in USD.</div>
<br />
<div style="text-align: justify;">
3) <a href="https://www.nexmo.com/" target="_blank"><b>Nexmo</b></a>: originally based in France (Europe) but now owned by Vonage (USA). Flat rates. Pricing sheet obtained from sales department on May 1st, 2018. Prices were given in EUR, converted to USD based on EUR/USD exchange rate from XE.com on May 2nd, 2018.</div>
<br />
<div style="text-align: justify;">
4) <a href="https://www.plivo.com/" target="_blank"><b>Plivo</b></a>: based in the USA. Carrier-dependent rates. Pricing sheet obtained from website on May 2nd, 2018. Prices given in USD.</div>
<br />
<div style="text-align: justify;">
5) <a href="https://www.tropo.com/" target="_blank"><b>Tropo</b></a>: owned by Cisco, based in the USA. Carrier-dependent rates. Pricing sheet obtained from website on May 2nd, 2018. Prices given in USD.</div>
<br />
<div style="text-align: justify;">
6) <a href="https://www.twilio.com/" target="_blank"><b>Twilio</b></a>: based in the USA. Carrier-dependent rates. Pricing sheet obtained from website on May 2nd, 2018. Prices given in USD.</div>
<br />
<div style="text-align: justify;">
I collected all data from these 6 providers and combined it into a single SQL table. I spent a good amount of time fixing the name of countries to get a coherent list - my apologies if any mistakes were made as I'm not an expert in geopolitics. I also deleted a few rare countries that were covered by only 1 provider. Then I built an Excel file and determined the provider that offers the cheapest rates for each country.</div>
<div style="text-align: justify;">
<br /></div>
<h2 style="text-align: justify;">
Results</h2>
<div style="text-align: justify;">
The final Excel table looks like this (download link can be found at the bottom of the article):</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglNvL_IWhCXpUuSpQzRUjTCu8pCtYNPpfrfTHBBXmbUpWH5nxzO_aUOz2aktRQYm2ev38wySmeQY1UUVRdTi518aXsI8ZnJN2j3XArSvivmphVsGZhxHk6W2Vs06wiRDxvi8fJzVXdZNk/s1600/Screenshot_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="456" data-original-width="1599" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglNvL_IWhCXpUuSpQzRUjTCu8pCtYNPpfrfTHBBXmbUpWH5nxzO_aUOz2aktRQYm2ev38wySmeQY1UUVRdTi518aXsI8ZnJN2j3XArSvivmphVsGZhxHk6W2Vs06wiRDxvi8fJzVXdZNk/s400/Screenshot_2.png" width="400" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The providers that offer the best rates are... *drum rolls*:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIVYDGAreW-UdqSLOTwRaIdzRsp2ymyNyPIy8O1eO9fAwQuLvFmfr07f1qtOkKP996PCawYaP5f8GaxqbHInNYsLJUPoK19VuTsdjbuMcS9hP95VYYvQ7LaWRj2mNs88gBHEom1aOY9r0/s1600/Screenshot_3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="173" data-original-width="381" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIVYDGAreW-UdqSLOTwRaIdzRsp2ymyNyPIy8O1eO9fAwQuLvFmfr07f1qtOkKP996PCawYaP5f8GaxqbHInNYsLJUPoK19VuTsdjbuMcS9hP95VYYvQ7LaWRj2mNs88gBHEom1aOY9r0/s320/Screenshot_3.png" width="320" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>1. Messagebird (flat rates)</b></div>
<div>
They offer the cheapest rates in:</div>
<div>
• 134 countries if we look at flat or average carrier rates of competitors</div>
<div>
• 122 countries if we look at flat or minimum carrier rates of competitors</div>
<div>
• 137 countries if we look at flat or maximum carrier rates of competitors</div>
<div>
<br /></div>
<div>
<div style="text-align: justify;">
<b>2. Tropo (carrier-dependent rates)</b></div>
<div>
They offer the cheapest rates in:</div>
<div>
• 50 countries if we look at flat or average carrier rates of competitors</div>
<div>
• 44 countries if we look at flat or minimum carrier rates of competitors</div>
<div>
• 50 countries if we look at flat or maximum carrier rates of competitors</div>
<div>
<br /></div>
</div>
<div>
<div style="text-align: justify;">
<b>3. Clickatell (flat rates)</b></div>
<div>
They offer the cheapest rates in:</div>
<div>
• 23 countries if we look at flat or average carrier rates of competitors</div>
<div>
• 20 countries if we look at flat or minimum carrier rates of competitors</div>
<div>
• 23 countries if we look at flat or maximum carrier rates of competitors</div>
</div>
<div>
<br /></div>
<div>
<div>
<div>
<div style="text-align: justify;">
<b>4. Plivo (</b><b>carrier-dependent rates</b><b>)</b></div>
<div>
They offer the cheapest rates in:</div>
<div>
• 19 countries if we look at flat or average carrier rates of competitors</div>
<div>
• 37 countries if we look at flat or minimum carrier rates of competitors</div>
<div>
• 16 countries if we look at flat or maximum carrier rates of competitors</div>
</div>
<div>
<br /></div>
</div>
</div>
<div>
<div>
<div>
<div style="text-align: justify;">
<b>5. Twilio (carrier-dependent rates)</b></div>
<div>
They offer the cheapest rates in:</div>
<div>
• 2 countries if we look at flat or average carrier rates of competitors</div>
<div>
• 8 countries if we look at flat or minimum carrier rates of competitors</div>
<div>
• 2 countries if we look at flat or maximum carrier rates of competitors</div>
</div>
<div>
<br /></div>
</div>
</div>
<div>
<div>
<div>
<div style="text-align: justify;">
<b>6. Nexmo (flat rates)</b></div>
<div>
They offer the cheapest rates in:</div>
<div>
• 1 country if we look at flat or average carrier rates of competitors</div>
<div>
• 1 country if we look at flat or minimum carrier rates of competitors</div>
<div>
• 1 country if we look at flat or maximum carrier rates of competitors</div>
</div>
<div>
<br /></div>
</div>
</div>
<h2>
Downloads</h2>
<div>
The Excel file with the full list of countries is available for <a href="http://cnedelcu.ovh/sms_pricing_comparison.xlsx" target="_blank">download here</a></div>
<div>
<br /></div>
<div>
You can also download the <a href="http://cnedelcu.ovh/sms_source.7z" target="_blank">source code</a> for my script, the file contains:</div>
<div>
• The original CSV/PDF/Excel files from providers with the rates</div>
<div>
• Database dump with the SQL table containing properly imported and reformatted data</div>
<div>
<div>
• The source code of my script. Bear in mind this script was written over 2 hours, I am publishing it for reasons of transparency, so please no judging of the dirty code (PHP 5.6).</div>
</div>
<div>
<br /></div>
<div>
If you notice any inconsistency in my data, script, or methodology please comment and I will do my best to make the necessary fixes.</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com2tag:blogger.com,1999:blog-512188703456595011.post-18654128457033711362018-02-21T15:45:00.001+08:002018-02-21T15:45:48.843+08:00Nginx HTTP Server - 4th edition now available<div style="text-align: justify;">
Thanks to the amazing work of <a href="https://blog.martinfjordvald.com/" target="_blank">Martin Fjordvald</a>, the 4th edition of <a href="https://www.packtpub.com/virtualization-and-cloud/nginx-http-server-fourth-edition" target="_blank">Nginx HTTP Server</a> (which was, at the time of the 1st edition, the first-ever book about Nginx) is as of today available for purchase in libraries and online. Congratulations Martin!</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.packtpub.com/virtualization-and-cloud/nginx-http-server-fourth-edition" target="_blank"><img border="0" data-original-height="605" data-original-width="491" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjERJ27i41BaB_P3KGSWJYbR3G915YolDNgQ7WNi3MDPAU-AGKBpT2nj0UDN8C3PjLRkY3ZlS8wWJ31Td3K_XvIsFt0a3b0UNHM60hGae28y3pMdTmHTQmRk2sU3jnQELSWRL43Kzc6oQQ/s320/nginx4thedition.png" width="259" /></a></div>
<br />
<div style="text-align: justify;">
This book is a detailed guide to setting up Nginx in ways that correspond to actual production situations: as a standalone server, as a reverse proxy, interacting with applications via FastCGI, and more. In addition, this complete direct reference will be indispensable at all stages of the configuration and maintenance processes. This book mainly targets the most recent version of Nginx (1.13.2) and focuses on all the new additions and improvements, such as support for HTTP/2, improved dynamic modules, security enhancements, and support for multiple SSL certificates. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This book is the perfect companion for both Nginx beginners and experienced administrators. For beginners, it will take you through the complete process of setting up this lightweight HTTP server on your system and configuring its various modules so that it does exactly what you need quickly and securely. For more experienced administrators, this book provides different approaches that can help you make the most of your current infrastructure.</div>
<br />Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com2tag:blogger.com,1999:blog-512188703456595011.post-40801981089350461752018-02-14T08:58:00.000+08:002018-02-14T08:58:10.078+08:00How to fix: Outlook on iOS/iPhone: "No Internet Connection"<div style="text-align: justify;">
Microsoft Outlook is probably one of the best (if not <b>the</b> best) email client for iOS to date. Sadly, you may run into a random annoying problem which basically renders the application useless: it displays a message saying "<b>No internet connection</b>", at which point you can't receive or send emails anymore. The number of people having this issue is incredibly high, as I discovered when it happened to me yesterday:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWzgk6eV-nXRs9bocQQYj27eVOuvmC8zLu2v3mfhkN-3hxtngHvYSTivf4N6HjyLwShkSAqmFO2qzQ_vq-gkEbTs5657eyjK6WNzDfgDYScSYc_vvsy7StV5AbeH3qAdHViohow00he_c/s1600/Screenshot_1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="585" data-original-width="827" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWzgk6eV-nXRs9bocQQYj27eVOuvmC8zLu2v3mfhkN-3hxtngHvYSTivf4N6HjyLwShkSAqmFO2qzQ_vq-gkEbTs5657eyjK6WNzDfgDYScSYc_vvsy7StV5AbeH3qAdHViohow00he_c/s400/Screenshot_1.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
After reading all of these posts and many more, there did not appear to be a particular solution for this. I had already checked the following:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>my Internet was of course working properly, on both WiFi and 4G</li>
<li>I made sure to allow data/internet usage for the Outlook app</li>
<li>I made sure my email accounts were working properly (they work fine on the Outlook desktop app & web)</li>
<li>I tried enabling or disabling push notifications but that did not help</li>
<li>I tried to use the 'reset account' functionality in the Outlook app settings for each of the accounts</li>
<li>I made sure I had enough storage space left on device, which I did, over 10 GB left. And the Outlook app itself was only using about 200 MB.</li>
</ul>
<br />
None of the above proved useful.<br />
<br />
<h3>
The only solution?</h3>
Eventually, here is what I did to get the app to work again:<br />
<br />
<ol>
<li>Removed all my accounts one by one from the Outlook app</li>
<li>Went to the iOS settings, "Storage & icloud" settings, manage storage, selected the 'Outlook' app and tapped 'Delete' in order to delete the application from my iPhone</li>
<li>I re-downloaded the application from the App Store</li>
<li>I set up my accounts into the app again</li>
</ol>
<br />
<div style="text-align: justify;">
Thankfully, the 'no internet connection' message hasn't shown up again until now. It's really surprising that considering the amount of people having this issue (not even recently) Microsoft have yet to address the issue properly. If someone is reading this, my iPhone is running the latest version of iOS 10, and I always keep my apps up to date so I had the latest version of Outlook for iOS installed at the time of writing this article.</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com43tag:blogger.com,1999:blog-512188703456595011.post-19349689238278732712017-01-04T17:31:00.004+08:002017-01-04T17:31:40.652+08:00VPNAutoConnect 1.0 for Windows: automatically connect and reconnect to a VPN<div dir="ltr" style="text-align: left;" trbidi="on">
I am releasing a handy little tool I have been working on called <b>VPNAutoConnect</b>. It does a couple of simple things Windows won't let you do (at least not easily):<br />
- automatically reconnects to a VPN when the connection is lost<br />
- connects to a VPN on computer start-up<br />
- logs VPN connection events for debugging<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK3vfw3QyaEOO7mbMd75K3fv_a6Lb6AL3FdkMVE0ebQE9LeN5xs4AGgHaNFvg2CUgg0EdGT782J0bsMPs2bH0S4XRqDlagEq4Y-8HFvFQ_7uShz4yqurgefpLcKfsqGssBNn0FVU59A5w/s1600/Image2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="209" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK3vfw3QyaEOO7mbMd75K3fv_a6Lb6AL3FdkMVE0ebQE9LeN5xs4AGgHaNFvg2CUgg0EdGT782J0bsMPs2bH0S4XRqDlagEq4Y-8HFvFQ_7uShz4yqurgefpLcKfsqGssBNn0FVU59A5w/s400/Image2.png" width="400" /></a></div>
<br />
<div style="text-align: justify;">
I designed this tool because I have been using a VPN for a while but I randomly get disconnected. I wish Windows offered an option to automatically reconnect but strangely there isn't an easy, straightforward way to do that (as of today). With this tool, not only my VPN connection is started when I boot my computer, but it always reconnects automatically after I get those random disconnects.</div>
<br />
This is a free open source program designed with Visual Studio Community 2015. It requires the .NET framework 4.5.2, and it makes uses of the DotRas library.<br />
- <b>Download program from here</b>: <a href="https://filetrip.net/files/vpnautoconnect-1.0.zip">vpnautoconnect-1.0.zip</a> (<a href="https://filetrip.net/view?SZjpB7MrrC" target="_blank">SHA1</a>)<br />
- <b>Download sources from here</b>: <a href="https://filetrip.net/files/vpnautoconnect-1.0.src.zip">vpnautoconnect-1.0.src.zip</a> (<a href="https://filetrip.net/view?SZjpB7MrrC" target="_blank">SHA1</a>)<br />
NB: use at your own risks. Tested under Windows 8.1 only.<br />
<br />
There are 3 command-line arguments that control the behavior of the program, allowing you to achieve automatic VPN connections on computer startup for example.<br />
<span style="font-family: Courier New, Courier, monospace;">--quiet</span>: enables the 'do not display ballon tips' option<br />
<span style="font-family: Courier New, Courier, monospace;">--timer=N</span>: sets the timer to N seconds<br />
<span style="font-family: Courier New, Courier, monospace;">--connection=XXX</span>: automatically connect/reconnects to XXX when the application starts. If your connection has spaces in its name, try using quotes (ie. <span style="font-family: Courier New, Courier, monospace;">--connection="My VPN"</span>)</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com1tag:blogger.com,1999:blog-512188703456595011.post-31178358111009439432016-12-18T11:49:00.002+08:002018-01-04T15:06:47.242+08:00Simple VPN autoconnect for Windows 8 and 10<div style="text-align: justify;">
Since Windows 7, for some reason VPN support in new Windows versions has annoyingly decreased in quality. You can't create shortcuts to VPNs on the desktop or in the start menu anymore; you can't set up a VPN connection to automatically connect on start up; and with Windows 10 there is even a bug (at the time of writing this article) that makes you click on another connection item in the list before the Connect button appears.</div>
<br />
The simplest way to achieve <b>automatic VPN connection on computer start-up</b> is to create a batch/cmd file with the following command:<br />
<span style="color: #990000; font-family: "courier new" , "courier" , monospace;"><b>rasdial "VPN Connection" username password</b></span><br />
<br />
Where:<br />
- <i>rasdial </i>is the name of the command-line utility that will perform the connection<br />
- replace "VPN Connection" by the actual name of the VPN connection<br />
- replace username by your actual VPN user name<br />
- replace password by your actual VPN password<br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If you want the VPN connection to be started when you log on, simply place this batch script into your startup folder: press Win+R to run 'shell:startup', this will open a folder in which you can place programs or shortcuts to be ran on startup.<br />
<br />
<b><span style="color: red;">UPDATE</span></b>: or use this tool - <a href="http://cnedelcu.blogspot.com/2017/01/vpnautoconnect-for-windows-automatically-reconnect-vpn.html" target="_blank">VPN AutoConnect</a></div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com1tag:blogger.com,1999:blog-512188703456595011.post-46022189268059773212016-09-06T12:15:00.001+08:002016-09-06T12:18:30.051+08:00Solution for "DOMException: Failed to load because no supported source was found" error in Chrome with HTML5 media API<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
After updating Chrome to release 53 this week, my web application was no longer able to use the media API to capture video with a webcam. This is the third time that I am forced to update my code due to changes in Chrome... this is getting a little annoying!<br />
<br />
The error message I was getting in my javascript console is:<br />
DOMException: Failed to load because no supported source was found<br />
<br />
I'll keep it short. The problem was the way I set the source of my media element.<br />
I was setting the source like this:<br />
<br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;">navigator.getUserMedia(videoObj, function(stream) {</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"> CaptureImageStream = stream;</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"> CaptureImageVideo.src = <b style="background-color: yellow;">stream</b>;</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"> CaptureImageVideo.play();</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;">}, errBack);</span><br />
<br />
It seems like this is no longer supported. I changed it to this and it now works again:<br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><br /></span>
<span style="color: #990000; font-family: Courier New, Courier, monospace;">navigator.getUserMedia(videoObj, function(stream) {</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"> CaptureImageStream = stream;</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"> CaptureImageVideo.src = <b style="background-color: yellow;">window.URL.createObjectURL(stream)</b>;</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"> CaptureImageVideo.play();</span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;">}, errBack); </span><br />
<br />
I hope this helps!<br />
Clement</div>
</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com12tag:blogger.com,1999:blog-512188703456595011.post-44200466955964663982016-07-28T16:28:00.003+08:002016-07-28T16:28:45.708+08:00Nginx: set up a LetsEncrypt SSL certificate with auto-renewal in 3 easy steps<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
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 <a href="https://www.letsencrypt.org/" target="_blank">LetsEncrypt</a>, 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).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let's get straight to the point. The three steps are summarized here:</div>
<div style="text-align: justify;">
1) Download LetsEncrypt (the application) for your Linux server</div>
<div style="text-align: justify;">
2) Run the application to generate a certificate for your domain and set up the monthly auto-renew cron job</div>
<div style="text-align: justify;">
3) Add the certificate to your Nginx configuration.</div>
<div style="text-align: justify;">
<br /></div>
<h3 style="text-align: justify;">
Step 1: download LetsEncrypt</h3>
<div style="text-align: justify;">
Install git if you haven't done so yet:</div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"># apt-get install git</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Use git to get the application and store it somewhere (ie: /root/temp)</div>
<div style="text-align: left;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"># git clone https://github.com/letsencrypt/letsencrypt /root/temp/letsencrypt</span></div>
<div style="text-align: left;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><br /></span></div>
<h3 style="text-align: left;">
Step 2: generate your certificate</h3>
<div>
<div style="text-align: justify;">
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.</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
So run the following command to generate the certificate:</div>
<div>
<div style="text-align: left;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"># /root/temp/letsencrypt/letsencrypt-auto certonly -a webroot --agree-tos --renew-by-default --webroot-path=<b>XXX </b>-d <b>YYY</b></span></div>
</div>
<div style="text-align: left;">
Where: <b>XXX </b>is the full path to your website's root folder. For example <span style="font-family: Courier New, Courier, monospace;">/home/www/website.com</span></div>
<div style="text-align: justify;">
And <b>YYY</b> is the domain name or subdomain name (ie: website.com, or something.website.com)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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, <b>we can set up a simple cron job to be ran monthly</b> (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).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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:</div>
<div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;">#!/bin/sh</span></div>
</div>
<div style="text-align: justify;">
And then put the exact same command you ran before to generate the certificate. You can also add <span style="font-family: Courier New, Courier, monospace;">>>/root/temp/certificate-update.log</span> 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).</div>
<div style="text-align: justify;">
<br /></div>
<h3 style="text-align: justify;">
Step 3: configuring Nginx</h3>
<div style="text-align: justify;">
After running the command that generates the certificates, you should have several files in <span style="color: #990000; font-family: Courier New, Courier, monospace;">/etc/letsencrypt/live/website.com/</span> (replace website.com by your own domain). We are going to need just two of them for Nginx: fullchain.pem and privkey.pem.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The beginning of your server block should look like this:</div>
<div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;">server {</span></div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>server_name <u>www.website.com</u> <u>website.com</u>;</span></div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>listen 443 ssl;</span></div>
</div>
<div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span><b>ssl_certificate /etc/letsencrypt/live/<u>website.com</u>/fullchain.pem;</b></span></div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>ssl_certificate_key /etc/letsencrypt/live/<u>website.com</u>/privkey.pem;</b></span></div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>ssl_session_cache shared:SSL:20m;</b></span></div>
</div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>[...]</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Don't forget that last line, otherwise Safari and iOS devices won't be able to visit your website (see my <a href="http://cnedelcu.blogspot.hk/2016/07/nginx-and-letsencrypt-ssl-certificate-safari-ios-problem.html" target="_blank">recent blog post about it</a>). 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.</div>
</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-52050654077912159402016-07-27T10:06:00.000+08:002016-07-27T10:07:28.285+08:00Nginx and LetsEncrypt SSL certificate problem with iOS and Safari (fixed)<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0H_ElPdnz4qk0YtLx9sKyIlIKRlxIanZoNkG8BabEhA0VhMzz-TTTSgoOODv4Bf8EZC0GLbyHPC-rzu7zEQ4VAfnekEfMSyRaCKIaJEHgKmg8_wj_HNp5DsIL_31d06FMtrS6QRwmFyU/s1600/454918315757603437.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0H_ElPdnz4qk0YtLx9sKyIlIKRlxIanZoNkG8BabEhA0VhMzz-TTTSgoOODv4Bf8EZC0GLbyHPC-rzu7zEQ4VAfnekEfMSyRaCKIaJEHgKmg8_wj_HNp5DsIL_31d06FMtrS6QRwmFyU/s320/454918315757603437.jpg" width="179" /></a></div>
<div>
<br /></div>
<div style="text-align: justify;">
The error reads: "<b>Safari cannot open the page because the network connection was reset. The server may be busy</b>". After trying to sort out the problem for hours and Googling up the error everywhere, I finally stumbled upon <a href="https://community.letsencrypt.org/t/apple-safari-browsers-fail-to-connect/3731" target="_blank">this forum thread</a>. Well thank you Mr. Duckson because that really did fix the problem!</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The solution: in your <i>server { ... }</i> block, insert the <a href="http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_cache" target="_blank">ssl_session_cache</a> directive with whatever value you deem fit. Example from Nginx documentation: <b>ssl_session_cache shared:SSL:10m</b>;</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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!</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-91817679752895232942016-03-08T11:48:00.000+08:002016-03-08T12:03:32.543+08:00HTML5 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.<br />
<br />
<b><u>Here was my code to initialize the capture canvas:</u></b><br />
<br />
<pre style="background-color: white; font-family: 'Courier New';"><pre style="font-family: 'Courier New';"><span style="color: navy; font-weight: bold;">function </span><span style="font-style: italic;">CaptureImageBeginCapture</span>() {
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageCanvas </span>= <span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureCanvas"</span>)[<span style="color: blue;">0</span>];
<span style="color: navy; font-weight: bold;">var </span><span style="color: #458383;">videoObj </span>= { <span style="color: #660e7a; font-weight: bold;">"video"</span>: <span style="color: navy; font-weight: bold;">true </span>},
<span style="font-style: italic;">errBack </span>= <span style="color: navy; font-weight: bold;">function</span>(error) {
<span style="color: #660e7a; font-weight: bold;">console</span>.<span style="color: #7a7a43;">log</span>(<span style="color: green; font-weight: bold;">"Video capture error: "</span>, error.<span style="color: #660e7a; font-weight: bold;">code</span>);
};
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo </span>= <span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCapturePreviewFrame"</span>)[<span style="color: blue;">0</span>];
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageContext </span>= <span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageCanvas</span>.<span style="color: #7a7a43;">getContext</span>(<span style="color: green; font-weight: bold;">"2d"</span>);
<span style="color: grey; font-style: italic;">// Put video listeners into place</span><span style="color: grey; font-style: italic;"> </span><span style="color: navy; font-weight: bold;">if</span>(<span style="color: #660e7a; font-weight: bold;">navigator</span>.getUserMedia) { <span style="color: grey; font-style: italic;">// Standard</span><span style="color: grey; font-style: italic;"> </span><span style="color: #660e7a; font-weight: bold;">navigator</span>.getUserMedia(<span style="color: #458383;">videoObj</span>, <span style="color: navy; font-weight: bold;">function</span>(stream) {
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageStream </span>= stream;
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>.<span style="color: #660e7a; font-weight: bold;">src </span>= stream;
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>.<span style="color: #7a7a43;">play</span>();
}, <span style="font-style: italic;">errBack</span>);
} <span style="color: navy; font-weight: bold;">else if</span>(<span style="color: #660e7a; font-weight: bold;">navigator</span>.webkitGetUserMedia) { <span style="color: grey; font-style: italic;">// WebKit-prefixed</span><span style="color: grey; font-style: italic;"> </span><span style="color: #660e7a; font-weight: bold;">navigator</span>.webkitGetUserMedia(<span style="color: #458383;">videoObj</span>, <span style="color: navy; font-weight: bold;">function</span>(stream){
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageStream </span>= stream;
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>.<span style="color: #660e7a; font-weight: bold;">src </span>= <span style="color: #660e7a; font-weight: bold;">window</span>.webkitURL.createObjectURL(stream);
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>.<span style="color: #7a7a43;">play</span>();
}, <span style="font-style: italic;">errBack</span>);
}
<span style="color: navy; font-weight: bold;">else if</span>(<span style="color: #660e7a; font-weight: bold;">navigator</span>.mozGetUserMedia) { <span style="color: grey; font-style: italic;">// Firefox-prefixed</span><span style="color: grey; font-style: italic;"> </span><span style="color: #660e7a; font-weight: bold;">navigator</span>.mozGetUserMedia(<span style="color: #458383;">videoObj</span>, <span style="color: navy; font-weight: bold;">function</span>(stream){
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageStream </span>= stream;
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>.<span style="color: #660e7a; font-weight: bold;">src </span>= <span style="color: #660e7a; font-weight: bold;">window</span>.URL.createObjectURL(stream);
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>.<span style="color: #7a7a43;">play</span>();
}, <span style="font-style: italic;">errBack</span>);
}
}</pre></pre><div><b><u>And this code was used to react to the pressing of a "Capture" button which froze the image and then saved it.</u></b></div><div style="font-family: 'Courier New';"><pre style="font-family: 'Courier New';"><span style="color: grey; font-style: italic;">// Snapping up the picture</span><span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureSnap"</span>).<span style="color: #7a7a43;">click</span>(<span style="color: navy; font-weight: bold;">function</span>() {
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageContext</span>.<span style="color: #7a7a43;">drawImage</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>, <span style="color: blue;">0</span>, <span style="color: blue;">0</span>, <span style="color: blue;">640</span>, <span style="color: blue;">480</span>, -<span style="color: blue;">95</span>,<span style="color: blue;">0</span>,<span style="color: blue;">448</span>,<span style="color: blue;">330</span>);
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageStream</span>.<span style="color: #7a7a43;">stop</span>();
<span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureStep1"</span>).<span style="color: #7a7a43;">hide</span>();
<span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureStep2"</span>).<span style="color: #660e7a; font-weight: bold;">show</span>();
});</pre></div><div><div><b><u>Unfortunately, the MediaStream.stop() function recently became depreciated. After a quick search, I found <a href="https://developers.google.com/web/updates/2015/07/mediastream-deprecations" target="_blank">only one article</a> 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.</u></b></div><div><pre style="font-family: 'Courier New';"><span style="color: grey; font-style: italic;">// Snapping up the picture</span><span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureSnap"</span>).<span style="color: #7a7a43;">click</span>(<span style="color: navy; font-weight: bold;">function</span>() {
<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageContext</span>.<span style="color: #7a7a43;">drawImage</span>(<span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageVideo</span>, <span style="color: blue;">0</span>, <span style="color: blue;">0</span>, <span style="color: blue;">640</span>, <span style="color: blue;">480</span>, -<span style="color: blue;">95</span>,<span style="color: blue;">0</span>,<span style="color: blue;">448</span>,<span style="color: blue;">330</span>);
<span style="color: grey; font-style: italic;"> </span><span style='background:yellow !important;'><span style=""><span style="color: navy; font-family: 'Courier New'; font-weight: bold;">try </span><span style="font-family: 'Courier New';">{ </span><span style="color: #660e7a; font-family: 'Courier New'; font-style: italic; font-weight: bold;">CaptureImageStream</span><span style="font-family: 'Courier New';">.</span><span style="color: #7a7a43; font-family: 'Courier New';">stop</span><span style="font-family: 'Courier New';">(); } </span><span style="color: navy; font-family: 'Courier New'; font-weight: bold;">catch</span><span style="font-family: 'Courier New';">(e) { }</span><pre style="font-family: 'Courier New';"><span style='background: yellow;'><span style="color: navy; font-weight: bold;"> try </span>{
<span style="color: navy; font-weight: bold;">var </span><span style="color: #458383;">track </span>= <span style="color: #660e7a; font-style: italic; font-weight: bold;">CaptureImageStream</span>.getTracks()[<span style="color: blue;">0</span>];
<span style="color: #458383;">track</span>.<span style="color: #7a7a43;">stop</span>();</pre><span style="font-family: 'Courier New';"> } </span><span style="color: navy; font-family: 'Courier New'; font-weight: bold;">catch</span><span style="font-family: 'Courier New';">(e) { }</span></span></span></span>
<span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureStep1"</span>).<span style="color: #7a7a43;">hide</span>();
<span style="color: #660e7a; font-weight: bold;">$</span>(<span style="color: green; font-weight: bold;">"#ImageCaptureStep2"</span>).<span style="color: #660e7a; font-weight: bold;">show</span>();
});</pre><div>Hopefully it won't change further, but as we know HTML5 APIs are evolving all the time.</div></div></div>Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-46542099214792895162016-01-08T18:29:00.000+08:002016-01-08T18:30:19.929+08:003 PHP quizzes for testing your knowledge: beginner, medium, and advanced levels<div style="text-align: justify;">
Hello everyone,</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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.</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="EN-US"><br /></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="EN-US">Beginner :
<a href="http://goo.gl/H9seNQ">http://goo.gl/H9seNQ</a> <o:p></o:p></span></div>
</div>
<div class="MsoNormal">
<div style="text-align: justify;">
<span lang="EN-US">Medium :
</span><a href="http://goo.gl/HBNezZ"><span lang="EN-US">http://goo.gl/HBNezZ</span></a><span lang="EN-US"><o:p></o:p></span></div>
</div>
<div style="text-align: justify;">
Advanced :
<a href="http://goo.gl/5ESofc">http://goo.gl/5ESofc</a></div>
<div class="MsoNormal">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="direction: ltr;">
<div style="text-align: justify;">
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. </div>
</div>
<div class="MsoNormal" style="direction: ltr;">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="direction: ltr;">
<div style="text-align: justify;">
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. </div>
</div>
<div class="MsoNormal" style="direction: ltr;">
<div style="text-align: justify;">
<br /></div>
</div>
<div class="MsoNormal" style="direction: ltr;">
<div style="text-align: justify;">
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!</div>
</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-38680305170539696292015-12-18T14:10:00.002+08:002015-12-18T14:30:06.967+08:00Get Nginx HTTP Server 3rd Edition and any other book from Packt Publishing for just $5<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.packtpub.com/networking-and-servers/nginx-http-server-third-edition/?utm_source=SP-cnedelcu&utm_medium=referral&utm_campaign=OME5D2015" target="_blank"><img border="0" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDDMS7Oq-2Htra2aXMTv9UjAxK7xq0oLw3zH4WVfu2NgBq7Byk9I3W8C-jcvhmIufFXNJDYvtmXhPl1TIGvT6VmcPMvIIlWvdaEXtW4NUXRihksXR3ayqjm977u7xlMxCvk8vMCXbEgX4/s320/%25245.png" width="320" /></a></div>
<br />
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 - <a href="https://www.packtpub.com/networking-and-servers/nginx-http-server-third-edition/?utm_source=SP-cnedelcu&utm_medium=referral&utm_campaign=OME5D2015" target="_blank">Nginx HTTP server 3rd edition</a>. The promotion started yesterday and will last until New Year. Hurry up and get as many books as you can before the promotion ends!Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com1tag:blogger.com,1999:blog-512188703456595011.post-9457737001500097552015-12-10T11:58:00.001+08:002015-12-10T12:00:20.283+08:00Outlook 2010 stuck in safe mode - just uninstall KB3114409Yesterday (December 9th, 2015) Microsoft rolled out a faulty update for Microsoft Office 2010 (KB3114409) which accidentally causes Outlook 2010 to <b>start in safe mode systematically</b>, ignoring registry and computer settings.<br />
<br />
To solve the problem, simply go to the "Programs and features" control panel applet, click on "View installed updates", <b>search for KB3114409, and uninstall it</b>. After you reboot your computer, Outlook will start normally again.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7BoOmANUXff_yPyhWFtekOU2slSWd_zMlBSP3cpJ53RpsMXMC4nG11N4gumc6fN3OxFQRpwvySaT42rxv65e8gtWUhyphenhyphenxj053AEUvN21EYyhXt3Lyxqz99l4IOX51DewuebkRbrYWdW-I/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="271" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg7BoOmANUXff_yPyhWFtekOU2slSWd_zMlBSP3cpJ53RpsMXMC4nG11N4gumc6fN3OxFQRpwvySaT42rxv65e8gtWUhyphenhyphenxj053AEUvN21EYyhXt3Lyxqz99l4IOX51DewuebkRbrYWdW-I/s400/Capture.PNG" width="400" /></a></div>
<br />
This solution has been tested successfully at work for dozens of users.<br />
<br />
Microsoft stated: “<i>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.</i>"<br />
<br />
Source: <a href="http://answers.microsoft.com/en-us/office/forum/office_2010-outlook/my-outlook-is-stuck-in-safe-mode-how-can-i-change/1068de35-07ad-4854-8480-30c6f66ad74e?db=5&page=2" target="_blank">Microsoft message boards</a>Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-79652129911738261622015-11-12T11:01:00.000+08:002015-11-12T13:42:24.533+08:00Nginx 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 <a href="http://www.amazon.com/Nginx-HTTP-Server-Cl-ment-Nedelcu-ebook/dp/B016DPU3JS/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr="><b>Amazon.com</b></a> or directly from <a href="https://www.packtpub.com/networking-and-servers/nginx-http-server-third-edition"><b>Packt Publishing</b></a>. Paperback version will follow on December 1st.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.packtpub.com/networking-and-servers/nginx-http-server-third-edition" target="_blank"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiF3vqvR8cPzsJOX3fkgGDBK_0iGH4uRzb-bDVad1iKeGQrpgX0w8OYuJFm6KauSBwTGEkqL0hZsyhyphenhyphen8iWCeDFWVVmim3U_HxpS8vcx5mAwwG1DOaE9-siXt7fW0UiEzv2e8izSUgWEnMc/s320/B04846_MockupCover_Normal.jpg" width="259" /></a><span id="goog_1155575478"></span><span id="goog_1155575479"></span><a href="https://www.blogger.com/"></a></div>
<br />
Aside from the numerous corrections, chapter overhauls, and section rewrites, this new edition comes with two entirely new chapters:<br />
<ul>
<li>an introduction to load balancing and optimization</li>
<li>real life case studies, starting from scratch</li>
</ul>
<div style="text-align: justify;">
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! <b>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!</b></div>
Clementhttp://www.blogger.com/profile/07321881637229432266noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-24923410379709143442015-09-12T20:37:00.001+08:002015-09-12T20:38:04.425+08:00Disqus comments, 3rd edition, 2 million page viewsJust a quick update that most likely no one will read, but here it is anyway:<br />
<ul>
<li><b>I have switched comment systems, we're now with Disqus.</b> 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.</li>
<li><a href="https://www.packtpub.com/networking-and-servers/nginx-http-server-second-edition" target="_blank"><b>Nginx HTTP Server</b></a>, <b>3rd edition is coming up soon</b>! 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.</li>
<li><b>2 million page views on the blog </b>- 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.</li>
</ul>
<div>
Thanks for visiting! Clement</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-32920749706091228172015-08-04T15:23:00.000+08:002015-08-06T12:14:27.190+08:00How to fix: jQuery UI progress bar not animating when indeterminate value<div style="text-align: justify;">
Once again I find myself in this situation:</div>
<div style="text-align: justify;">
- I run into a small problem</div>
<div style="text-align: justify;">
- I google it: can't find a solution</div>
<div style="text-align: justify;">
- Try to fix it myself: success</div>
<div style="text-align: justify;">
I am hoping that by posting this article I will help out a person or two.</div>
<div style="text-align: justify;">
<br />
<span style="color: red;"><b><u>UPDATE</u>:</b> a day later, the problem is back, this post is thereby useless. If you know a proper solution I'm all ears! ;-(</span></div>
<h3 style="text-align: justify;">
What's the problem?</h3>
<div style="text-align: justify;">
The <a href="https://jqueryui.com/progressbar/#indeterminate" target="_blank">jQuery UI progress bar widget</a> 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. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The problem I've been having is that the progress bar <b>RANDOMLY doesn't animate</b> 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).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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).</div>
<div style="text-align: justify;">
<br /></div>
<h3 style="text-align: justify;">
How to fix it?</h3>
<div style="text-align: justify;">
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 <a href="http://filetrip.net/view?hnOZD5o1IV" target="_blank">can be found here</a>). </div>
<div style="text-align: justify;">
Example:</div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">.ui-progressbar-overlay{background:url("images/overlay.gif")</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
That's it! Save your files, refresh your cache and voila.<br />
<br />
<b><span style="color: red;">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.</span></b></div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-65603291382267713232015-06-22T14:41:00.000+08:002015-06-22T14:43:28.265+08:00Word 2007/2010/2013: attaching a template (containing custom styles) to a document<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
As I am writing the third edition of <a href="http://link.packtpub.com/V9sFNg" target="_blank">Nginx HTTP Server</a> 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:</div>
<ul style="text-align: left;">
<li>attaching the .dot / .dotm template file to your document</li>
<li>editing the settings to display all styles (not only the "recommended" ones)</li>
</ul>
<h3 style="text-align: left;">
Attaching a .dot or .dotm file to your document</h3>
<div>
<div style="text-align: justify;">
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)</div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM_dUTK55DRcbniKXZ_PgZWX_Uulau9mwD0F9rVlWVdZhcWRAXVAxdACPBWySzTR_7hiruz94PyzYPuZNDl62qALADBFjFocSrpHYHNt0MG7L5xUrCnvppK4traX4SJ-iTLAFg4mIRT90/s1600/1234.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgM_dUTK55DRcbniKXZ_PgZWX_Uulau9mwD0F9rVlWVdZhcWRAXVAxdACPBWySzTR_7hiruz94PyzYPuZNDl62qALADBFjFocSrpHYHNt0MG7L5xUrCnvppK4traX4SJ-iTLAFg4mIRT90/s400/1234.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
In the window that pops up, click the "Attach..." button to attach your template file. That's the first step.</div>
<div>
<br /></div>
<h3 style="text-align: left;">
Editing the settings to display all styles</h3>
<div class="separator" style="clear: both; text-align: justify;">
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:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul style="text-align: left;">
<li>All styles</li>
<li>Alphabetical</li>
<li>Tick all check boxes</li>
</ul>
<div class="separator" style="clear: both; text-align: left;">
Press OK to apply the changes. There you go! A full list of styles from your imported template.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6ApFJUsIvs4A-Lgl0frAfq_RV2VrgdoRYSnBNYT5ht03qL0ruy_rCecxHvFV7-QFzDCvQU00o7OXDF8c9pr4XmP94jSjujBBYxIQycHVtXSZzzpMD-tkK3UiDUmwSXG5ikBIm5whOq9Y/s1600/settings-123.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6ApFJUsIvs4A-Lgl0frAfq_RV2VrgdoRYSnBNYT5ht03qL0ruy_rCecxHvFV7-QFzDCvQU00o7OXDF8c9pr4XmP94jSjujBBYxIQycHVtXSZzzpMD-tkK3UiDUmwSXG5ikBIm5whOq9Y/s400/settings-123.png" width="400" /></a></div>
<div>
<br /></div>
</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com0tag:blogger.com,1999:blog-512188703456595011.post-77912929122820557652015-04-14T15:35:00.000+08:002018-03-28T18:32:03.661+08:00wkHTMLToPDF chinese/japanese/korean character support on Linux based systems<div style="text-align: justify;">
This post will explain <b>how to add support for Chinese or Japanese or Korean characters in <a href="http://wkhtmltopdf.org/" target="_blank">wkHTMLToPDF</a> </b>- the famous tool that converts HTML pages to PDF documents seamlessly. By default, if you have Chinese characters in your HTML page and convert the page to PDF with wkHTMLToPDF, nothing comes out (blanks replace chinese characters). I doubt this subject will be helpful to a lot of people around the world, but I might need to use this trick again in the future so why not blog about it?</div>
<div>
<br /></div>
<div>
The trick is to install Chinese character support on your OS and rebuild the cache. Under Ubuntu, I ran this command to install Chinese fonts:</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><b>apt-get install fonts-wqy-microhei ttf-wqy-microhei fonts-wqy-zenhei ttf-wqy-zenhei </b></span></div>
<div>
<div>
Note: package names might be different if you aren't under Ubuntu (try <span style="font-family: "courier new" , "courier" , monospace;">apt-cache search</span> ... to search for packages)</div>
<div>
</div>
Then, run this command to update the font cache:</div>
<div>
<b><span style="font-family: "courier new" , "courier" , monospace;">fc-cache -f -v</span></b></div>
<div>
<br />
For Japanese and Korean please use those:<br />
https://help.ubuntu.com/community/Fonts#Chinese.2C_Japanese.2C_and_Korean_Fonts<br />
<br />
<blockquote class="tr_bq">
<b>ttf-wqy-microhei</b> - A droid derived Sans-Seri style CJK font<br /><b>ttf-wqy-zenhei</b> - "WenQuanYi Zen Hei" A Hei-Ti Style (sans-serif) Chinese font<br /><b>ttf-dejima-mincho</b> - antique-looking Japanese TrueType Mincho font<br /><b>ttf-umefon</b> - Japanese TrueType font, Ume-font<br /><b>ttf-takao, ttf-takao-gothic, ttf-takao-mincho, and ttf-takao-pgothic</b> - Japanese TrueType font set: Takao Fonts, Takao Gothic Fonts, Takao Mincho Fonts, and Takao P Gothic Fonts.<br /><b>ttf-kochi-gothic and ttf-kochi-mincho </b>- Kochi Subst Gothic and Mincho Japanese TrueType font without naga10<br /><b>ttf-sazanami-gothic and ttf-sazanami-mincho </b>- Sazanami Gothic and Mincho Japanese TrueType font (legacy)<br /><b>ttf-nanum-coding </b>- Nanum Coding fixed width Korean TrueType font<br />fonts-nanum and fonts-nanum-extra - Nanum and additional Nanum Korean fonts<br /><b>ttf-baekmuk </b>- Baekmuk series Korean fonts</blockquote>
</div>
<div>
After that, try generating a PDF again with wkHTMLToPDF: it works! Huge thanks to an anonymous user on <a href="http://stackoverflow.com/questions/25833954/wkhtmltopdf-and-chinese-characters" target="_blank">StackOverflow</a> for finding the solution.</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com2tag:blogger.com,1999:blog-512188703456595011.post-90352710935606738812015-03-11T11:34:00.000+08:002015-03-12T14:00:43.112+08:00Sublime Text vs phpDesigner vs PhpStorm<div style="text-align: justify;">
Lately I have been trying out several IDE solutions in order to improve my development productivity. Working on large projects made me realize that I was probably not using the right tools. Over the past year I have tried three in particular and I've got a clear winner here. So clear in fact that I thought I should write about it.</div>
<div style="text-align: justify;">
<br /></div>
The three solutions that I am comparing are:<br />
<ul>
<li><a href="http://sublimetext.com/">Sublime Text</a> (multi-platform, loaded with plugins), $70</li>
<li><a href="http://www.mpsoftware.dk/">phpDesigner</a> (Windows only), 29€</li>
<li><a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a> (multi-platform), $99</li>
</ul>
<div>
<div style="text-align: justify;">
They all have trial periods so you are free to try them out for a limited time. Also please bear in mind that I am only working on PHP projects, so if that is not the case for you, you might find this article irrelevant.</div>
<br /></div>
<h2>
Sublime Text</h2>
<div>
<div style="text-align: justify;">
I was originally using Notepad++ as code editor, but when I started working on larger projects I quickly felt the need for something more. I was recommended Sublime Text by a friend. Let me list the pros and cons of the solution before discussing further.</div>
</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
<div>
<b><span style="color: #38761d;">Pros:</span></b></div>
<div>
- Fully multi-platform, though I have only been using the Windows version</div>
<div>
- Lots of plugins to extend functionality</div>
<div>
- Very lightweight and responsive<br />
<br /></div>
<div>
<b><span style="color: #cc0000;">Cons:</span></b></div>
<div>
- Default functionality is somewhat feeble (you have to resort to plugins)</div>
<div>
- Steep learning curve, documentation clearly lacking, terrible support even for paid users</div>
<div>
- Can be unstable, plugins and application sometimes crash</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_rjkB0AWFfCyj56L0-DzCfQ4QsgEzm6-z0j0c9AlXaRecsFouUMUTF448sx_Mv2h_8he5AHSdjGsg3e_mphQI8ixYX8P-8XGJfb1peDsn1qt_8l7CqAgY8QZ_Lvjz2N8JIrUsYZNhwN4/s1600/sttext.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_rjkB0AWFfCyj56L0-DzCfQ4QsgEzm6-z0j0c9AlXaRecsFouUMUTF448sx_Mv2h_8he5AHSdjGsg3e_mphQI8ixYX8P-8XGJfb1peDsn1qt_8l7CqAgY8QZ_Lvjz2N8JIrUsYZNhwN4/s1600/sttext.PNG" height="173" width="320" /></a></div>
<div style="text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
<b>My thoughts:</b></div>
<div>
<div style="text-align: justify;">
It took me weeks to really finalize my Sublime Text set up: first you need to know that the program doesn't do much if don't install plugins. And there is no actual GUI for configuring the program: all the program and plugin settings have to be written in text format in the editor (and guess what? you will not find an up-to-date list of all the settings that can be configured). Then you realize installing and managing plugins is pretty easy and cool, so you install tons of them, turning Sublime Text into a pretty good IDE. The thing is, some of the plugins that I've used have been upgraded over time and changed the behavior of the application (I'm talking about SublimeCodeIntel specifically, but there are other examples). In addition, some features just don't work properly at all -- code folding, indenting -- and some things are just downright missing (ie. automatic indenting, full code folding, ...) and aren't available as plugins. On top of that, it is nearly impossible to get support. There is a message board available but nobody really cares at all and messages are left unanswered. <b>In conclusion I would only recommend Sublime Text if you are working on big projects with tons of files open (because it is really lightweight) as long as you don't need extensive functionality.</b></div>
<b><br /></b></div>
<h2>
phpDesigner</h2>
<div>
<div style="text-align: justify;">
I found out about phpDesigner accidentally during a Google Search. It looked nice and appeared to be free (official website states "Free Download"), but it actually isn't. You even have to pay for upgrades. That isn't usually a big problem because when an application really improves your productivity, it is worth purchasing. I had a good run with phpDesigner but I gave up for several reasons. Let me list the pros and cons.</div>
</div>
<div>
<br /></div>
<div>
<b><span style="color: #38761d;">Pros:</span></b></div>
<div>
- Easy to install and use, fast learning curve</div>
<div>
- Comes with tons of power features (intelligent syntax highlighting, autocompletion, ...)</div>
<div>
- Relatively lightweight</div>
<div>
<br /></div>
<div>
<b><span style="color: #cc0000;">Cons:</span></b></div>
<div>
- Windows only, other platforms are unsupported </div>
<div>
- The GUI can be cumbersome and annoying</div>
<div>
- Doesn't work well on high DPI settings</div>
<div>
<br /></div>
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1VwskTBAqCf4AwLbe8NfcezGqmuJCaqSkvYoYDVLEx3VzyWt7du-pBoNA5qTSaCGoICxNku7Tl6RAmXm9kI5dFIurUnhA11uPRPhYkOqkqi6PhGhO9gfX0JXYsW_doQjDZKkYxIfoMmU/s1600/phpd8-main2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1VwskTBAqCf4AwLbe8NfcezGqmuJCaqSkvYoYDVLEx3VzyWt7du-pBoNA5qTSaCGoICxNku7Tl6RAmXm9kI5dFIurUnhA11uPRPhYkOqkqi6PhGhO9gfX0JXYsW_doQjDZKkYxIfoMmU/s1600/phpd8-main2.png" height="236" width="320" /></a></div>
<div>
<br /></div>
<div>
<b>My thoughts:</b></div>
<div>
<div style="text-align: justify;">
When I first installed this program, I thought: wow, it looks completely broken. Toolbars looked terrible, UI fonts were too small or too large, and so on. I quickly realized that this was due to the DPI settings I was using on Windows (150% -- I have a high res monitor). When I switched back to 100%, the program looked perfectly fine. I reported the issue to the developer about a year ago and he replied nicely, but the program was never updated since. It's a shame because it has potential. There are some particularly useful features such as a full fledged code explorer, very relevant code completion, code reformatting tools and many more. In the end, I gave up on it because of the UI issues. I hope it gets fixed in the future, but I wouldn't be too hopeful. <b>In conclusion, I would recommend phpDesigner if you're a Windows user with regular OS settings and conditions, but if you are the kind of person who requires very specific work environment settings I think you might be turned off by the UI.</b></div>
<b><br /></b></div>
<h2>
PhpStorm</h2>
<div>
<div style="text-align: justify;">
I recently stumbled upon a <a href="http://www.sitepoint.com/best-php-ide-2014-survey-results/">survey of the best PHP IDE</a> (2014 edition) showing overwhelming results in favor of PhpStorm. Strangely I had never heard the name before, and it was not for lack of Googling! So I looked into it, downloaded the trial version and... well, what a shock this has been. I could not dream of a better IDE. It is absolutely perfects for my needs.</div>
</div>
<div>
<br /></div>
<div>
<b><span style="color: #38761d;">Pros</span></b>:</div>
<div>
- It has every feature you could dream of, and more</div>
<div>
- Extremely configurable, in a very easy way</div>
<div>
- Excellent and friendly user interface</div>
<div>
- Fully multiplatform</div>
<div>
<br /></div>
<div>
<b><span style="color: #cc0000;">Cons:</span></b></div>
<div>
- Somewhat heavy, if you compare it to Sublime Text</div>
<div>
- I really can't find another con</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwqEUWFn0LcPeOWg40IBWbBGrTF_2Won42Y2ZdBCxeNQcqbnH73D52ejrkzd3auafeJ1KUD1gDrJo5wB8CI7WvrG9o3f77u0Om2ZCMHyeEoKgKqLf6uyIJoQScxDgCxmvqsHaiDlx2wIM/s1600/phpstorm.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwqEUWFn0LcPeOWg40IBWbBGrTF_2Won42Y2ZdBCxeNQcqbnH73D52ejrkzd3auafeJ1KUD1gDrJo5wB8CI7WvrG9o3f77u0Om2ZCMHyeEoKgKqLf6uyIJoQScxDgCxmvqsHaiDlx2wIM/s1600/phpstorm.PNG" height="197" width="320" /></a></div>
<div style="text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
<b>My thoughts:</b></div>
<div>
<div style="text-align: justify;">
After downloading the program, I was surprised to see that they have a very nicely written guide that helps you go through the first steps of installing and configuring the IDE. It answered pretty much every question I had, right off the bat. It took me a few minutes to figure out how to fully and properly import my existing projects into the application. Then I spent hours configuring the IDE -- not because I had to, but because I enjoyed it! They actually have a theme download website (themes are easy to install), a thousand settings which can either be language-specific or global, at the end of the day you can really have it the way you want. In addition, there is a nice little community of users which makes it easy to get help. After a few days of use, I ended up purchasing the license. No regrets at all, that's a well spent $99. <b>In conclusion, I would recommend PhpStorm if you're after a powerful IDE and have a decent computer (since it's not as lightweight as Sublime Text, for example).</b></div>
</div>
<div>
<br /></div>
<div>
If you've read the article fully, you'll probably have understood that my personal favorite is PhpStorm by far!</div>
Clementhttp://www.blogger.com/profile/00545377683292039358noreply@blogger.com14tag:blogger.com,1999:blog-512188703456595011.post-15835724776507418092014-10-16T12:58:00.001+08:002014-10-16T12:58:29.679+08:00HTTPS with Nginx: setting up an SSL certificate in 3 simple steps<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
This article will explain how to <b>serve content securely over HTTPS via Nginx</b>. This can be done in 3 simple steps detailed below. It's unbelievably easy! I've even added an optional step for optimization, and links for further readings.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The three steps are as follows:</div>
<div style="text-align: justify;">
Step 1: preparing your private key and CSR </div>
<div style="text-align: justify;">
Step 2: obtaining an SSL certificate</div>
<div style="text-align: justify;">
Step 3: Nginx SSL configuration</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This post is valid as of October 2014, tested with Nginx 1.2, Nginx 1.4 and Nginx 1.6 (probably works with every version above 1.2). For older versions, directive names might change just a tiny bit but the rest of the process should otherwise work normally.</div>
<br />
<h3 style="text-align: left;">
Requirements</h3>
<div style="text-align: justify;">
You will need to have OpenSSL installed on your server. To find out whether OpenSSL is installed on your server, type "<b><span style="color: #990000; font-family: Courier New, Courier, monospace;">openssl version</span></b>". It should tell you the version you are running. I recommend version 1.0.1 at least because it supports several features which will come in handy in future tutorials (including which SPDY). If you do not have OpenSSL installed yet, just run "<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b>apt-get install openssl</b></span>" or equivalent to install it.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
You also need to have the SSL module installed on Nginx. To find out whether you have it, run "<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b>nginx -V</b></span>" and see if the HTTP SSL module is included in the list. If it isn't, you will need to rebuild Nginx with the proper configure parameter (<a href="http://nginx.org/en/docs/configure.html" target="_blank">read more</a>).</div>
<br />
<h3 style="text-align: left;">
Step 1: preparing your private key and CSR</h3>
<div style="text-align: justify;">
Note: in the following examples, you'll need to replace all references to <b>mydomain.com</b> by your actual domain name.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
You need two files to be able to obtain an SSL certificate. First, a private key file. Such a file can be generated by running the following command:</div>
<div style="text-align: justify;">
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b>openssl genrsa -out mydomain.com.key 2048</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
You will notice that this command generates a file called "mydomain.com.key" in the current folder. This is your private key file. Now, we're going to use this key to generate a CSR file (Certificate Signing Request), which will be used in step 2 to obtain the SSL certificate. Run the following command:</div>
<div style="text-align: justify;">
<b><span style="color: #990000; font-family: Courier New, Courier, monospace;">openssl req -new -key mydomain.com.key -out mydomain.com.csr</span></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Caution! This command will prompt you to enter some values. Enter actual values for your domain and company information, and be extra careful when filling up the "<i>Common Name</i>" field: you need to enter the domain name for which you will use the certificate! If you are going to use the certificate on "mydomain.com" then you have to enter "mydomain.com" as Common Name. If you fail this step, your certificate will not work properly.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
After this is done, you'll find yourself with two files: </div>
<div style="text-align: justify;">
- a .key file = your private key file</div>
<div style="text-align: justify;">
- a .csr file = your certificate signing request file</div>
<br />
<h3 style="text-align: left;">
Step 2: obtaining an SSL certificate</h3>
<div style="text-align: justify;">
There are thousands of providers on the web for SSL certificates. I personally use Godaddy because it's reliable and quite cheap. Plus, you can find coupons online (Google it, you'll probably be able to get at least 30% off like I did). </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
GoDaddy will ask you to provide your .CSR file in a text box. Just open your .CSR file with a text editor, then copy/paste the entire content into the textbox on GoDaddy. At this point you'll be able to verify the domain name that you entered in step 1. This is your chance to make things right in case you made a mistake.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
After your CSR file is uploaded, you'll be able to download your certificate. GoDaddy offers several file formats for the different web servers. Nginx isn't in the list (as of October 2014) so just pick the "Other" option. You're given a .zip file containing two files: </div>
<div style="text-align: justify;">
- a .crt file with a seemingly random name, which is your website's certificate,</div>
<div style="text-align: justify;">
- and GoDaddy's .crt file (gd_bundle_something.crt) which is GoDaddy's certificate</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now you're going to need to concatenate these two files into one (your certificate coming first, then Godaddy's). You could do so by creating a new file in the Notepad on Windows and copy-pasting the content of your site's .crt file, then the contents of Godaddy's .crt file. Otherwise on Linux you could just run the following command:</div>
<div style="text-align: justify;">
<b><span style="color: #990000; font-family: Courier New, Courier, monospace;">cat your_website.crt gd_bundle_something.crt > mydomain.com.crt</span></b></div>
<div style="text-align: justify;">
The order is important! Your site's certificate MUST come before Godaddy's, otherwise you'll get a warning/error page from the web browser when visiting your site.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
At this point, you should have two files that we'll need to provide to Nginx:</div>
<div style="text-align: justify;">
- mydomain.com.key (private key file, from step 1)</div>
<div style="text-align: justify;">
- mydomain.com.crt (certificate file which we just generated)</div>
<div style="text-align: justify;">
If you are missing one of these, read the tutorial again because I covered both ;-)</div>
<div style="text-align: justify;">
<br /></div>
<h3>
Step 3: Nginx SSL configuration</h3>
The configuration is done at the server block level:<br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b>server {</b></span><br />
<span style="font-family: Courier New, Courier, monospace;"><b style="color: #990000;"><span class="Apple-tab-span" style="white-space: pre;"> </span>listen 443 ssl; </b><span style="color: #38761d;"># this tells Nginx to listen on port 443 (https) with SSL</span></span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>ssl_certificate /path/to/your/mydomain.com.crt;</b></span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b><span class="Apple-tab-span" style="white-space: pre;"> </span>ssl_certificate_key /path/to/your/mydomain.com.key;</b></span><br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b><br /></b></span>
<span style="color: #38761d; font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>[...] # The rest of your vhost configuration...</span><br />
<br />
Save your configuration, reload Nginx and voilà ! People can now securely visit your website via HTTPS.<br />
<br />
<h3 style="text-align: left;">
Optional: optimization and advanced configuration</h3>
Nginx lets you tweak the configuration with the following directives:<br />
- <b><span style="font-family: Courier New, Courier, monospace;">ssl_protocols</span></b>: lets you specify the list of allowed SSL protocols<br />
- <span style="background-color: white; line-height: 16px;"><b><span style="font-family: Courier New, Courier, monospace;">ssl_ciphers</span></b>: lets you specify the enabled ciphers (format must follow standards imposed by the OpenSSL library)</span><br />
And <a href="http://nginx.org/en/docs/http/ngx_http_ssl_module.html" target="_blank">many more</a>...<br />
<br />
You can also add a few directives at the http block level that may help with performance:<br />
- <b><span style="font-family: Courier New, Courier, monospace;">ssl_session_cache</span></b>: a caching mechanism for SSL sessions, allowing to avoid new handshake and session overhead every time a user connects. It is used on par with the next directive...<br />
- <b><span style="font-family: Courier New, Courier, monospace;">ssl_session_timeout</span></b>: defines how long an SSL session should last.<br />
For details on how to use either directive, read the <a href="http://nginx.org/en/docs/http/configuring_https_servers.html#optimization" target="_blank">official documentation</a>.<br />
<br />
If you really don't want to bother with it, just use the example below:<br />
<span style="color: #990000; font-family: Courier New, Courier, monospace;"><b>http {</b></span><br />
<span style="font-family: Courier New, Courier, monospace;"><b style="color: #990000;"> ssl_session_cache shared:SSL:10m; </b><span style="color: #38761d;"># 10 megabytes are reserved for the SSL cache</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><b style="color: #990000;"> ssl_session_timeout 10m; </b><span style="color: #38761d;"># 10 minutes</span></span><br />
<span style="font-family: Courier New, Courier, monospace;"><b style="color: #990000;"> </b><span style="color: #38761d;">[...]</span></span><br />
<br />
<h3 style="text-align: left;">
Conclusion</h3>
<div style="text-align: justify;">
We've set up an SSL certificate on Nginx to serve secure content over a single domain. But what if you have subdomains or multiple domains with the same content? This is a much more complex subject, I recommend <a href="http://nginx.org/en/docs/http/configuring_https_servers.html#name_based_https_servers" target="_blank">reading this</a> before going any further.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Additionally, if you're moving a domain from HTTP to HTTPS, you will probably want to read this article about how to properly <a href="http://www.branded3.com/blogs/seo-considerations-moving-http-https/" target="_blank">move from HTTP to HTTPS from the point of view of SEO</a>. It might be a significant change in the eyes of a search engine!</div>
</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com6tag:blogger.com,1999:blog-512188703456595011.post-79358206509010309712014-10-16T09:55:00.003+08:002014-10-16T09:55:59.686+08:001,000,000 page views on this blog!<div dir="ltr" style="text-align: left;" trbidi="on">
Just a quick self congratulation post: 6 years after the launch of this blog, I've already received<br />
<br />
<div style="text-align: center;">
<b><span style="font-size: x-large;">1,000,000 page views!</span></b></div>
<div style="text-align: center;">
<br /></div>
The milestone was reached last week while I was away. This has led me to realize that I should probably update this blog a little more. I've got two articles coming up:<br />
- How to set up an SSL certificate on Nginx to serve HTTPS content<br />
- How to enable SPDY on Nginx<br />
<br />
Thank you for visiting!</div>
Clément Nedelcuhttp://www.blogger.com/profile/00168228978102132365noreply@blogger.com46