<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>rui lopes notebook</title>
    <description></description>
    <link>http://blog.ruilopes.com/</link>
    <atom:link href="http://blog.ruilopes.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Mon, 01 Jun 2015 18:27:17 +0000</pubDate>
    <lastBuildDate>Mon, 01 Jun 2015 18:27:17 +0000</lastBuildDate>
    <generator>Jekyll v2.4.0</generator>
    
      <item>
        <title>Using Packer, Vagrant and Boxstarter to create Windows environments</title>
        <description>&lt;p&gt;Testing your application in different environments can be hard to do manually, as its time consuming, error prone, and not easily reproducible. This article will show you a way on how to automatically create Windows environments, where you can test your application.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;/h2&gt;

&lt;p&gt;You will use the following tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://packer.io/&quot;&gt;Packer&lt;/a&gt; and &lt;a href=&quot;https://github.com/joefitzgerald/packer-windows&quot;&gt;packer-windows&lt;/a&gt; to create an up-to-date Windows base image from an ISO file.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt; to launch and configure a base image tailored to a specific scenario.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://boxstarter.org/&quot;&gt;Boxstarter&lt;/a&gt; to easily install software from &lt;a href=&quot;https://chocolatey.org/&quot;&gt;Chocolatey&lt;/a&gt; packages.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt; to run virtual machines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;install&quot;&gt;Install&lt;/h3&gt;

&lt;p&gt;You will need to run several commands. These must be run on a bash shell, which I’ll assume that you have installed following the instructions from &lt;a href=&quot;/sane-shell-environment-on-windows.html&quot;&gt;Sane shell environment on Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Make sure you have previously installed Packer, Vagrant and VirtualBox and have them available on your &lt;code&gt;PATH&lt;/code&gt;, e.g. with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;$PATH:/c/Development/packer&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;$PATH:/c/Development/Vagrant/bin&amp;quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;$PATH:/c/Program Files/Oracle/VirtualBox&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;windows-base-image&quot;&gt;Windows base image&lt;/h2&gt;

&lt;p&gt;Packer is a tool to automatically create a machine image from a &lt;a href=&quot;https://packer.io/docs/basics/terminology.html#Templates&quot;&gt;template file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;packer-windows is a repository with pre-configured template files for installing different Windows versions.&lt;/p&gt;

&lt;p&gt;We will use them to drive the installation of Windows 2012 R2 into a virtual machine image. This image will have the bare minimum needed to be later used by Vagrant.&lt;/p&gt;

&lt;p&gt;This base image will be automatically configured with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SSH server.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/aa384426%28v=vs.85%29.aspx&quot;&gt;WinRM&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;vagrant&lt;/code&gt; user account with a &lt;code&gt;vagrant&lt;/code&gt; password.&lt;/li&gt;
  &lt;li&gt;Latest Windows updates.&lt;/li&gt;
  &lt;li&gt;VirtualBox guest additions.&lt;/li&gt;
  &lt;li&gt;60 GB disk.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start by getting the Windows template files:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;git clone https://github.com/joefitzgerald/packer-windows.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;packer-windows&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; These templates are for the trial versions of Windows, namely Windows 2012 R2 Standard, but you can also &lt;a href=&quot;#install-from-your-own-windows-iso-file&quot;&gt;install from your own Windows ISO file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to makes things easier for us we will tweak a couple of files.&lt;/p&gt;

&lt;p&gt;We want to see how the installation is going on, for that we need to change the template file to start the virtual machine in non-&lt;a href=&quot;http://en.wikipedia.org/wiki/Headless_software&quot;&gt;headless mode&lt;/a&gt;. For that, edit the &lt;code&gt;windows_2012_r2.json&lt;/code&gt; template file:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;windows_2012_r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;virtualbox-iso&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;headless&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, the template is configured to install the latest Windows updates, but the default timeout might now be enough for the updates to finish in time, so increase the &lt;code&gt;ssh_timeout&lt;/code&gt; from the default &lt;code&gt;2h&lt;/code&gt; to &lt;code&gt;8h&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;windows_2012_r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;virtualbox-iso&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;ssh_wait_timeout&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;8h&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also, sometimes, the &lt;a href=&quot;https://github.com/joefitzgerald/packer-windows/issues/80&quot;&gt;last provisioning step fails&lt;/a&gt;, so you also need to change the line that has &lt;code&gt;rm -rf&lt;/code&gt; to:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shell&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;inline&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;rm -rf /tmp/* || true&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Also consider removing the &lt;code&gt;./scripts/compact.bat&lt;/code&gt; (it takes ages to run) and the &lt;code&gt;./scripts/chef.bat&lt;/code&gt; (you might not need it) lines.&lt;/p&gt;

&lt;p&gt;Finally, build the VirtualBox based image:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time packer build -only virtualbox-iso windows_2012_r2.json
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now be patient! It will download the Windows ISO file and install the latest Windows Updates. These steps take a lot of time to complete (about 2 hours in my environment). At the end you should have a &lt;code&gt;.box&lt;/code&gt; file (about 1.8 GB), ready to be used by Vagrant.&lt;/p&gt;

&lt;p&gt;Add the generated box file to vagrant:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant box add --name windows_2012_r2 windows_2012_r2_virtualbox.box
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; You can distribute the box file to other system, or you can delete it (its no longer needed once added to vagrant)&lt;/p&gt;

&lt;p&gt;We are now almost ready to launch a Windows virtual machine with Vagrant, for that we need to create a &lt;code&gt;Vagrantfile&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;testing&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vagrantfile&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- mode: ruby -*-&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# vi: set ft=ruby :&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require_version&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;gt;= 1.6.2&amp;quot;&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;testing&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;box&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;windows_2012_r2&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:virtualbox&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gui&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--memory&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2048&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--cpus&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And launch it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;time vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; The initial run will take about 4m to boot into Windows. Later runs take about 40s. But YMMV.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; To troubleshoot you need pass the &lt;code&gt;--debug&lt;/code&gt; flag to &lt;code&gt;vagrant up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once Windows boots, try it a bit to check whether things are working fine, and then stop the virtual machine with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant halt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And destroy it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You are now ready to customize a vagrant environment to fit your needs. For that we will modify the &lt;code&gt;Vagrantfile&lt;/code&gt; to use a provision script.&lt;/p&gt;

&lt;h2 id=&quot;provisioning&quot;&gt;Provisioning&lt;/h2&gt;

&lt;p&gt;Customizing a vagrant environment is a mater of creating one or more provision scripts. Lets start simple, with one embedded within the &lt;code&gt;Vagrantfile&lt;/code&gt;, it will just change the keyboard layout and timezone:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vagrantfile&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- mode: ruby -*-&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# vi: set ft=ruby :&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;require_version&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;gt;= 1.6.2&amp;quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# NB this is a PowerShell script that is run as Administrator.&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$root_provision_script&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ROOT_PROVISION_SCRIPT&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# set keyboard layout.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# NB you can get the name from the list:&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#      [System.Globalization.CultureInfo]::GetCultures(&amp;#39;InstalledWin32Cultures&amp;#39;) | out-gridview&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;Set-WinUserLanguageList pt-PT -Force&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# set the date format, number format, etc.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;Set-Culture pt-PT&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# set the timezone.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# tzutil /l lists all available timezone ids&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;amp; $env:windir\system32\tzutil /s &amp;quot;GMT Standard Time&amp;quot;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;ROOT_PROVISION_SCRIPT&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;testing&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;box&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;windows_2012_r2&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:virtualbox&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;override&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gui&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--memory&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2048&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;customize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--cpus&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provision&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shell&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$root_provision_script&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And launch it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If its running fine, stop the virtual machine with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant halt
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now its time to install applications. This is handled by Boxstarter. Lets modify the provision script to install Boxstarter and some applications:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Vagrantfile&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;vg&quot;&gt;$root_provision_script&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ROOT_PROVISION_SCRIPT&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# install Boxstarter.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# NB Do NOT install chocolatey before Boxstarter. If you do, strange things&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#    will happen...&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# TODO this should all be abstracted in a &amp;quot;boxstarter&amp;quot; provisioner.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;$boxstarterSetupPath = &amp;quot;$env:TEMP\Boxstarter-setup&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;$boxstarterSetupZipPath = $boxstarterSetupPath + &amp;quot;.zip&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;Invoke-WebRequest http://boxstarter.org/downloads/Boxstarter.2.4.209.zip -OutFile $boxstarterSetupZipPath&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt; [System.Reflection.Assembly]::LoadWithPartialName(&amp;quot;System.IO.Compression.FileSystem&amp;quot;)&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt; [System.IO.Compression.ZipFile]::ExtractToDirectory($boxstarterSetupZipPath, $boxstarterSetupPath)&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;amp; $boxstarterSetupPath\setup.bat -Force&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;echo NBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNB&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;echo NB&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;echo &amp;#39;NB Boxstarter might need to reboot the machine, in that case, vagrant will&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;echo &amp;#39;NB fail, but that is expected. you need to monitor the install yourself to&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;echo &amp;#39;NB known when its done...&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;echo NB&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;echo NBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNBNB&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# NB if any of the choco packages need to access the desktop, you need to force&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#    a reboot at start of the boxstarter script. when you do that Boxstarter&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#    will run the script again, but in a auto-logon session. the easiest way to&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#    do that, is to install google chrome.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;$env:PSModulePath = &amp;quot;$([System.Environment]::GetEnvironmentVariable(&amp;#39;PSModulePath&amp;#39;, &amp;#39;User&amp;#39;));$([System.Environment]::GetEnvironmentVariable(&amp;#39;PSModulePath&amp;#39;, &amp;#39;Machine&amp;#39;))&amp;quot;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;cp C:\vagrant\setup.ps1 $env:TEMP&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;Import-Module Boxstarter.Chocolatey&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;$credential = New-Object System.Management.Automation.PSCredential(&amp;quot;vagrant&amp;quot;, (ConvertTo-SecureString &amp;quot;vagrant&amp;quot; -AsPlainText -Force))&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;Install-BoxstarterPackage $env:TEMP\setup.ps1 -Credential $credential&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;ROOT_PROVISION_SCRIPT&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create the script to automatically install some software:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cat&amp;lt;&amp;lt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&amp;gt;setup.ps1
&lt;span class=&quot;c&quot;&gt;# NB this file has to be idempotent. it will be run several times if the computer needs to be restarted.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    when that happens, Boxstarter schedules this script to run again with an auto-logon.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# NB always remember to pass -y to choco install!&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# NB already installed packages will refuse to install again; so we are safe to run this entire script again.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# NB make sure this is the first software you install, because, as a side&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    effect, this will trigger a reboot, which in turn, will fix the vagrant bug&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    that prevents the machine from rebooting after setting the hostname.&lt;/span&gt;
choco install -y google-chrome-x64

&lt;span class=&quot;c&quot;&gt;# Enable Show Window Contents While Dragging&lt;/span&gt;
reg ADD &lt;span class=&quot;s2&quot;&gt;&amp;quot;HKCU\Control Panel\Desktop&amp;quot;&lt;/span&gt; /v DragFullWindows /t REG_SZ /d &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; /f
taskkill /IM explorer.exe /F &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; explorer.exe

&lt;span class=&quot;c&quot;&gt;# Pin an application to the task bar.&lt;/span&gt;
Install-ChocolateyPinnedTaskBarItem &lt;span class=&quot;s2&quot;&gt;&amp;quot;$env:windir\system32\services.msc&amp;quot;&lt;/span&gt;

choco install -y notepad2

choco install -y nodejs.install

choco install -y visualstudiocode
EOF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And launch it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will notice that &lt;code&gt;vagrant up&lt;/code&gt; seems to fail with something like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The following WinRM command responded with a non-zero exit status.
 Vagrant assumes that this means the command failed!&lt;/p&gt;

  &lt;p&gt;powershell -ExecutionPolicy Bypass -OutputFormat Text -file c:\tmp\vagrant-shell.ps1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that’s expected, you need to monitor the install yourself to known when its done. Doing that automatically would be nice, but I’ll leave that as an exercise for the reader (hint: You could create a new &lt;code&gt;boxstarter&lt;/code&gt; Vagrant provisioner).&lt;/p&gt;

&lt;p&gt;As a side note, you could also manually provision the machine and later export it as a new box file, e.g.:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant package --base testing --output testing.box
&lt;/code&gt;&lt;/pre&gt;

&lt;h1 id=&quot;install-from-your-own-windows-iso-file&quot;&gt;Install from your own Windows ISO file&lt;/h1&gt;

&lt;p&gt;The templates contained in the windows-packer repository are configured to install the trial versions of windows, but you can also install from a specific ISO file. For that, you need to set the ISO path and its MD5 checksum, e.g.:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;vim&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;windows_2012_r2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;iso_url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;d:/Images/windows_2012_r2.iso&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;iso_checksum_type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;md5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;iso_checksum&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;458ff91f8abc21b75cb544744bf92e6a&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;iso_checksum&lt;/code&gt; value can be computed with &lt;code&gt;md5sum&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;md5sum d:/Images/windows_2012_r2.iso
458ff91f8abc21b75cb544744bf92e6a *d:/Images/windows_2012_r2.iso&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you don’t have a volume license ISO, you also need to set the Product Key. For that open the &lt;code&gt;answer_files/2012_r2/Autounattend.xml&lt;/code&gt; file, search for &lt;code&gt;ProductKey&lt;/code&gt; and follow the instructions.&lt;/p&gt;

&lt;h1 id=&quot;the-end&quot;&gt;The End&lt;/h1&gt;

&lt;p&gt;And thats it! You should now be able to create Windows environments to fit your needs.&lt;/p&gt;

&lt;p&gt;You should also look into configuration management tools like &lt;a href=&quot;http://www.ansible.com/&quot;&gt;Ansible&lt;/a&gt;, &lt;a href=&quot;https://www.chef.io/&quot;&gt;Chef&lt;/a&gt;, and &lt;a href=&quot;https://puppetlabs.com/&quot;&gt;Puppet&lt;/a&gt;. These might useful to actually install and configure your own application.&lt;/p&gt;
</description>
        <pubDate>Sun, 24 May 2015 00:00:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/using-packer-vagrant-and-boxstarter-to-create-windows-environments.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/using-packer-vagrant-and-boxstarter-to-create-windows-environments.html</guid>
        
        
      </item>
    
      <item>
        <title>Testing the Elasticsearch cluster behavior under network failure</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.elastic.co/products/elasticsearch&quot;&gt;Elasticsearch&lt;/a&gt; is a distributed system that depends heavily on the network, as such, you need to known how it behaves under different failures scenarios. This post shows a way of mounting these scenarios with Linux containers.&lt;/p&gt;

&lt;p&gt;You can simulate a couple of failure scenarios:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Node network loss&lt;/li&gt;
  &lt;li&gt;Packet delay and/or loss&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup should also be generally useful when you want to known how Elasticsearch behaves. For example: &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Expand or shrink the cluster&lt;/li&gt;
  &lt;li&gt;Node maintenance&lt;/li&gt;
  &lt;li&gt;Backup/Restore&lt;/li&gt;
  &lt;li&gt;Shard re-allocation&lt;/li&gt;
  &lt;li&gt;Near disk full behavior &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The setup will be created with the help of: &lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt;, &lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt;, &lt;a href=&quot;https://coreos.com/&quot;&gt;CoreOS&lt;/a&gt; and &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;h2 id=&quot;preparation&quot;&gt;Preparation&lt;/h2&gt;

&lt;p&gt;Make sure you install VirtualBox, Vagrant, and Git. And have them available on your &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check the tools versions.&lt;/p&gt;

&lt;p&gt;VirtualBox:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;VBoxManage --version

4.3.24r98716
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Vagrant:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant version

Installed Version: 1.7.2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Git:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git --version

git version 1.9.5.msysgit.0
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;coreos-and-docker&quot;&gt;CoreOS and Docker&lt;/h3&gt;

&lt;p&gt;CoreOS will be running inside a VirtualBox Virtual Machine. It will be used as our Docker host. Docker will be used to create a Linux container for each Elasticsearch node.&lt;/p&gt;

&lt;p&gt;Install and start CoreOS:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone https://github.com/coreos/coreos-vagrant test-elasticsearch
cd test-elasticsearch
vagrant up
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Open a shell:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Check the Docker version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;docker version

Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.3.3
Git commit (client): a8a31ef-dirty
OS/Arch (client): linux/amd64
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.3.3
Git commit (server): a8a31ef-dirty
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Check the Docker info:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;docker info

Containers: 0
Images: 0
Storage Driver: overlay
 Backing Filesystem: extfs
Execution Driver: native-0.2
Kernel Version: 3.19.0
Operating System: CoreOS 618.0.0
CPUs: 1
Total Memory: 998 MiB
Name: core-01
ID: QLVN:NP7B:SZDN:D7PM:DWNF:364W:O4XA:3JLG:MNJ4:2NFS:L5YU:GUOO
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;

&lt;p&gt;We test the different scenarios in a three node Elasticsearch cluster.&lt;/p&gt;

&lt;p&gt;Each node is run in a Docker container that is based on the &lt;a href=&quot;https://registry.hub.docker.com/u/dockerfile/elasticsearch/&quot;&gt;dockerfile/elasticsearch&lt;/a&gt; image.&lt;/p&gt;

&lt;p&gt;Docker manages the network between the nodes. It does so by creating a pair of veth (virtual Ethernet) interfaces for each container. These form a point-to-point link between the container the host. The host side will be connected to a bridge, which allows the communication between nodes:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;+-- docker0 bridge --+        +-- node0 container --+
|                    |        |                     |  
|      +-----&amp;gt; $node0_veth &amp;lt;----&amp;gt; eth1 interface    |
|      |             |        |                     |
|      |             |        +---------------------+
|      |             |
|      |             |        +-- node1 container --+
|      |             |        |                     |
|      +-----&amp;gt; $node1_veth &amp;lt;----&amp;gt; eth1 interface    |
|      |             |        |                     |
|      |             |        +---------------------+
|      |             |
|      |             |        +-- node2 container --+
|      |             |        |                     |
|      +-----&amp;gt; $node2_veth &amp;lt;----&amp;gt; eth1 interface    |
|                    |        |                     |
+--------------------+        +---------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; This setup allows for multicast, so you don’t have to do anything more for having a working Elasticsearch cluster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; For more details read the &lt;a href=&quot;https://docs.docker.com/articles/networking/&quot;&gt;Docker Network Configuration documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The interface name of each container is saved in a environment variable, e.g., &lt;code&gt;node0_veth&lt;/code&gt;. This will later let us easily fiddle with a node network interface. &lt;/p&gt;

&lt;p&gt;Each container will get its data from a &lt;a href=&quot;https://docs.docker.com/userguide/dockervolumes/&quot;&gt;volume&lt;/a&gt; that is stored on the host. This will let us easily see the logs and index data.&lt;/p&gt;

&lt;p&gt;Each container will also have the normal Elasticsearch 9200 port forwarded to the host, e.g. node 1 will be available at &lt;code&gt;http://localhost:9201&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before you can start the nodes you need the &lt;a href=&quot;https://bitbucket.org/rgl/docker-native-inspect&quot;&gt;docker-native-inspect&lt;/a&gt; tool. Build it with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;curl -o docker-native-inspect.tar.bz2 https://bitbucket.org/rgl/docker-native-inspect/get/default.tar.bz2
mkdir docker-native-inspect
sudo mkdir -p /opt/bin
tar xf docker-native-inspect.tar.bz2 --strip-components&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; -C docker-native-inspect
docker build -t docker-native-inspect docker-native-inspect
docker run --rm docker-native-inspect tar czf - docker-native-inspect &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; tar vxzf - -C /opt/bin
docker-native-inspect -h&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And start the Elasticsearch nodes with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; i in &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; 2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  mkdir -p node&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;data,work,logs,plugins&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
  docker run -d &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    --name&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;node&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    --hostname&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;node&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -p 920&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt;:9200 &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -v &lt;span class=&quot;s2&quot;&gt;&amp;quot;$PWD/node$i:/data&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    dockerfile/elasticsearch &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    /elasticsearch/bin/elasticsearch &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -Des.node.name&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;node&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -Des.path.data&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/data/data &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -Des.path.work&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/data/work &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -Des.path.logs&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/data/logs &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -Des.path.plugins&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/data/plugins &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    -Des.logger.level&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;DEBUG
  &lt;span class=&quot;nb&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;node${i}_veth=`sudo docker-native-inspect -format &amp;#39;{{.network_state.veth_host}}&amp;#39; state node$i`&amp;quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Install some plugins:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; i in &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; 2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; -it node&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; /elasticsearch/bin/plugin --install mobz/elasticsearch-head       &lt;span class=&quot;c&quot;&gt;# /_plugin/head&lt;/span&gt;
  docker &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; -it node&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; /elasticsearch/bin/plugin --install royrusso/elasticsearch-HQ     &lt;span class=&quot;c&quot;&gt;# /_plugin/HQ&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;#docker exec -it node$i /elasticsearch/bin/plugin --install lmenezes/elasticsearch-kopf  # /_plugin/kopf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; Access them at &lt;a href=&quot;http://localhost:9200/_plugin/head&quot;&gt;http://localhost:9200/_plugin/head&lt;/a&gt; or &lt;a href=&quot;http://localhost:9200/_plugin/HQ&quot;&gt;HQ&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you need to access the node, e.g. to inspect something, you can use:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;docker exec -it node0 bash
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create a basic &lt;code&gt;hello&lt;/code&gt; index:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;curl -XPUT http://localhost:9200/hello -d &lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;index:&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;    number_of_shards: 3&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;    number_of_replicas: 1&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Index some documents:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; i in &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;9&lt;/span&gt; 10&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  curl -XPUT http://localhost:9200/hello/message/&lt;span class=&quot;nv&quot;&gt;$i&lt;/span&gt; -d &lt;span class=&quot;s2&quot;&gt;&amp;quot;{\&amp;quot;message\&amp;quot;:\&amp;quot;hello $i\&amp;quot;}&amp;quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To see how things are going, open a different shell, and tail the logs:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;tail -f node*/logs/elasticsearch.log
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Also open the head and HQ pages:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://localhost:9200/_plugin/head
http://localhost:9200/_plugin/HQ
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You are now ready to test the several scenarios!&lt;/p&gt;

&lt;h2 id=&quot;test&quot;&gt;Test&lt;/h2&gt;

&lt;h3 id=&quot;node-network-loss&quot;&gt;Node network loss&lt;/h3&gt;

&lt;p&gt;To simulate a network loss we simply bring the node container veth interface down:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo ip link &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;dev &lt;span class=&quot;nv&quot;&gt;$node1_veth&lt;/span&gt; down&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you now try to refresh the cluster state in the head plugin, you should see it does not really work. After a while, the Elasticsearch logs should starting to display a lot of activity.&lt;/p&gt;

&lt;p&gt;For example, at the master node (in my case this was &lt;code&gt;node2&lt;/code&gt;), things like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[2015-03-14 14:50:55,265][DEBUG][action.admin.cluster.node.stats] [node2] failed to execute on node [gDtJuVYCQ5qHiU-aSKnj7g]
org.elasticsearch.transport.ReceiveTimeoutTransportException: [node1][inet[/10.1.0.12:9300]][cluster:monitor/nodes/stats[n]] request_id [289] timed out after [15002ms]
        at org.elasticsearch.transport.TransportService$TimeoutHandler.run(TransportService.java:366)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

[2015-03-14 14:51:25,263][DEBUG][action.admin.cluster.node.stats] [node2] failed to execute on node [gDtJuVYCQ5qHiU-aSKnj7g]
org.elasticsearch.transport.ReceiveTimeoutTransportException: [node1][inet[/10.1.0.12:9300]][cluster:monitor/nodes/stats[n]] request_id [326] timed out after [15000ms]
        at org.elasticsearch.transport.TransportService$TimeoutHandler.run(TransportService.java:366)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

[2015-03-14 14:51:55,265][DEBUG][action.admin.cluster.node.stats] [node2] failed to execute on node [gDtJuVYCQ5qHiU-aSKnj7g]
org.elasticsearch.transport.ReceiveTimeoutTransportException: [node1][inet[/10.1.0.12:9300]][cluster:monitor/nodes/stats[n]] request_id [363] timed out after [15001ms]
        at org.elasticsearch.transport.TransportService$TimeoutHandler.run(TransportService.java:366)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

[2015-03-14 14:51:58,692][DEBUG][discovery.zen.fd         ] [node2] [node  ] failed to ping [[node1][gDtJuVYCQ5qHiU-aSKnj7g][node1][inet[/10.1.0.12:9300]]], tried [3] times, each with  maximum [30s] timeout

[2015-03-14 14:51:58,700][DEBUG][cluster.service          ] [node2] processing [zen-disco-node_failed([node1][gDtJuVYCQ5qHiU-aSKnj7g][node1][inet[/10.1.0.12:9300]]), reason failed to ping, tried [3] times, each with maximum [30s] timeout]: execute

[2015-03-14 14:51:58,726][DEBUG][cluster.service          ] [node2] cluster state updated, version [11], source [zen-disco-node_failed([node1][gDtJuVYCQ5qHiU-aSKnj7g][node1][inet[/10.1.0.12:9300]]), reason failed to ping, tried [3] times, each with maximum [30s] timeout]

[2015-03-14 14:51:58,732][INFO ][cluster.service          ] [node2] removed {[node1][gDtJuVYCQ5qHiU-aSKnj7g][node1][inet[/10.1.0.12:9300]],}, reason: zen-disco-node_failed([node1][gDtJuVYCQ5qHiU-aSKnj7g][node1][inet[/10.1.0.12:9300]]), reason failed to ping, tried [3] times, each with maximum [30s] timeout

[2015-03-14 14:51:58,732][DEBUG][cluster.service          ] [node2] publishing cluster state version 11&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After which the cluster will scramble to recover the lost shards in the remaining nodes.&lt;/p&gt;

&lt;p&gt;And on &lt;code&gt;node1&lt;/code&gt; (the one we cut the network cable) will have something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[2015-03-14 14:51:58,847][DEBUG][discovery.zen.fd         ] [node1] [master] failed to ping [[node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]]], tried [3] times, each with maximum [30s] timeout

[2015-03-14 14:51:58,851][DEBUG][discovery.zen.fd         ] [node1] [master] stopping fault detection against master [[node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]]], reason [master failure, failed to ping, tried [3] times, each with  maximum [30s] timeout]

[2015-03-14 14:51:58,854][INFO ][discovery.zen            ] [node1] master_left [[node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]]], reason [failed to ping, tried [3] times, each with  maximum [30s] timeout]

[2015-03-14 14:51:58,868][DEBUG][cluster.service          ] [node1] processing [zen-disco-master_failed ([node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]])]: execute

[2015-03-14 14:51:58,870][WARN ][discovery.zen            ] [node1] master left (reason = failed to ping, tried [3] times, each with  maximum [30s] timeout), current nodes: {[node0][tu2reCtdT2Shekx0gitB1g][node0][inet[/10.1.0.11:9300]],[node1][gDtJuVYCQ5qHiU-aSKnj7g][node1][inet[/10.1.0.12:9300]],}

[2015-03-14 14:51:58,898][DEBUG][cluster.service          ] [node1] cluster state updated, version [10], source [zen-disco-master_failed ([node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]])]

[2015-03-14 14:51:58,903][INFO ][cluster.service          ] [node1] removed {[node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]],}, reason: zen-disco-master_failed ([node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]])

[2015-03-14 14:51:58,918][DEBUG][cluster.service          ] [node1] set local cluster state to version 10

[2015-03-14 14:51:58,968][DEBUG][cluster.service          ] [node1] processing [zen-disco-master_failed ([node2][E3MoSOWDSDW_8AdCPznakg][node2][inet[/10.1.0.13:9300]])]: done applying updated cluster_state (version: 10)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After a while &lt;code&gt;node1&lt;/code&gt; will be marked as failed by &lt;code&gt;node2&lt;/code&gt; and will no longer be pinged. Which means, it has to manually re-join the cluster. &lt;/p&gt;

&lt;p&gt;After a while &lt;code&gt;node1&lt;/code&gt; will elect itself as a master:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2015-03-14 14:53:03,491&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;DEBUG&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;cluster.service          &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;node1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; cluster state updated, version &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;11&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;zen-disco-join &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;elected_as_master&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2015-03-14 14:53:03,491&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;INFO &lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;cluster.service          &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;node1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; new_master &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;node1&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;gDtJuVYCQ5qHiU-aSKnj7g&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;node1&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;inet&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;/10.1.0.12:9300&lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;, reason: zen-disco-join &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;elected_as_master&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2015-03-14 14:53:03,492&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;DEBUG&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;cluster.service          &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;node1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; publishing cluster state version 11

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;2015-03-14 14:53:33,504&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;WARN &lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;discovery.zen.publish    &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;node1&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; timed out waiting &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; all nodes to process published state &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;11&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;timeout &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;30s&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, pending nodes: &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt;node0&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;tu2reCtdT2Shekx0gitB1g&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;node0&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;inet&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;/10.1.0.11:9300&lt;span class=&quot;o&quot;&gt;]]])&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Which is somewhat odd. But this happens because the &lt;a href=&quot;http://www.elastic.co/guide/en/elasticsearch/reference/current/modules-discovery-zen.html#master-election&quot;&gt;&lt;code&gt;discovery.zen.minimum_master_nodes&lt;/code&gt;&lt;/a&gt; key was not changed from the default of &lt;code&gt;1&lt;/code&gt;. You should probably increase that value.&lt;/p&gt;

&lt;p&gt;Bring the interface back up to the network:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo ip link &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;dev &lt;span class=&quot;nv&quot;&gt;$node1_veth&lt;/span&gt; up&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You’ll notice that the node will not re-join the other nodes in the cluster. You have to manually restart it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;docker stop node1
docker start node1
&lt;span class=&quot;nb&quot;&gt;declare&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;node1_veth=`sudo docker-native-inspect -format &amp;#39;{{.network_state.veth_host}}&amp;#39; state node1`&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And it should now join the cluster.&lt;/p&gt;

&lt;h3 id=&quot;packet-delay-andor-loss&quot;&gt;Packet delay and/or loss&lt;/h3&gt;

&lt;p&gt;Linux lets you fiddle with the network stack in several ways. One of them lets you delay or discard packets. &lt;/p&gt;

&lt;p&gt;You can influence the entire communication between all nodes by changing the &lt;code&gt;bridge0&lt;/code&gt; interface. You can also do it for a single node by changing the corresponding veth interface. &lt;/p&gt;

&lt;p&gt;For example, to add 100ms+-10ms delay to all packets:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo tc qdisc add dev docker0 root netem delay 100ms 10ms
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To change it to have 25% pseudo-correlation:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo tc qdisc change dev docker0 root netem delay 100ms 10ms 25%
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To change it to have 1% of packet loss:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo tc qdisc change dev docker0 root netem loss 1%
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To change it to combine delay and loss:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo tc qdisc change dev docker0 root netem delay 100ms 10ms 25% loss 1%
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To see all rules:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo tc qdisc show dev docker0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To remove all rules:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo tc qdisc del dev docker0 root
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To apply the above examples to a specific node, instead of the &lt;code&gt;docker0&lt;/code&gt; device use the corresponding veth device, e.g. &lt;code&gt;$node2_veth&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For more information see:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.linuxfoundation.org/collaborate/workgroups/networking/netem&quot;&gt;Linux Network Emulation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.archlinux.org/index.php/Advanced_traffic_control&quot;&gt;Linux Traffic Control&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.docker.com/articles/networking/&quot;&gt;Docker networking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Sun, 15 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/testing-the-elasticsearch-cluster-behavior-under-network-failure.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/testing-the-elasticsearch-cluster-behavior-under-network-failure.html</guid>
        
        
      </item>
    
      <item>
        <title>Bootstrapping your GitHub Pages blog with Vagrant</title>
        <description>&lt;p&gt;This will show you a way of creating a &lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt; Virtual Machine with the tools needed for generating a blog based on the &lt;a href=&quot;https://pages.github.com/&quot;&gt;GitHub Pages&lt;/a&gt; stack. GitHub Pages uses the &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; static site generator. This VM will use the same version of the tools that are &lt;a href=&quot;https://github.com/github/pages-gem&quot;&gt;currently in use&lt;/a&gt; at GitHub.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;The base Vagrant box is based on the one created in &lt;a href=&quot;/from-iso-to-vagrant-box.html&quot;&gt;From Iso To Vagrant Box&lt;/a&gt; post (read it first) but with a Xubuntu desktop.&lt;/p&gt;

&lt;p&gt;You need to modify the base box to install the &lt;code&gt;xubuntu-desktop&lt;/code&gt; package. For that, modify the preseed &lt;code&gt;pkgsel/include&lt;/code&gt; line to include its package name:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vi preseed.txt
...
d-i pkgsel/include string openssh-server, xubuntu-desktop
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Build the image, and add it to Vagrant:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;packer build ubuntu-14.10.json
vagrant box add xubuntu-14.10-amd64 ubuntu-14.10-amd64-virtualbox.box
rm ubuntu-14.10-amd64-virtualbox.box&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create the &lt;code&gt;Vagrantfile&lt;/code&gt; that provisions the GitHub Pages tools:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;n&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;VAGRANTFILE&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Vagrantfile&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# -*- mode: ruby -*-&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# vi: set ft=ruby :&lt;/span&gt;

&lt;span class=&quot;vg&quot;&gt;$root_provision_script&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ROOT_PROVISION_SCRIPT&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# abort this script on errors.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;set -eux&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# prevent apt-get et al from opening stdin.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# NB even with this, you&amp;#39;ll still get some warnings that you can ignore:&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;#     dpkg-preconfigure: unable to re-open stdin: No such file or directory&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;export DEBIAN_FRONTEND=noninteractive&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install javascript support for Jekyll.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;# See https://github.com/sstephenson/execjs&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get -y install software-properties-common&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-add-repository -y ppa:chris-lea/node.js&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get update&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get -y install nodejs&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install git. we&amp;#39;ll use it to later push the blog to github.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get -y install git&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install ungit. a web-based gui for git.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;npm install -g ungit&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install retext. a Markdown editor.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get -y install retext&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install ruby. Jekyll is a ruby application.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get -y install ruby-dev ruby&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install dependencies needed for the gems.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;apt-get -y install zlib1g-dev&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;# install Jekyll -- the version that is currently hosted by GitHub.&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;gem install --verbose github-pages&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;ROOT_PROVISION_SCRIPT&lt;/span&gt;

&lt;span class=&quot;no&quot;&gt;Vagrant&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;box&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;xubuntu-14.10-amd64&amp;quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hostname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;pages&amp;quot;&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;virtualbox&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;vb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gui&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;provision&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shell&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$root_provision_script&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;VAGRANTFILE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; This blog has a similar &lt;a href=&quot;https://github.com/rgl/rgl.github.io/blob/master/Vagrantfile&quot;&gt;Vagrantfile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enter the VM and &lt;a href=&quot;https://help.github.com/articles/generating-ssh-keys/&quot;&gt;generate&lt;/a&gt; a SSH key-pair:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vagrant ssh
ssh-keygen
cat ~/.ssh/id_rsa.pub&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Add the public key (the content of the &lt;code&gt;id_rsa.pub&lt;/code&gt; file) into your GitHub account at:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/settings/ssh&quot;&gt;https://github.com/settings/ssh&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also create a new empty repository named after your username, e.g. &lt;code&gt;example.github.io&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; From here on I’ll use &lt;code&gt;example&lt;/code&gt; as your username.&lt;/p&gt;

&lt;p&gt;Setup git:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git config --global user.name &lt;span class=&quot;s2&quot;&gt;&amp;quot;Example Doe&amp;quot;&lt;/span&gt;
git config --global user.email example@example.com
git config --global push.default simple
git config --list&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Test that it works:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;ssh -T git@github.com&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Initialize the blog:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git clone git@github.com:example/example.github.io.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;example.github.io
jekyll new .&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Start the server:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;jekyll serve&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And access the blog at:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://localhost:4000&quot;&gt;http://localhost:4000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At another shell, open a file, edit and save it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vi blog/about.md&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After you save a file Jekyll should re-generate the blog. To see the result just refresh the browser page.&lt;/p&gt;

&lt;p&gt;When you are ready, push the changes to the world:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;git add --all
git commit -m &lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello World!&amp;#39;&lt;/span&gt;
git push&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After a couple of minutes the blog should be live at:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://example.github.io
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that’s it!&lt;/p&gt;
</description>
        <pubDate>Fri, 13 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/bootstrapping-your-github-pages-blog-with-vagrant.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/bootstrapping-your-github-pages-blog-with-vagrant.html</guid>
        
        
      </item>
    
      <item>
        <title>From Iso To Vagrant Box</title>
        <description>&lt;p&gt;This is my recipe on how to automatically create an up-to-date Ubuntu Vagrant box file from an iso.&lt;/p&gt;

&lt;p&gt;You need the following ingredients:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.ubuntu.com/community/Installation/MinimalCD&quot;&gt;Ubuntu minimal ISO&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://packer.io/&quot;&gt;Packer&lt;/a&gt; &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use the minimal ISO because the regular ISO does not always contains the latest package versions, so you’ll not end up having to update your system just right after you install it. This is because the mini ISO installs the latest packages right of the internet; it is also much smaller than the regular ISO. &lt;/p&gt;

&lt;p&gt;Packer is used to install Ubuntu into a Vagrant box file. Packer uses a &lt;a href=&quot;https://packer.io/docs/basics/terminology.html#Templates&quot;&gt;template file&lt;/a&gt; to describe that process. The template uses a &lt;a href=&quot;https://wiki.debian.org/DebianInstaller/Preseed&quot;&gt;preseed&lt;/a&gt; file to drive the Debian installer (aka &lt;em&gt;d-i&lt;/em&gt;) to automatically install Ubuntu in a VirtualBox Virtual Machine, which will be later exported into a Vagrant box file.&lt;/p&gt;

&lt;p&gt;Vagrant is used to automatically create and setup (or provision) a development environment inside a Virtual Machine. Vagrant uses a &lt;a href=&quot;http://docs.vagrantup.com/v2/vagrantfile/&quot;&gt;Vagrantfile&lt;/a&gt; script to describe that process.&lt;/p&gt;

&lt;p&gt;VirtualBox is used to actually run the Virtual Machine.&lt;/p&gt;

&lt;p&gt;You can find the sources at &lt;a href=&quot;https://github.com/rgl/ubuntu-vagrant&quot;&gt;rgl/ubuntu-vagrant&lt;/a&gt;, but read along to known more details.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;The following sections assume that you already have Packer, Vagrant and VirtualBox installed and available on your &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;packer-template&quot;&gt;Packer Template&lt;/h2&gt;

&lt;p&gt;Create the template:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;nx&quot;&gt;cat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ubuntu&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;14.10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;variables&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;disk_size&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8192&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;builders&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;amd64-virtualbox&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;virtualbox-iso&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;guest_os_type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Ubuntu_64&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;guest_additions_mode&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;attach&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;headless&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;http_directory&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;vboxmanage&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;{{.Name}}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--memory&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2048&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;{{.Name}}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--cpus&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;modifyvm&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;{{.Name}}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;--vram&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;32&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;disk_size&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;{{user `disk_size`}}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;hard_drive_interface&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;sata&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;iso_url&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://archive.ubuntu.com/ubuntu/dists/utopic/main/installer-amd64/current/images/netboot/mini.iso&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;iso_checksum&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;4f783f3917ed4c663c9a983f4ee046fc&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;iso_checksum_type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;md5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;ssh_username&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;vagrant&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;ssh_password&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;vagrant&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;ssh_wait_timeout&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;60m&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;boot_wait&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;5s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;boot_command&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;esc&amp;gt;&amp;lt;wait&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;/linux initrd=/initrd.gz&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; nofb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; fb=false&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; auto=true&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; url=http://{{.HTTPIP}}:{{.HTTPPort}}/preseed.txt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; hostname=vagrant&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; DEBCONF_DEBUG=5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; --&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot; nofb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;enter&amp;gt;&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;shutdown_command&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;echo vagrant | sudo -S poweroff&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;

  &lt;span class=&quot;s2&quot;&gt;&amp;quot;provisioners&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shell&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;execute_command&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;echo vagrant | sudo -S bash {{.Path}}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;scripts&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;setup.sh&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;

  &lt;span class=&quot;s2&quot;&gt;&amp;quot;post-processors&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;vagrant&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&amp;quot;output&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;ubuntu-14.10-{{.BuildName}}.box&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;notes&quot;&gt;Notes&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;To known the available boot options open the &lt;code&gt;boot/grub/grub.cfg&lt;/code&gt; file inside the &lt;code&gt;mini.iso&lt;/code&gt; file.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;While d-i is installing Ubuntu you can press &lt;code&gt;alt+f2&lt;/code&gt; to open a shell and inspect the environment. e.g. &lt;code&gt;cat /proc/cmdline ; env ; ls -l /target&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can also press &lt;code&gt;alt+f4&lt;/code&gt; to see what is going on (its a console running &lt;code&gt;tail -f /var/log/syslog&lt;/code&gt;). Press &lt;code&gt;alt+f1&lt;/code&gt; to return to the d-i.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;code&gt;DEBCONF_DEBUG=5&lt;/code&gt; was added into the &lt;a href=&quot;https://github.com/torvalds/linux/blob/master/Documentation/kernel-parameters.txt&quot;&gt;kernel command line&lt;/a&gt; to aid us in debugging the preseed installation. At install time, when d-i asks a question, look at the last debconf variable that is mentioned on syslog (press &lt;code&gt;alt+f4&lt;/code&gt;), its probably the one you need to set to answer the question.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;At a console, to change the keyboard map, type e.g. &lt;code&gt;loadkeys pt&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You only have the Nano text editor on the install console. To search text inside it press &lt;code&gt;ctrl+w&lt;/code&gt;. To repeat the search press &lt;code&gt;alt+w&lt;/code&gt;. To search backwards press &lt;code&gt;alt+b&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;preseed&quot;&gt;Preseed&lt;/h2&gt;

&lt;p&gt;Create the preseed:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cat&amp;lt;&amp;lt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&amp;gt;preseed.txt
&lt;span class=&quot;c&quot;&gt;# save the log for debugging purposes.&lt;/span&gt;
d-i preseed/late_command string cp /var/log/syslog /target/home/vagrant/preseed.log

d-i debian-installer/locale string en_US.UTF-8
d-i localechooser/supported-locales multiselect en_US.UTF-8, pt_PT.UTF-8

d-i keyboard-configuration/layoutcode string pt
d-i console-setup/ask_detect boolean &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;

d-i mirror/country string manual
d-i mirror/http/hostname string nl.archive.ubuntu.com
d-i mirror/http/directory string /ubuntu
d-i mirror/http/proxy string

d-i clock-setup/utc boolean &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
d-i &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;/zone string Europe/Lisbon

d-i partman-auto/method string regular
d-i partman-auto/choose_recipe &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; atomic
d-i partman-partitioning/confirm_write_new_label boolean &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
d-i partman/choose_partition &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; finish
d-i partman/confirm boolean &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
d-i partman/confirm_nooverwrite boolean &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;

d-i grub-installer/only_debian boolean &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
d-i finish-install/reboot_in_progress note

d-i passwd/user-fullname string vagrant
d-i passwd/username string vagrant
d-i passwd/user-password password vagrant
d-i passwd/user-password-again password vagrant
d-i user-setup/allow-password-weak boolean &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;
d-i user-setup/encrypt-home boolean &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;

tasksel tasksel/first multiselect
d-i pkgsel/include string openssh-server
d-i pkgsel/upgrade &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; full-upgrade
d-i pkgsel/update-policy &lt;span class=&quot;k&quot;&gt;select&lt;/span&gt; none
EOF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;notes-1&quot;&gt;Notes&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Also see the &lt;a href=&quot;https://help.ubuntu.com/14.10/installation-guide/example-preseed.txt&quot;&gt;example preseed&lt;/a&gt; at the Ubuntu Installation Guide.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A &lt;code&gt;preseed/late_command&lt;/code&gt; was added to aid in debugging the preseed; it creates a &lt;code&gt;preseed.log&lt;/code&gt; file with what happened at preseed.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;keyboard-configuration/layoutcode&lt;/code&gt; accepts similar values as &lt;a href=&quot;http://manpages.ubuntu.com/manpages/utopic/en/man1/loadkeys.1.html&quot;&gt;loadkeys(1)&lt;/a&gt;, e.g. &lt;code&gt;us&lt;/code&gt;, &lt;code&gt;pt&lt;/code&gt;, etc.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;time/zone&lt;/code&gt; accepts a filename relative to the &lt;code&gt;/usr/share/zoneinfo/&lt;/code&gt; directory.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code&gt;tasksel/first&lt;/code&gt; is a comma separated list, .e.g. &lt;code&gt;ubuntu-server, xubuntu-desktop&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;You can later add support for other locales. e.g. I like to use &lt;a href=&quot;https://code.google.com/p/conemu-maximus5/&quot;&gt;ConEmu&lt;/a&gt; and it does not support UTF-8 at all, so I do:&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo sh -c &lt;span class=&quot;s1&quot;&gt;&amp;#39;echo en_US.ISO-8859-15 ISO-8859-15 &amp;gt;&amp;gt; /var/lib/locales/supported.d/local&amp;#39;&lt;/span&gt;
sudo sudo dpkg-reconfigure locales
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LANG&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;en_US.ISO-8859-15 &lt;span class=&quot;nv&quot;&gt;LANGUAGE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;en_US
&lt;span class=&quot;c&quot;&gt;#sudo sh -c &amp;quot;echo &amp;#39;LANG=$LANG&amp;#39; &amp;gt; /etc/default/locale&amp;quot; # optional. maybe just do this on your .bashrc&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;provisioning-script&quot;&gt;Provisioning script&lt;/h2&gt;

&lt;p&gt;Create the provisioning script:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cat&amp;lt;&amp;lt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ENDSETUP&amp;quot;&lt;/span&gt;&amp;gt;setup.sh
&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# abort this script when a command fails or a unset variable is used.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; -eu
&lt;span class=&quot;c&quot;&gt;# echo all the executed commands.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt; -x

&lt;span class=&quot;c&quot;&gt;# let our user use root permissions without sudo asking for a password (because&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# d-i adds us into the sudo group, but we must be on the admin group instead).&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# alternatively: echo &amp;#39;vagrant ALL=(ALL) NOPASSWD:ALL&amp;#39; &amp;gt; /etc/sudoers.d/vagrant&lt;/span&gt;
groupadd -r admin
usermod -a -G admin vagrant
gpasswd -d vagrant sudo
sed -i -e &lt;span class=&quot;s1&quot;&gt;&amp;#39;s,%admin ALL=(ALL) ALL,%admin ALL=(ALL) NOPASSWD:ALL,g&amp;#39;&lt;/span&gt; /etc/sudoers

&lt;span class=&quot;c&quot;&gt;# installing the vagrant public key.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# NB vagrant will replace it on the first run.&lt;/span&gt;
install -d -m &lt;span class=&quot;m&quot;&gt;700&lt;/span&gt; /home/vagrant/.ssh
&lt;span class=&quot;nb&quot;&gt;pushd&lt;/span&gt; /home/vagrant/.ssh
wget --no-check-certificate https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -O authorized_keys
chmod &lt;span class=&quot;m&quot;&gt;600&lt;/span&gt; ~/.ssh/authorized_keys
chown -R vagrant:vagrant .

&lt;span class=&quot;c&quot;&gt;# install the VirtualBox Guest Additions.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# this will be installed at /opt/VBoxGuestAdditions-VERSION.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# REMOVE_INSTALLATION_DIR=0 is to fix a bug in VBoxLinuxAdditions.run.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# See http://stackoverflow.com/a/25943638.&lt;/span&gt;
apt-get -y -q install gcc dkms
mkdir -p /mnt
mount /dev/sr1 /mnt
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; ! -f /mnt/VBoxLinuxAdditions.run &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; sleep 1&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;REMOVE_INSTALLATION_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; /mnt/VBoxLinuxAdditions.run --target /tmp/VBoxGuestAdditions
rm -rf /tmp/VBoxGuestAdditions
umount /mnt

&lt;span class=&quot;c&quot;&gt;# disable the DNS reverse lookup on the SSH server. this stops it from&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# trying to resolve the client IP address into a DNS domain name, which&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# is kinda slow and does not normally work when running inside VB.&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;UseDNS no &amp;gt;&amp;gt; /etc/ssh/sshd_config

&lt;span class=&quot;c&quot;&gt;# disable the graphical terminal. its kinda slow and useless on a VM.&lt;/span&gt;
sed -i -E &lt;span class=&quot;s1&quot;&gt;&amp;#39;s,#(GRUB_TERMINAL\s*=).*,\1console,g&amp;#39;&lt;/span&gt; /etc/default/grub
update-grub

&lt;span class=&quot;c&quot;&gt;# use the up/down arrows to navigate the bash history.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# NB to get these codes, press ctrl+v then the key combination you want.&lt;/span&gt;
cat&amp;lt;&amp;lt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&amp;gt;&amp;gt;/etc/inputrc
&lt;span class=&quot;s2&quot;&gt;&amp;quot;\e[A&amp;quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;history&lt;/span&gt;-search-backward
&lt;span class=&quot;s2&quot;&gt;&amp;quot;\e[B&amp;quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;history&lt;/span&gt;-search-forward
&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;show-all-if-ambiguous on
&lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;completion-ignore-case on
EOF

&lt;span class=&quot;c&quot;&gt;# clean packages.&lt;/span&gt;
apt-get -y autoremove
apt-get -y clean

&lt;span class=&quot;c&quot;&gt;# zero the free disk space -- for better compression of the box file.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#dd if=/dev/zero of=/EMPTY bs=1M ; rm -f /EMPTY&lt;/span&gt;
ENDSETUP&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;build&quot;&gt;Build&lt;/h2&gt;

&lt;p&gt;Build it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;packer validate ubuntu-14.10.json
packer inspect ubuntu-14.10.json
&lt;span class=&quot;c&quot;&gt;#time packer build -var disk_size=81920 ubuntu-14.10.json&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;packer build ubuntu-14.10.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; you can also modify the disk size with the &lt;code&gt;disk_size&lt;/code&gt; &lt;a href=&quot;https://www.packer.io/docs/templates/user-variables.html&quot;&gt;user variable&lt;/a&gt;. e.g. for 80GB, build with: &lt;code&gt;packer build -var disk_size=81920 ubuntu-14.10.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; the box will compress to about 720MB (with 1.2G of used space).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; in my machine, the build took about 15 minutes to create the final box file.&lt;/p&gt;

&lt;p&gt;Add the box to vagrant:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vagrant box add ubuntu-14.10-amd64 ubuntu-14.10-amd64-virtualbox.box
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;test&quot;&gt;Test&lt;/h2&gt;

&lt;p&gt;Create a test VM based on our created box:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;mkdir -p &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd test&lt;/span&gt;
vagrant init ubuntu-14.10-amd64
&lt;span class=&quot;nb&quot;&gt;time &lt;/span&gt;vagrant up&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; in my machine, this takes about 45 seconds to boot.&lt;/p&gt;

&lt;p&gt;Connect to the console, and kick the tires:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vagrant ssh
uname -a
id
df -h
less preseed.log
cat /proc/cmdline
dmesg
&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Poweroff the VM, and destroy it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vagrant halt
vagrant destroy
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..
rm -rf &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you no longer need the box in vagrant, you can also remove it with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;vagrant box remove ubuntu-14.10-amd64&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that’s it!&lt;/p&gt;

&lt;p&gt;You could now proceed on how to &lt;a href=&quot;/bootstrapping-your-github-pages-blog-with-vagrant.html&quot;&gt;bootstrap a GitHub Pages blog inside a Xubuntu desktop&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Thu, 12 Mar 2015 00:00:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/from-iso-to-vagrant-box.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/from-iso-to-vagrant-box.html</guid>
        
        
      </item>
    
      <item>
        <title>From zero to a blank world map</title>
        <description>&lt;p&gt;When you need to show a web map you normally end up using something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;map&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;38.736946&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;9.142685&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tileLayer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;http://{s}.tile.osm.org/{z}/{x}/{y}.png&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But what does it take to show that map? What software stack lays behind the curtains? And how can you customize the map? Lets find out!&lt;/p&gt;

&lt;p&gt;We start from a vanilla Linux Virtual Machine and end up showing a humble web map – a blank world – the hello world of maps.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;&lt;strong&gt;Be warned&lt;/strong&gt; that I barely describe the terms used in the &lt;a href=&quot;http://en.wikipedia.org/wiki/Geographic_information_system&quot;&gt;GIS&lt;/a&gt; world. Be sure to read the referenced material for more information.&lt;/p&gt;

&lt;p&gt;So, lets get cooking!&lt;/p&gt;

&lt;h1 id=&quot;ingredients&quot;&gt;Ingredients&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://xubuntu.org/&quot;&gt;Xubuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mapbox.com/mapbox-studio/&quot;&gt;Mapbox Studio&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://openstreetmapdata.com/data/water-polygons&quot;&gt;OpenStreetMap Coastline data&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mojodna/tessera&quot;&gt;Tessera&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mapbox.com/mapbox.js/&quot;&gt;Mapbox.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;recipe&quot;&gt;Recipe&lt;/h1&gt;

&lt;h2 id=&quot;install-xubuntu&quot;&gt;Install Xubuntu&lt;/h2&gt;

&lt;p&gt;Install &lt;a href=&quot;http://xubuntu.org/&quot;&gt;Xubuntu&lt;/a&gt; 14.10 (Utopic Unicorn) from &lt;a href=&quot;http://torrent.ubuntu.com/xubuntu/releases/utopic/release/desktop/xubuntu-14.10-desktop-amd64.iso.torrent&quot;&gt;torrent&lt;/a&gt; on a &lt;a href=&quot;https://www.virtualbox.org/&quot;&gt;VirtualBox&lt;/a&gt; VM.&lt;/p&gt;

&lt;p&gt;Make sure you give it some respectful resources. I gave mine:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;60GB of disk&lt;/li&gt;
  &lt;li&gt;4GB of memory&lt;/li&gt;
  &lt;li&gt;2 CPUs&lt;/li&gt;
  &lt;li&gt;64MB of video memory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After install, bring it up to date. Open a Terminal Emulator and type:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo apt-get update
sudo apt-get upgrade
sudo apt-get clean
sudo reboot&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Install the VirtualBox &lt;a href=&quot;https://www.virtualbox.org/manual/ch04.html&quot;&gt;Guest Additions&lt;/a&gt;. On the VM VirtualBox UI select &lt;code&gt;Devices&lt;/code&gt;, &lt;code&gt;Insert Guest Additions CD Image...&lt;/code&gt;. Xubuntu should automatically mount the CD. Open a terminal and type:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo apt-get install dkms
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /media/&lt;span class=&quot;nv&quot;&gt;$USER&lt;/span&gt;/VBOX*
sudo ./VBoxLinuxAdditions.run
sudo reboot&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In order to copy the commands from this article into the VM you should enable the shared clipboard. On the VM VirtualBox UI select the &lt;code&gt;Devices&lt;/code&gt;, &lt;code&gt;Shared Clipboard&lt;/code&gt;, &lt;code&gt;Bidirectional&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;mapbox-studio&quot;&gt;Mapbox Studio&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.mapbox.com/mapbox-studio/&quot;&gt;Studio&lt;/a&gt; is used to quickly style maps.&lt;/p&gt;

&lt;p&gt;Install it with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo apt-add-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs

sudo apt-get install git
git clone https://github.com/mapbox/mapbox-studio.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mapbox-studio
npm install&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; I’ve got revision &lt;a href=&quot;https://github.com/mapbox/mapbox-studio/commit/953ecc35ff6eca3fb5f1caf099ec46f85e86c60c&quot;&gt;953ecc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Start Studio:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;npm start&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the Terminal, Right-Click the &lt;a href=&quot;http://localhost:3000&quot;&gt;http://localhost:3000&lt;/a&gt; text and select &lt;code&gt;Open Link&lt;/code&gt;. Or open the Firefox Web Browser
from the Xfce menu. Or in a second Terminal type:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;exo-open http://localhost:3000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Follow the application steps to create a free Mapbox account. After that, you are ready to use Studio.&lt;/p&gt;

&lt;h2 id=&quot;coastline-data&quot;&gt;Coastline data&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Coastline&quot;&gt;Coastline&lt;/a&gt; is the line where the land meets the sea. We’ll use it to draw the world outline on our map.&lt;/p&gt;

&lt;p&gt;The Coastline data is maintained by the &lt;a href=&quot;http://www.openstreetmap.org/copyright&quot;&gt;OpenStreetMap contributors&lt;/a&gt;. Its periodically extracted from OpenStreetMap and made available at the &lt;a href=&quot;http://openstreetmapdata.com&quot;&gt;OpenStreetMap Data&lt;/a&gt; site as a &lt;a href=&quot;http://en.wikipedia.org/wiki/Shapefile&quot;&gt;Shapefile&lt;/a&gt; – created by the &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/OSMCoastline&quot;&gt;OSMCoastline&lt;/a&gt; application.&lt;/p&gt;

&lt;p&gt;This data is available in two different projections (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/Spatial_reference_system&quot;&gt;SRS&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://epsg.io/4326&quot;&gt;EPSG:4326&lt;/a&gt; (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/World_Geodetic_System&quot;&gt;WGS84&lt;/a&gt;). Used in &lt;a href=&quot;http://en.wikipedia.org/wiki/Global_Positioning_System&quot;&gt;GPS&lt;/a&gt; and &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Projection&quot;&gt;raw OpenStreetMap data&lt;/a&gt; found on &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Planet.osm&quot;&gt;Planet.osm&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://epsg.io/3857&quot;&gt;EPSG:3857&lt;/a&gt; (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_Mercator&quot;&gt;Web Mercator or Spherical Mercator&lt;/a&gt; aka &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_Mercator#OpenLayers:900913&quot;&gt;900913&lt;/a&gt;). Used in web maps (e.g. Google/Bing/Leaftlet/Mapbox.js).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; You should prefer EPSG:3857 because its the one normally used in web maps – no re-projection will be needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; Be sure to known your coordinates projection – otherwise confusion will surely arise!&lt;/p&gt;

&lt;p&gt;Download the Coastline &lt;a href=&quot;http://openstreetmapdata.com/data/water-polygons&quot;&gt;water polygons&lt;/a&gt; Shapefile (~390MB) – EPSG:3857 projection:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo apt-get install curl
curl -O http://data.openstreetmapdata.com/water-polygons-split-3857.zip
unzip water-polygons-split-3857.zip&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And index it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;~/mapbox-studio/node_modules/mapnik/lib/binding/node-v11-linux-*/shapeindex water-polygons-split-3857/water_polygons.shp&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;source&quot;&gt;Source&lt;/h2&gt;

&lt;p&gt;To show any data in Studio we need to have a &lt;a href=&quot;https://www.mapbox.com/mapbox-studio/source-quickstart/&quot;&gt;Source&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; A Studio Source handles both of the projections mentioned before. But if you use EPSG:3857 no re-projection will be needed.&lt;/p&gt;

&lt;p&gt;To create one, go to Studio, and:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click the &lt;code&gt;Projects&lt;/code&gt; icon (bottom-left corner).&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;New Project&lt;/code&gt; icon.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Blank source&lt;/code&gt; icon (right column).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a new layer for the data:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click the &lt;code&gt;New Layer&lt;/code&gt; icon (top-right).&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Browse&lt;/code&gt; button and select the &lt;code&gt;water-polygons-split-3857/water_polygons.shp&lt;/code&gt; file.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;rename&lt;/code&gt; link and rename the layer to &lt;code&gt;coastalarea&lt;/code&gt;. You will later use it in a stylesheet selector as &lt;code&gt;#coastalarea&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Done&lt;/code&gt; button.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Change the project settings:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click the &lt;code&gt;Settings&lt;/code&gt; button (left toolbar).&lt;/li&gt;
  &lt;li&gt;Change the Maxzoom value to &lt;code&gt;22&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Save as&lt;/code&gt; button (left toolbar).&lt;/li&gt;
  &lt;li&gt;Save the Source project as &lt;code&gt;blank-world&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should now have on your disk a &lt;code&gt;blank-world.tm2source&lt;/code&gt; directory. It contains all the Source project files.&lt;/p&gt;

&lt;p&gt;You are now ready to create a Style project.&lt;/p&gt;

&lt;h2 id=&quot;style&quot;&gt;Style&lt;/h2&gt;

&lt;p&gt;Maps are styled with &lt;a href=&quot;https://github.com/mapbox/carto&quot;&gt;CartoCSS&lt;/a&gt; – a language similar to &lt;a href=&quot;http://en.wikipedia.org/wiki/Cascading_Style_Sheets&quot;&gt;CSS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lets use it to style the map.&lt;/p&gt;

&lt;p&gt;Go to Studio and create a new &lt;a href=&quot;https://www.mapbox.com/mapbox-studio/style-quickstart/&quot;&gt;Style&lt;/a&gt; project:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click the &lt;code&gt;Projects&lt;/code&gt; icon (bottom-left corner).&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;New Project&lt;/code&gt; icon.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Basic&lt;/code&gt; style icon (left column).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should now see a basic map; but we want to use our own Source, so:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Click the &lt;code&gt;Layers&lt;/code&gt; icon.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Change source&lt;/code&gt; icon.&lt;/li&gt;
  &lt;li&gt;Toggle the Sources to &lt;code&gt;Local&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Select the &lt;code&gt;blank-world.tm2source&lt;/code&gt; Source that we’ve created before.&lt;/li&gt;
  &lt;li&gt;Click the &lt;code&gt;Save as&lt;/code&gt; button (left toolbar). And save the project as &lt;code&gt;blank-world&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On your disk, you should now have a &lt;code&gt;blank-world.tm2&lt;/code&gt; directory. It contains all the Style project files.&lt;/p&gt;

&lt;p&gt;You should also notice a &lt;code&gt;Style&lt;/code&gt; pane on the right hand side of the window. It contains the stylesheet that is used to style the map. Replace the text with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;k&quot;&gt;@land&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#f8f4f0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@water&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#a0c8f0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;Map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;land&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;#coastalarea&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;water&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;polygon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;water&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Save the Project (press Ctrl+S).&lt;/p&gt;

&lt;p&gt;After a bit, you should see a map!&lt;/p&gt;

&lt;h2 id=&quot;tile-server&quot;&gt;Tile server&lt;/h2&gt;

&lt;p&gt;To display a map on a web page we need:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A server that returns the map as &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Tiles&quot;&gt;Tile images&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;A HTML widget that displays them.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We’ll use the &lt;a href=&quot;https://github.com/mojodna/tessera&quot;&gt;tessera server&lt;/a&gt;. Install it with:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;mkdir blank-world &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;blank-world

cat&amp;lt;&amp;lt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EOF&amp;quot;&lt;/span&gt;&amp;gt;package.json
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&amp;quot;blank-world&amp;quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;version&amp;quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&amp;quot;1.0.0&amp;quot;&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;private&amp;quot;&lt;/span&gt;: &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;,
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;: &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
EOF

npm install tessera --save
npm install tilelive-tmsource --save
npm install tilelive-tmstyle --save&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See the resulting dependencies and versions:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;cat package.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I got:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tessera&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;^0.5.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;tilelive&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;^5.4.1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;tilelive-tmsource&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;^0.1.2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;tilelive-tmstyle&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;^0.3.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;&amp;quot;tilelive-vector&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;^2.3.1&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Start tessera:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;./node_modules/.bin/tessera tmstyle://&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/blank-world.tm2&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It should now be running at &lt;a href=&quot;http://localhost:8080&quot;&gt;http://localhost:8080&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In another Terminal, get the &lt;a href=&quot;https://github.com/mapbox/tilejson-spec&quot;&gt;TileJSON&lt;/a&gt; document that describes the map:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;sudo apt-get install httpie
http get http://localhost:8080/index.json&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should see something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;attribution&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;bounds&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;85.0511&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;mi&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
        &lt;span class=&quot;mf&quot;&gt;85.0511&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;center&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;format&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;png8:m=h&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;maxzoom&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;minzoom&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Untitled&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;scale&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;source&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tmsource:///home/rgl/blank-world.tm2source&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;tilejson&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2.0.0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;tiles&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://localhost:8080/{z}/{x}/{y}.png&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also get a Tile image, e.g. the south of &lt;a href=&quot;http://en.wikipedia.org/wiki/Portugal&quot;&gt;Portugal&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;curl -O http://localhost:8080/6/30/24.png
exo-open 24.png&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Tiles are normally PNG images with 256x256 pixels.&lt;/p&gt;

&lt;p&gt;You are almost done! Off to showing the web map…&lt;/p&gt;

&lt;h1 id=&quot;web-map&quot;&gt;Web map&lt;/h1&gt;

&lt;p&gt;To show the map we’ll use the &lt;a href=&quot;https://www.mapbox.com/mapbox.js/&quot;&gt;Mapbox.js&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;Create the web page:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;cat&lt;span class=&quot;err&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&amp;quot;EOF&amp;quot;&amp;gt;map.html
&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;blank world&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;viewport&amp;#39;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;initial-scale=1,maximum-scale=1,user-scalable=no&amp;#39;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;https://api.tiles.mapbox.com/mapbox.js/v2.1.4/mapbox.js&amp;#39;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;https://api.tiles.mapbox.com/mapbox.js/v2.1.4/mapbox.css&amp;#39;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;stylesheet&amp;#39;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;#map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;absolute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;map&amp;#39;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;L&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mapbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;map&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://localhost:8080/index.json&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;38.736946&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;9.142685&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
EOF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;exo-open map.html&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You should now see the blank world map!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/blank-world-map.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And there you have it! Let me known how it worked for you.&lt;/p&gt;

&lt;p&gt;In a future article I’ll show you how to import the &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Tag:natural%3Dwater&quot;&gt;water areas&lt;/a&gt; from OpenStreetMap.&lt;/p&gt;

&lt;h1 id=&quot;more-information&quot;&gt;More information&lt;/h1&gt;

&lt;p&gt;This article mentioned a lot of pieces that you might not be familiar with. To get more insight you should read the following references:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mapbox.com/guides/how-web-maps-work/&quot;&gt;Tiles and zoom levels&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.mapbox.com/mapbox-studio/&quot;&gt;Mapbox Studio Documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mapbox/carto&quot;&gt;CartoCSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Map Styles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/mapbox?query=.tm2&quot;&gt;All Mapbox Styles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/stamen/toner-carto&quot;&gt;Toner&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/gravitystorm/openstreetmap-carto&quot;&gt;OpenStreetMap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Map projections (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/Spatial_reference_system&quot;&gt;SRS&lt;/a&gt;):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://epsg.io/4326&quot;&gt;EPSG:4326&lt;/a&gt; (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/World_Geodetic_System&quot;&gt;WGS84&lt;/a&gt;). Used in &lt;a href=&quot;http://en.wikipedia.org/wiki/Global_Positioning_System&quot;&gt;GPS&lt;/a&gt; and &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Projection&quot;&gt;raw OpenStreetMap data&lt;/a&gt; found on &lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Planet.osm&quot;&gt;Planet.osm&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://epsg.io/3857&quot;&gt;EPSG:3857&lt;/a&gt; (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/Web_Mercator&quot;&gt;Web Mercator or Spherical Mercator&lt;/a&gt;). Used in web maps (e.g. Google/Bing/Leaftlet/Mapbox.js).&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://trac.osgeo.org/proj/wiki/FAQ&quot;&gt;FAQ&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://alastaira.wordpress.com/2011/01/23/the-google-maps-bing-maps-spherical-mercator-projection/&quot;&gt;The Google Maps / Bing Maps Spherical Mercator Projection&lt;/a&gt; confusion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;http://www.openstreetmap.org/&quot;&gt;OpenStreetMap&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Beginners%27_Guide&quot;&gt;Beginners Guide&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Map_features&quot;&gt;Map features&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Good_practice&quot;&gt;Good practices&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://help.openstreetmap.org/&quot;&gt;Forum&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Main_Page&quot;&gt;Wiki&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://wiki.openstreetmap.org/wiki/Overpass_turbo&quot;&gt;Overpass Turbo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an alternative software stack, you should look at:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://geoserver.org/&quot;&gt;GeoServer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://openlayers.org/&quot;&gt;OpenLayers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And finally, feel free to contact me!&lt;/p&gt;

&lt;p&gt;– RGL&lt;/p&gt;
</description>
        <pubDate>Sun, 04 Jan 2015 17:54:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/from-zero-to-a-blank-world-map.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/from-zero-to-a-blank-world-map.html</guid>
        
        
      </item>
    
      <item>
        <title>Taking web application screenshots with CasperJS</title>
        <description>&lt;p&gt;When you need to take screenshots of a web application, the normal route is to navigate to a page, fill in the forms with sample data, use the &lt;a href=&quot;http://en.wikipedia.org/wiki/Print_screen&quot;&gt;Print screen&lt;/a&gt; (or &lt;code&gt;Alt+Print screen&lt;/code&gt;) key to take the screenshot, then crop and export it with a normal application like &lt;a href=&quot;http://www.gimp.org/&quot;&gt;GIMP&lt;/a&gt;… which is quite time consuming… and god forbid if you need to do it again, with a slightly different data or page design…&lt;/p&gt;

&lt;p&gt;A better route would be to automate the whole process. Let me show you how to do it with &lt;a href=&quot;http://casperjs.org/&quot;&gt;CasperJS&lt;/a&gt;!&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;Lets start!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; if you need some help installing CasperJS, see the end of this article.&lt;/p&gt;

&lt;p&gt;I’ll be using my &lt;a href=&quot;http://ruilopes.com&quot;&gt;home page&lt;/a&gt; as an example.&lt;/p&gt;

&lt;p&gt;Create a simple casper test script that captures the entire page inside the file &lt;code&gt;example.js&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// set the viewport size to include all our page content.&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;viewportSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;700&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// step 1: open the page.&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;http://ruilopes.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// do an example test.&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;assertTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;rui lopes home&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// step 2: take some screenshots.&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// capture the entire page.&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;capture&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;page.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// capture the nav element.&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;captureSelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;selector.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;nav&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// actually run the steps we defined before.&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;casper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; As you can see its quite self-explanatory; but you should really read &lt;a href=&quot;http://docs.casperjs.org/en/latest/modules/casper.html#capture&quot;&gt;The Fine Manual&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run casper:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;casperjs test example.js
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Should output something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;Test file: example.js
&lt;span class=&quot;c&quot;&gt;# test&lt;/span&gt;
PASS Page title is: &lt;span class=&quot;s2&quot;&gt;&amp;quot;rui lopes home&amp;quot;&lt;/span&gt;
PASS &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;test &lt;/span&gt;executed in 0.087s, &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt; passed, &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; failed, &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; dubious, &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; skipped.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And look at the generated screenshots.&lt;/p&gt;

&lt;h3 id=&quot;the-entire-page&quot;&gt;the entire page&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bytebucket.org/rgl/casperjs-screenshooter/raw/7c27e3474fb264ca84daeb71e6c3794ac548892b/page.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;the-nav-element&quot;&gt;the nav element&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://bytebucket.org/rgl/casperjs-screenshooter/raw/7c27e3474fb264ca84daeb71e6c3794ac548892b/selector.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;mouse-cursor&quot;&gt;Mouse Cursor&lt;/h2&gt;

&lt;p&gt;CasperJS uses &lt;a href=&quot;http://phantomjs.org/&quot;&gt;PhantomJS&lt;/a&gt; uses &lt;a href=&quot;https://qt-project.org/wiki/QtWebKit&quot;&gt;QtWebKit&lt;/a&gt; in headless mode. But, unfortunately, this combo does not seem to support the mouse cursor. So I had to roll my own solution by creating &lt;a href=&quot;https://bitbucket.org/rgl/casperjs-screenshooter&quot;&gt;casperjs-screenshooter&lt;/a&gt;. It simulates the mouse cursor by adding an &lt;code&gt;img&lt;/code&gt; element with id &lt;code&gt;screenshooterCursor&lt;/code&gt; to the page DOM and the &lt;code&gt;hover&lt;/code&gt; class into a element to simulate the hover effect.&lt;/p&gt;

&lt;p&gt;Lets see how we can use it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;// step 3: take some screenshots with the mouse over a element.
screenshooter.thenMoveCursor&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pointer&amp;quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&amp;quot;a[href=&amp;#39;http://blog.ruilopes.com/&amp;#39;]&amp;quot;&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    // capture the area taken by the h1 and mouse cursor elements.
    screenshooter.capture&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;multiple-selector-with-mouse-cursor.png&amp;quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&amp;quot;h1, #screenshooterCursor&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; by default, you can use the following cursor names: &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;pointer&lt;/code&gt;, &lt;code&gt;text&lt;/code&gt;, &lt;code&gt;help&lt;/code&gt; or &lt;code&gt;none&lt;/code&gt;. You can add more yourself by using &lt;a href=&quot;https://bitbucket.org/rgl/cur2png&quot;&gt;cur2png or png2json&lt;/a&gt; (you can &lt;a href=&quot;https://bitbucket.org/rgl/cur2png/downloads&quot;&gt;download the binaries&lt;/a&gt; too).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; the default cursors come from the excellent &lt;a href=&quot;http://nordlicht.deviantart.com/art/Ubuntu-quot-Human-quot-Cursors-35930998&quot;&gt;Ubuntu Human theme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; with &lt;code&gt;screenshooter.capture&lt;/code&gt; (instead of &lt;code&gt;casper.capture&lt;/code&gt;) you can capture the area taken by several elements, each selected by a different selector separated by a comma.&lt;/p&gt;

&lt;p&gt;And the resulting screenshot image:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://bytebucket.org/rgl/casperjs-screenshooter/raw/7c27e3474fb264ca84daeb71e6c3794ac548892b/multiple-selector-with-mouse-cursor.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And thats it… see the &lt;a href=&quot;https://bitbucket.org/rgl/casperjs-screenshooter/src/7c27e3474fb264ca84daeb71e6c3794ac548892b/example.js?at=default&quot;&gt;full source&lt;/a&gt; and let me known what you think!&lt;/p&gt;

&lt;p&gt;– RGL&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;install-on-ubuntu&quot;&gt;Install on Ubuntu&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; I’m using Ubuntu 14.04; but it should be the same on other versions.&lt;/p&gt;

&lt;p&gt;Run the following commands:&lt;/p&gt;

&lt;pre&gt;
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install nodejs
sudo npm install -g casperjs
&lt;/pre&gt;

&lt;h2 id=&quot;install-on-windows&quot;&gt;Install on Windows&lt;/h2&gt;

&lt;p&gt;On Windows (I’m using 8.1), we need to jump through some hoops… download the installer (e.g. &lt;a href=&quot;http://nodejs.org/dist/v0.10.26/node-v0.10.26-x86.msi&quot;&gt;node-v0.10.26-x86.msi&lt;/a&gt;) from:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;http://nodejs.org/download/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And install it (I’ve installed mine at &lt;code&gt;C:\Development\nodejs&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Next, open a Command Prompt, and make sure you can run node. If you didn’t let the installer modify your &lt;code&gt;PATH&lt;/code&gt;, you need to add the directories manually with:&lt;/p&gt;

&lt;pre&gt;
set PATH=%PATH%;C:\Development\nodejs;%APPDATA%\npm
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; &lt;code&gt;%APPDATA%&lt;/code&gt; should expand to something like &lt;code&gt;C:\Users\rgl\AppData\Roaming&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Check the installed node version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;node --version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Should output something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;v0.10.26
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Check the installed npm version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;npm --version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Should output something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1.4.3
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Install CasperJS with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;npm install -g casperjs
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And check its version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;casperjs --version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Should output something like:&lt;/p&gt;

&lt;pre&gt;
&#39;python&#39; is not recognized as an internal or external command,
operable program or batch file.
&lt;/pre&gt;

&lt;p&gt;Errr what? needs python? Oh well… as I found out its possible to run without it, lets add the needed directories into the PATH:&lt;/p&gt;

&lt;pre&gt;
set PATH=%APPDATA%\npm\node_modules\casperjs\bin;%APPDATA%\npm\node_modules\casperjs\node_modules\phantomjs\lib\phantom;%PATH%
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; You need to add the &lt;code&gt;caspjerjs\bin&lt;/code&gt; directories before the ones we’ve set before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; If this sounds too hackish, install &lt;a href=&quot;https://www.python.org/downloads/&quot;&gt;python&lt;/a&gt; and add it into your &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And try again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;casperjs --version
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Should finally output something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1.1.0-beta3
&lt;/code&gt;&lt;/pre&gt;
</description>
        <pubDate>Sun, 20 Apr 2014 15:51:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/taking-web-application-screenshots-with-casperjs.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/taking-web-application-screenshots-with-casperjs.html</guid>
        
        
      </item>
    
      <item>
        <title>Fix magnet link openning in Xfce / Arch Linux</title>
        <description>&lt;p&gt;The current Xfce (4.10) that ships with Arch Linux has an annoying bug of not correctly opening &lt;a href=&quot;http://en.wikipedia.org/wiki/Magnet_URI_scheme&quot;&gt;Magnet&lt;/a&gt; URIs (e.g. when you click a magnet link from within Chromium). So I had to have that fixed, but doing it took longer that I expected… so I’m creating this recipe for helping you solving the problem more easily.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;Chromium handles unknown &lt;a href=&quot;http://en.wikipedia.org/wiki/URI_scheme&quot;&gt;URI schemes&lt;/a&gt; by delegating them to the &lt;a href=&quot;https://wiki.archlinux.org/index.php/Xdg-open&quot;&gt;xdg-open command&lt;/a&gt;. Which in turn, detects it’s running under the Xfce desktop and delegates the control the &lt;a href=&quot;https://wiki.archlinux.org/index.php/Xdg-open&quot;&gt;exo-open command&lt;/a&gt;. Which fails to open the magnet URIs.&lt;/p&gt;

&lt;p&gt;In these instructions you’ll patch the &lt;a href=&quot;https://www.archlinux.org/packages/?name=exo&quot;&gt;exo package&lt;/a&gt; and re-install it with a little &lt;a href=&quot;http://git.xfce.org/xfce/exo/commit/?id=05848bb&quot;&gt;patch&lt;/a&gt; that fixes that annoying problem.&lt;/p&gt;

&lt;p&gt;So let’s get to it! Open a terminal and issue the following commands.&lt;/p&gt;

&lt;p&gt;Configure &lt;code&gt;xdg-open&lt;/code&gt; to open magnet URIs with the &lt;a href=&quot;http://www.transmissionbt.com/&quot;&gt;Transmission application&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
xdg-mime default transmission-gtk.desktop x-scheme-handler/magnet
&lt;/pre&gt;

&lt;p&gt;NB: this modifies the &lt;code&gt;~/.local/share/applications/mimeapps.list&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Get the &lt;code&gt;exo&lt;/code&gt; package (contains the &lt;code&gt;exo-open&lt;/code&gt; command):&lt;/p&gt;

&lt;pre&gt;
sudo pacman -S abs
sudo abs extra/exo
cd /tmp
cp -R /var/abs/extra/exo .
cd exo
&lt;/pre&gt;

&lt;p&gt;Add the &lt;a href=&quot;http://git.xfce.org/xfce/exo/commit/?id=05848bb&quot;&gt;patch&lt;/a&gt; into a file:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;cat&amp;lt;&amp;lt;&amp;quot;EOF&amp;quot;&amp;gt;fix-exo_str_looks_like_an_uri-bug-10098.patch
&lt;span class=&quot;gh&quot;&gt;diff --git a/exo/exo-string.c b/exo/exo-string.c&lt;/span&gt;
&lt;span class=&quot;gh&quot;&gt;index 33f86f9..056b36a 100644&lt;/span&gt;
&lt;span class=&quot;gd&quot;&gt;--- a/exo/exo-string.c&lt;/span&gt;
&lt;span class=&quot;gi&quot;&gt;+++ b/exo/exo-string.c&lt;/span&gt;
&lt;span class=&quot;gu&quot;&gt;@@ -429,7 +429,7 @@ exo_str_looks_like_an_uri (const gchar *str)&lt;/span&gt;
       for (++s; g_ascii_isalnum (*s) || *s == &amp;#39;+&amp;#39; || *s == &amp;#39;-&amp;#39; || *s == &amp;#39;.&amp;#39;; ++s);

       /* &amp;lt;scheme&amp;gt; must be followed by &amp;quot;:&amp;quot; */
&lt;span class=&quot;gd&quot;&gt;-      return (*s == &amp;#39;:&amp;#39; &amp;amp;&amp;amp; *(s+1) == &amp;#39;/&amp;#39;);&lt;/span&gt;
&lt;span class=&quot;gi&quot;&gt;+      return (*s == &amp;#39;:&amp;#39; &amp;amp;&amp;amp; *(s+1) != &amp;#39;\0&amp;#39;);&lt;/span&gt;
     }

   return FALSE;
EOF&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Modify the &lt;a href=&quot;https://wiki.archlinux.org/index.php/PKGBUILD&quot;&gt;PKGBUILD&lt;/a&gt; file to patch the source by adding the &lt;code&gt;prepare&lt;/code&gt; function above the existing &lt;code&gt;build&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;prepare&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;$srcdir/$pkgname-$pkgver&amp;quot;&lt;/span&gt;
  patch -p1 &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;lt&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;$startdir/fix-exo_str_looks_like_an_uri-bug-10098.patch&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;NB to properly finish the package you should also add the patch file name into the &lt;code&gt;source&lt;/code&gt; array and its sha256 checksum into the &lt;code&gt;sha256sums&lt;/code&gt; array… but I’ll not bother.&lt;/p&gt;

&lt;p&gt;And finally build and install the package:&lt;/p&gt;

&lt;pre&gt;
makepkg -s
sudo pacman -U *.pkg*
&lt;/pre&gt;

&lt;p&gt;And that should be it! Try to click on a magnet file link now!&lt;/p&gt;

&lt;p&gt;– RGL&lt;/p&gt;
</description>
        <pubDate>Sun, 25 Aug 2013 18:18:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/fix-magnet-link-openning-in-xfce-arch-linux.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/fix-magnet-link-openning-in-xfce-arch-linux.html</guid>
        
        
      </item>
    
      <item>
        <title>from http to https with free certificates</title>
        <description>&lt;p&gt;Recently I’ve noticed that &lt;a href=&quot;http://www.startcom.org/&quot;&gt;StartCom&lt;/a&gt; gives away free certificates through theirs &lt;a href=&quot;http://www.startssl.com/&quot;&gt;StartSSL&lt;/a&gt; site. In this post I will explain how I managed to configure &lt;a href=&quot;http://nginx.org/en/&quot;&gt;nginx&lt;/a&gt; to host two of my domains, on the same IP address, using &lt;a href=&quot;http://en.wikipedia.org/wiki/HTTP_Secure&quot;&gt;HTTPS&lt;/a&gt;.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;h1 id=&quot;tldr-summary&quot;&gt;TL;DR summary&lt;/h1&gt;

&lt;p&gt;This is the recipe to create an RSA keypair, a Certificate Signing Request (CSR), install and configure nginx.&lt;/p&gt;

&lt;p&gt;Create the RSA keypair:&lt;/p&gt;

&lt;pre&gt;
cd /etc/ssl/private
openssl req -newkey rsa:2048 -nodes -keyout ruilopes.com.key -out ruilopes.com.csr &amp;amp;&amp;amp; chmod 400 ruilopes.com.key
&lt;/pre&gt;

&lt;p&gt;Set Common Name (eg, YOUR name) field to: ruilopes.com&lt;/p&gt;

&lt;p&gt;Paste the contents of the &lt;code&gt;ruilopes.com.csr&lt;/code&gt; file into the StartCom form, let’m generate the certificate, copy it into the &lt;code&gt;ruilopes.com.crt&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Append the StartCom intermediate CA certificate to our own:&lt;/p&gt;

&lt;pre&gt;
curl -O https://www.startssl.com/certs/sub.class1.server.ca.pem
cat sub.class1.server.ca.pem &amp;gt;&amp;gt; ruilopes.com.crt
&lt;/pre&gt;

&lt;p&gt;Install and configure nginx:&lt;/p&gt;

&lt;pre&gt;
add-apt-repository ppa:nginx/stable
apt-get update
apt-get install nginx-full

mkdir /var/www/ruilopes.com
&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/var/www/ruilopes.com/index.html
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;
  &amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
EOF


cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/etc/nginx/sites-available/ruilopes.com.conf
server {
  server_name ruilopes.com www.ruilopes.com;

  listen 80 default;
  listen 443 default ssl;

  ssl_certificate      /etc/ssl/private/ruilopes.com.crt;
  ssl_certificate_key  /etc/ssl/private/ruilopes.com.key;

  root /var/www/ruilopes.com;
  access_log /var/log/nginx/ruilopes.com.access.log;

  index index.html;
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;
ln -s /etc/nginx/sites-available/ruilopes.com.conf /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default

service nginx restart
&lt;/pre&gt;

&lt;p&gt;Test with openssl:&lt;/p&gt;

&lt;pre&gt;
openssl s_client -connect ruilopes.com:443 -servername ruilopes.com
&lt;/pre&gt;

&lt;p&gt;Test by opening the following address:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;https://ruilopes.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That’s it!&lt;/p&gt;

&lt;p&gt;But really, keep reading! I’ll explain how this works and also add a second domain to the same IP address… this is a somewhat lengthy post… so bear with me! In the end, I hope you’ll understand what is going on.&lt;/p&gt;

&lt;h1 id=&quot;from-http-to-https&quot;&gt;From http to HTTPS&lt;/h1&gt;

&lt;p&gt;Roughly, we’ll follow this plan:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;create a &lt;a href=&quot;http://en.wikipedia.org/wiki/RSA&quot;&gt;RSA&lt;/a&gt; keypair (two keys: a private and a public key).&lt;/li&gt;
  &lt;li&gt;create a &lt;a href=&quot;http://en.wikipedia.org/wiki/Certificate_signing_request&quot;&gt;Certificate Signing Request&lt;/a&gt; (CSR).&lt;/li&gt;
  &lt;li&gt;submit the CSR to StartCom; they will create and sign a certificate that binds our public key and domain name to their Certification Authority (CA).&lt;/li&gt;
  &lt;li&gt;configure nginx to use our private key and the certificate signed by StartCom.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’ll use Ubuntu 10.04, so the nginx install and file-system paths are tied to this particular Linux flavor.&lt;/p&gt;

&lt;p&gt;All the commands displayed here should be run inside a shell with root privileges.&lt;/p&gt;

&lt;p&gt;Lets start by installing nginx:&lt;/p&gt;

&lt;pre&gt;
apt-get install nginx
&lt;/pre&gt;

&lt;p&gt;And a plain nginx configuration (no certificates involved) for my primary domain &lt;code&gt;ruilopes.com&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/etc/nginx/sites-available/ruilopes.com.conf
server {
  server_name ruilopes.com www.ruilopes.com;

  listen 80;

  root /var/www/ruilopes.com;
  access_log /var/log/nginx/ruilopes.com.access.log;

  index index.html;
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Create a simple index page:&lt;/p&gt;

&lt;pre&gt;
mkdir /var/www/ruilopes.com
&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/var/www/ruilopes.com/index.html
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;
  &amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Enable the new site, remove the default site (which ships by default with Ubuntu), and notify nginx to reload its configuration:&lt;/p&gt;

&lt;pre&gt;
ln -s /etc/nginx/sites-available/ruilopes.com.conf /etc/nginx/sites-enabled/
rm /etc/nginx/sites-enabled/default
service nginx reload
&lt;/pre&gt;

&lt;p&gt;Try to access the site, to see if its working:&lt;/p&gt;

&lt;pre&gt;
curl --silent --dump - http://ruilopes.com/
&lt;/pre&gt;

&lt;p&gt;You should see something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK
Server: nginx/0.7.65
Date: Mon, 31 Jan 2011 21:54:22 GMT
Content-Type: text/html
Content-Length: 141
Last-Modified: Sun, 30 Jan 2011 20:26:43 GMT
Connection: keep-alive
Vary: Accept-Encoding
Accept-Ranges: bytes

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;
  &amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now that we have the baseline working, lets add some crypto to the mix.&lt;/p&gt;

&lt;p&gt;Using &lt;a href=&quot;http://www.openssl.org/docs/apps/openssl.html&quot;&gt;openssl(1)&lt;/a&gt; &lt;a href=&quot;http://www.openssl.org/docs/apps/genrsa.html&quot;&gt;genrsa(1)&lt;/a&gt; create an 2048-bit RSA keypair (without password protection; use &lt;code&gt;-des3&lt;/code&gt; for password protection):&lt;/p&gt;

&lt;pre&gt;
cd /etc/ssl/private
openssl genrsa -out ruilopes.com.key 2048
chmod 400 ruilopes.com.key
&lt;/pre&gt;

&lt;p&gt;NB You can later password protect a key with:&lt;/p&gt;

&lt;pre&gt;
openssl rsa -des3 -in ruilopes.com.key -out ruilopes.com.key.new &amp;amp;&amp;amp; mv ruilopes.com.key.new ruilopes.com.key
&lt;/pre&gt;

&lt;p&gt;You can inspect the private and public key components with:&lt;/p&gt;

&lt;pre&gt;
openssl rsa -noout -text -in ruilopes.com.key
&lt;/pre&gt;

&lt;p&gt;It looks something like:&lt;/p&gt;

&lt;pre&gt;
Private-Key: (2048 bit)
modulus:
    00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:
    ...
publicExponent: 65537 (0x10001)
privateExponent:
    ...
prime1:
    ...
prime2:
    ...
exponent1:
    ...
exponent2:
    ...
coefficient:
    ...
&lt;/pre&gt;

&lt;p&gt;Or just inspect the public content:&lt;/p&gt;

&lt;pre&gt;
openssl rsa -pubout -in ruilopes.com.key 2&amp;gt;/dev/null | openssl rsa -noout -text -pubin
&lt;/pre&gt;

&lt;p&gt;Which should look something like:&lt;/p&gt;

&lt;pre&gt;
Modulus (2048 bit):
    00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:
    ...
Exponent: 65537 (0x10001)
&lt;/pre&gt;

&lt;p&gt;Using &lt;a href=&quot;http://www.openssl.org/docs/apps/req.html&quot;&gt;openssl req(1)&lt;/a&gt; create the Certificate Signing Request (CSR):&lt;/p&gt;

&lt;pre&gt;
openssl req -new -key ruilopes.com.key -out ruilopes.com.csr
&lt;/pre&gt;

&lt;p&gt;NB You can also generate the keypair and CSR with a single command:&lt;/p&gt;

&lt;pre&gt;
openssl req -newkey rsa:2048 -nodes -keyout ruilopes.com.key -out ruilopes.com.csr
&lt;/pre&gt;

&lt;p&gt;This step will ask you for information to include in the CSR, in our case, StartCom level 1 certificates only need the domain name (aka &lt;a href=&quot;http://en.wikipedia.org/wiki/X.509&quot;&gt;X.509&lt;/a&gt; Common Name or CN; NB all the other information is ignored by StartCom), here’s how openssl req asks for this information:&lt;/p&gt;

&lt;pre&gt;
Country Name (2 letter code) [AU]:.
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (eg, YOUR name) []:ruilopes.com
Email Address []:.

Please enter the following &#39;extra&#39; attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
&lt;/pre&gt;

&lt;p&gt;NB “.” is an openssl convention that means the field should be empty/omitted.&lt;/p&gt;

&lt;p&gt;You can inspect the certificate signing request using:&lt;/p&gt;

&lt;pre&gt;
openssl req -noout -text -in ruilopes.com.csr
&lt;/pre&gt;

&lt;p&gt;It looks something like:&lt;/p&gt;

&lt;pre&gt;
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: CN=ruilopes.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (2048 bit)
                Modulus (2048 bit):
                    00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:
                    ...
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha1WithRSAEncryption
        47:98:bd:ee:41:cb:29:de:29:54:f9:0d:d7:ff:6d:00:55:ec:
        ...
&lt;/pre&gt;

&lt;p&gt;You are now ready to send the CSR to StartCom… just copy&amp;amp;paste its contents to the StartCom control panel and let them generate our certificate.&lt;/p&gt;

&lt;p&gt;NB: They also let you add one sub-domain, I’ve choosen “www” (for &lt;code&gt;www.ruilopes.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;After the certificate is generated, copy&amp;amp;paste it into the &lt;code&gt;ruilopes.com.crt&lt;/code&gt; file, and inspect the certificate with:&lt;/p&gt;

&lt;pre&gt;
openssl x509 -noout -text -in ruilopes.com.crt
&lt;/pre&gt;

&lt;p&gt;It will look something like:&lt;/p&gt;

&lt;pre&gt;
Certificate:
...
        Issuer: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Class 1 Primary Intermediate Server CA
        Validity
            Not Before: Jan 29 17:45:36 2011 GMT
            Not After : Jan 30 19:25:11 2012 GMT
        Subject: description=345115-eJ9Q0A1Uk83j6dMv, C=PT, O=Persona Not Validated, OU=StartCom Free Certificate Member, CN=www.ruilopes.com/emailAddress=me@example.com
...
            X509v3 Subject Alternative Name:
                DNS:www.ruilopes.com, DNS:ruilopes.com
&lt;/pre&gt;

&lt;p&gt;You are now ready to configure nginx with the private keypair (inside &lt;code&gt;ruilopes.com.key&lt;/code&gt; file) and the certificate (inside &lt;code&gt;ruilopes.com.crt&lt;/code&gt; file). So lets do that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/etc/nginx/sites-available/ruilopes.com.conf
server {
  server_name ruilopes.com www.ruilopes.com;

  listen 80 default;
  listen 443 default ssl;

  ssl_certificate      /etc/ssl/private/ruilopes.com.crt;
  ssl_certificate_key  /etc/ssl/private/ruilopes.com.key;

  root /var/www/ruilopes.com;
  access_log /var/log/nginx/ruilopes.com.access.log;

  index index.html;
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;NB We’ve just added the &lt;code&gt;listen 443&lt;/code&gt;, &lt;code&gt;ssl_certificate&lt;/code&gt; and &lt;code&gt;ssl_certificate_key&lt;/code&gt; lines.&lt;/p&gt;

&lt;p&gt;Notify nginx to reload the configuration:&lt;/p&gt;

&lt;pre&gt;
service nginx reload
&lt;/pre&gt;

&lt;p&gt;And try to access our shinny HTTPS server! This time using &lt;a href=&quot;http://www.openssl.org/docs/apps/s_client.html&quot;&gt;openssl s_client(1)&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
openssl s_client -connect ruilopes.com:443 -servername ruilopes.com
&lt;/pre&gt;

&lt;p&gt;The output should look something like:&lt;/p&gt;

&lt;pre&gt;
CONNECTED(00000003)
depth=0 /description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
   i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
---
Server certificate
-----BEGIN CERTIFICATE-----
... omitted ...
-----END CERTIFICATE-----
subject=/description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
issuer=/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
---
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;NB&lt;/strong&gt; for now, ignore the errors that are displayed in this output.&lt;/p&gt;

&lt;p&gt;Lets try with curl:&lt;/p&gt;

&lt;pre&gt;
curl --silent --dump - https://ruilopes.com/
&lt;/pre&gt;

&lt;p&gt;And you’ll notice that something is not right, as no text output is displayed… lets see whats is going on by removing the &lt;code&gt;--silent&lt;/code&gt; switch, and try again. This time the output should be something like:&lt;/p&gt;

&lt;pre&gt;
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a &quot;bundle&quot;
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn&#39;t adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you&#39;d like to turn off curl&#39;s verification of the certificate, use
 the -k (or --insecure) option.
&lt;/pre&gt;

&lt;p&gt;This happens because curl, by default, does not even try to validate intermediate CA certificates. Recall this piece of information from openssl s_client output:&lt;/p&gt;

&lt;pre&gt;
---
Certificate chain
 0 s:/description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
   i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
---
&lt;/pre&gt;

&lt;p&gt;This means that our HTTPS server is returning a single certificate, issued by the Certification Authority (CA) that has the Common Name (CN) &lt;code&gt;StartCom Class 1 Primary Intermediate Server CA&lt;/code&gt;. Lets see if Ubuntu ships with a certificate that has that CN:&lt;/p&gt;

&lt;pre&gt;
ls -F /etc/ssl/certs | grep -i startcom
&lt;/pre&gt;

&lt;p&gt;It outputs something like:&lt;/p&gt;

&lt;pre&gt;
StartCom_Certification_Authority.pem
StartCom_Ltd..pem
&lt;/pre&gt;

&lt;p&gt;Lets see the CN:&lt;/p&gt;

&lt;pre&gt;
openssl x509 -noout -text -in /etc/ssl/certs/StartCom_Certification_Authority.pem
&lt;/pre&gt;

&lt;p&gt;It should look something like (we are only interested in the Issuer and Subject fields):&lt;/p&gt;

&lt;pre&gt;
Issuer:  C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority
Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority
&lt;/pre&gt;

&lt;p&gt;As you can see, the Subject CN is not the CN we are looking for… lets try the other certificate:&lt;/p&gt;

&lt;pre&gt;
openssl x509 -noout -text -in /etc/ssl/certs/StartCom_Ltd..pem
&lt;/pre&gt;

&lt;p&gt;It should look something like:&lt;/p&gt;

&lt;pre&gt;
Issuer:  C=IL, ST=Israel, L=Eilat, O=StartCom Ltd., OU=CA Authority Dep., CN=Free SSL Certification Authority/emailAddress=admin@startcom.org
Subject: C=IL, ST=Israel, L=Eilat, O=StartCom Ltd., OU=CA Authority Dep., CN=Free SSL Certification Authority/emailAddress=admin@startcom.org
&lt;/pre&gt;

&lt;p&gt;So neither certificate Subject has the CN we are looking for… so Ubuntu does not ship with the &lt;code&gt;StartCom Class 1 Primary Intermediate Server CA&lt;/code&gt; certificate.&lt;/p&gt;

&lt;p&gt;NB This is a simplification of the certificate resolution algorithm; eg. they are not matched just by their CN, but by their Distinguished Name (DN) and public key value/fingerprint (and other details I’m omitting here).&lt;/p&gt;

&lt;p&gt;Lets download it from StartCom site, and see its contents:&lt;/p&gt;

&lt;pre&gt;
curl -O https://www.startssl.com/certs/sub.class1.server.ca.pem
openssl x509 -noout -text -in sub.class1.server.ca.pem
&lt;/pre&gt;

&lt;p&gt;It should look something like:&lt;/p&gt;

&lt;pre&gt;
Issuer:  C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Certification Authority
Subject: C=IL, O=StartCom Ltd., OU=Secure Digital Certificate Signing, CN=StartCom Class 1 Primary Intermediate Server CA
&lt;/pre&gt;

&lt;p&gt;So, the Subject we were looking for is here! Also notice that the Subject is different than the Issuer… this means this is an intermediate certificate; the ones that have the Issuer equal to Subject are called root certificates (aka self-signed certificates).&lt;/p&gt;

&lt;p&gt;Also notice that the Issuer CN is the same has the one inside the &lt;code&gt;/etc/ssl/certs/StartCom_Certification_Authority.pem&lt;/code&gt; file! So, Ubuntu ships with that root certificate. So, we are missing a link in the certificate chain we return in our HTTPS server… lets fix that by appending it there:&lt;/p&gt;

&lt;pre&gt;
cat sub.class1.server.ca.pem &amp;gt;&amp;gt; ruilopes.com.crt
&lt;/pre&gt;

&lt;p&gt;Notify nginx to reload the configuration:&lt;/p&gt;

&lt;pre&gt;
service nginx reload
&lt;/pre&gt;

&lt;p&gt;See how the certificate chain is now returned:&lt;/p&gt;

&lt;pre&gt;
openssl s_client -connect ruilopes.com:443 -servername ruilopes.com
&lt;/pre&gt;

&lt;p&gt;The output should look something like:&lt;/p&gt;

&lt;pre&gt;
---
Certificate chain
 0 s:/description=345115-eJ9Q0A1Uk83j6dMv/C=PT/O=Persona Not Validated/OU=StartCom Free Certificate Member/CN=www.ruilopes.com/emailAddress=me@example.com
   i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
 1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
   i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
---
&lt;/pre&gt;

&lt;p&gt;So, now the chain is composed by two links:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Subject with CN=www.ruilopes.com; issued by Issuer with CN=StartCom Class 1 Primary Intermediate Server CA&lt;/li&gt;
  &lt;li&gt;Subject with CN=StartCom Class 1 Primary Intermediate Server CA; issued by Issuer with CN=StartCom Certification Authority&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;See how the first certificate Issuer is the same has the second certificate Subject? That’s how the first certificate is validated by the second, which in turn is validated by the root certificate installed on our local Ubuntu. You see, a chain is formed, starting on our certificate till the root certificate installed on our machine.&lt;/p&gt;

&lt;p&gt;OK, looks good… lets see if it actually works by trying again with curl:&lt;/p&gt;

&lt;pre&gt;
curl --silent --dump - https://ruilopes.com/
&lt;/pre&gt;

&lt;p&gt;You should see something like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK
Server: nginx/0.7.65
Date: Mon, 31 Jan 2011 21:54:22 GMT
Content-Type: text/html
Content-Length: 141
Last-Modified: Sun, 30 Jan 2011 20:26:43 GMT
Connection: keep-alive
Vary: Accept-Encoding
Accept-Ranges: bytes

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset=&quot;utf-8&quot; /&amp;gt;
  &amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So it worked!&lt;/p&gt;

&lt;p&gt;Finally… lets try with a browser! Using Google Chrome you should see something like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/from-http-to-https-with-free-certificates-ruilopes.com-https-crt.jpeg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;NB the window with the certificate information appears after you click the green padlock on the address bar.&lt;/p&gt;

&lt;p&gt;So, that’s it! Our first domain is ready to use!&lt;/p&gt;

&lt;p&gt;Now on to the other domain… well, now it much easier, just repeat everything, but with a different domain name and configuration file!&lt;/p&gt;

&lt;p&gt;Create the configuration file:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/etc/nginx/sites-available/statica.info.conf
server {
  server_name statica.info;

  listen 80 default;
  listen 443 default ssl;

  ssl_certificate      /etc/ssl/private/statica.info.crt;
  ssl_certificate_key  /etc/ssl/private/statica.info.key;

  root /var/www/statica.info;
  access_log /var/log/nginx/statica.info.access.log;

  index index.html;
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;
ln -s /etc/nginx/sites-available/statica.info.conf /etc/nginx/sites-enabled/
&lt;/pre&gt;

&lt;p&gt;Notify nginx to reload the configuration:&lt;/p&gt;

&lt;pre&gt;
service nginx reload
&lt;/pre&gt;

&lt;p&gt;And… it fails with:&lt;/p&gt;

&lt;pre&gt;
Restarting nginx: [emerg]: a duplicate default server for 0.0.0.0:80 in /etc/nginx/sites-enabled/ruilopes.com.conf:4
configuration file /etc/nginx/nginx.conf test failed
&lt;/pre&gt;

&lt;p&gt;This happens because we already had a default domain (&lt;code&gt;ruilopes.com&lt;/code&gt;); so, remove the “&lt;code&gt;default&lt;/code&gt;” word from the “&lt;code&gt;listen&lt;/code&gt;” configuration lines:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat&amp;lt;&amp;lt;&quot;EOF&quot;&amp;gt;/etc/nginx/sites-available/statica.info.conf
server {
  server_name statica.info;

  listen 80;
  listen 443 ssl;

  ssl_certificate      /etc/ssl/private/statica.info.crt;
  ssl_certificate_key  /etc/ssl/private/statica.info.key;

  root /var/www/statica.info;
  access_log /var/log/nginx/statica.info.access.log;

  index index.html;
}
EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And try again:&lt;/p&gt;

&lt;pre&gt;
service nginx reload
&lt;/pre&gt;

&lt;p&gt;Now it fails with a different error:&lt;/p&gt;

&lt;pre&gt;
Restarting nginx: [emerg]: &quot;ssl&quot; parameter can be specified for the default &quot;listen&quot; directive only in /etc/nginx/sites-enabled/statica.info.conf:5
configuration file /etc/nginx/nginx.conf test failed
&lt;/pre&gt;

&lt;p&gt;It turns out we need a newer version of nginx… fortunately, there is a PPA at https://launchpad.net/nginx Lets, remove the old nginx, and add the new version to our system:&lt;/p&gt;

&lt;pre&gt;
service nginx stop
add-apt-repository ppa:nginx/stable
apt-get update
apt-get remove nginx        # remove 0.7.65
apt-get install nginx-full  # add 0.8.54
&lt;/pre&gt;

&lt;p&gt;And start it:&lt;/p&gt;

&lt;pre&gt;
service nginx start
&lt;/pre&gt;

&lt;p&gt;It should now work fine!&lt;/p&gt;

&lt;p&gt;If you are still with me, you might be wondering how it possible to have two (or more) certificates on the same IP address? This is possible because nginx has support for &lt;a href=&quot;http://en.wikipedia.org/wiki/Server_Name_Indication&quot;&gt;Server Name Indication&lt;/a&gt; (SNI), which you can see with:&lt;/p&gt;

&lt;pre&gt;
nginx -V
&lt;/pre&gt;

&lt;p&gt;Which will output something like:&lt;/p&gt;

&lt;pre&gt;
nginx version: nginx/0.8.54
TLS SNI support enabled
&lt;/pre&gt;

&lt;p&gt;For this to work, the browser also has to support SNI. When it does, the browser will send the domain name (aka server name) that its trying to access in the initial TLS handshake.&lt;/p&gt;

&lt;p&gt;This also means that older browsers (without SNI) will not be able to access our site…&lt;/p&gt;

&lt;p&gt;And that’s it! I hope you now understand a bit more how certificates work!&lt;/p&gt;

&lt;p&gt;– RGL&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Mar 2011 14:51:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/from-http-to-https-with-free-certificates.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/from-http-to-https-with-free-certificates.html</guid>
        
        <category>https</category>
        
        <category>tls</category>
        
        <category>ssl</category>
        
        <category>nginx</category>
        
        <category>openssl</category>
        
        
      </item>
    
      <item>
        <title>from zero to elasticsearch in a jiffy</title>
        <description>&lt;p&gt;In this article I will cut to the chase on how to start using &lt;a href=&quot;http://www.elasticsearch.org/&quot;&gt;elasticsearch&lt;/a&gt;, a distributed search engine that just works, &lt;em&gt;You known, for Search&lt;/em&gt;!&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;Elasticsearch (ES) is based on &lt;a href=&quot;http://lucene.apache.org/&quot;&gt;Lucene&lt;/a&gt;, as so, you first need to &lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/index.html&quot;&gt;download the Java Runtime Environment&lt;/a&gt;. I’ll assume you have installed it at &lt;code&gt;C:\Dev\Java\jre6&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, download elasticsearch from:&lt;/p&gt;

&lt;p&gt;http://www.elasticsearch.org/download/&lt;/p&gt;

&lt;p&gt;And decompress it, eg., at &lt;code&gt;C:\Dev\elasticsearch-0.14.4&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Open a Windows Command Prompt window, go into ES directory, and launch it:&lt;/p&gt;

&lt;pre&gt;
cd c:\Dev\elasticsearch-0.14.4
set JAVA_HOME=C:\Dev\Java\jre6
bin\elasticsearch.bat -f
&lt;/pre&gt;

&lt;p&gt;In a new Windows Command Prompt window, verify that ES is responding correctly. First check the &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/api/admin-cluster-health.html&quot;&gt;cluster status&lt;/a&gt; by opening the following URL:&lt;/p&gt;

&lt;p&gt;http://localhost:9200/_cluster/health&lt;/p&gt;

&lt;p&gt;You should see something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;cluster_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;elasticsearch&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;green&amp;quot;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;timed_out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;number_of_nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;number_of_data_nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;active_primary_shards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;active_shards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;relocating_shards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;initializing_shards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;unassigned_shards&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And also check the &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/api/admin-cluster-state.html&quot;&gt;cluster state&lt;/a&gt; at:&lt;/p&gt;

&lt;p&gt;http://localhost:9200/_cluster/state&lt;/p&gt;

&lt;p&gt;Which should return something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;cluster_name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;elasticsearch&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;master_node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Sz86lynqSAKwb1X_NHsrIQ&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;Sz86lynqSAKwb1X_NHsrIQ&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Dredmund Druid&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;transport_address&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;inet[/192.168.1.245:9300]&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;templates&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;indices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;routing_table&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;indices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;routing_nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;unassigned&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;nodes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;allocations&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As ES seems to be working fine, we are now ready to index some documents; I’m going to use a tweet as an example.&lt;/p&gt;

&lt;p&gt;Open a Bash shell window (I’m assuming you already have it installed as described at &lt;a href=&quot;http://blog.ruilopes.com/post/2143557964/sane-shell-environment-on-windows&quot;&gt;Sane shell environment on Windows&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;You also need &lt;a href=&quot;http://curl.haxx.se/download.html&quot;&gt;curl&lt;/a&gt; on your &lt;code&gt;PATH&lt;/code&gt;, you can install it from:&lt;/p&gt;

&lt;p&gt;http://curl.haxx.se/download/libcurl-7.19.3-win32-ssl-msvc.zip&lt;/p&gt;

&lt;p&gt;Download a tweet:&lt;/p&gt;

&lt;pre&gt;
curl -o 19529810560688128.json &#39;http://api.twitter.com/1/statuses/show/19529810560688128.json?include_entities=1&#39;
&lt;/pre&gt;

&lt;p&gt;And check its overall structure:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cat 19529810560688128.json
&lt;/code&gt;&lt;/pre&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;why marking an operation as idempotent is important: http:\/\/www.zeroc.com\/faq\/whyIdempotent.html&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;NB I’m just showing the attribute that is relevant to the search we are going to make. The actual tweet has much more attributes.&lt;/p&gt;

&lt;p&gt;Lets index it:&lt;/p&gt;

&lt;pre&gt;
curl -XPUT -d@19529810560688128.json http://localhost:9200/tweets/tweet/19529810560688128
&lt;/pre&gt;

&lt;p&gt;ES should return something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;19529810560688128&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;_index&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tweets&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;_type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tweet&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;ok&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We are now ready for our first search! Lets &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/api/search/uri-request.html&quot;&gt;search for tweets&lt;/a&gt; that have the “idempotent” word. For this we use the &lt;code&gt;q&lt;/code&gt; parameter like:&lt;/p&gt;

&lt;pre&gt;
curl &#39;http://localhost:9200/tweets/_search?pretty=true&amp;amp;q=idempotent&#39;
&lt;/pre&gt;

&lt;p&gt;Which returns something like:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;_shards&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;failed&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;successful&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;total&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;hits&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;hits&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;19529810560688128&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_index&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tweets&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_score&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.023731936&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_source&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;why marking an operation as idempotent is important: http:\/\/www.zeroc.com\/faq\/whyIdempotent.html&amp;quot;&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tweet&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;max_score&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.023731936&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;total&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;took&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The most important attribute in this result set is the &lt;code&gt;hits.hits&lt;/code&gt; array, it contains all matched documents hits.&lt;/p&gt;

&lt;p&gt;The previous search looked inside all tweet attributes. We can also search inside a particular attribute, for example, “text” attribute:&lt;/p&gt;

&lt;pre&gt;
curl &#39;http://localhost:9200/tweets/_search?pretty=true&amp;amp;q=text:idempotent&#39;
&lt;/pre&gt;

&lt;p&gt;Which should return the same document as before, but this time, with a higher &lt;a href=&quot;http://lucene.apache.org/java/3_0_0/scoring.html&quot;&gt;score&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ES lets us do much more advanced searches; we can use the simple &lt;a href=&quot;http://lucene.apache.org/java/3_0_0/queryparsersyntax.html&quot;&gt;Lucene Query Parser Syntax&lt;/a&gt; (as we did) and we can also use the &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/query-dsl/&quot;&gt;JSON based search query DSL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And that’s it! As you can see, the out-of-box experience is quite simple and strait forward! Of course, this was just the tip of the iceberg. elasticsearch &lt;a href=&quot;http://www.elasticsearch.org/&quot;&gt;has many tricks up its sleeve&lt;/a&gt;, my favorites are: simplicity, automatically distributed (just keep launching nodes, one or several, its the same; its really elastic), highly available (data is replicated; if a node fails, the data will come from another node) and &lt;a href=&quot;http://www.elasticsearch.org/guide/reference/modules/thrift&quot;&gt;thrift transport&lt;/a&gt; (at least one order of magnitude faster than HTTP).&lt;/p&gt;

&lt;p&gt;You should read the &lt;a href=&quot;http://www.elasticsearch.org/guide/&quot;&gt;documentation&lt;/a&gt; and &lt;a href=&quot;http://www.elasticsearch.org/community/&quot;&gt;join the community&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Also checkout the various &lt;a href=&quot;http://www.elasticsearch.org/guide/appendix/clients.html&quot;&gt;client libraries&lt;/a&gt;, and the &lt;a href=&quot;https://github.com/elasticsearch/elasticsearch&quot;&gt;source code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and in case you were wondering, the node names that appear on the logs are based on marvel characters, e.g.:&lt;/p&gt;

&lt;p&gt;[2011-02-17 11:13:47,427][INFO ][node                     ] [&lt;a href=&quot;http://en.wikipedia.org/wiki/Demolition_Man_(comics)&quot;&gt;D-Man&lt;/a&gt;] {elasticsearch/0.14.4}[6212]: stopping …&lt;/p&gt;

&lt;p&gt;[2011-02-17 11:13:53,516][INFO ][node                     ] [&lt;a href=&quot;http://en.wikipedia.org/wiki/Sublime_(comics)&quot;&gt;Sublime, John&lt;/a&gt;] {elasticsearch/0.14.4}[5520]: initializing …&lt;/p&gt;

&lt;p&gt;– RGL&lt;/p&gt;
</description>
        <pubDate>Thu, 17 Feb 2011 16:39:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/from-zero-to-elasticsearch-in-a-jiffy.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/from-zero-to-elasticsearch-in-a-jiffy.html</guid>
        
        <category>elasticsearch</category>
        
        <category>lucene</category>
        
        <category>search</category>
        
        
      </item>
    
      <item>
        <title>Fix SyntaxHighlighter to display tumblr Markdown URLs</title>
        <description>&lt;p&gt;I write these tumblr blog posts using the &lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax&quot;&gt;Markdown&lt;/a&gt; syntax, which automatically detects and transforms URLs into proper HTML links. Though, things get messed up when I syntax highlight them with &lt;a href=&quot;http://alexgorbatchev.com/SyntaxHighlighter/&quot;&gt;SyntaxHighlighter&lt;/a&gt;.&lt;/p&gt;

&lt;!--MORE--&gt;

&lt;p&gt;I see something like (as displayed by the browser):&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://example.com&quot;&gt;http://example.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;instead of the expected:&lt;/p&gt;

&lt;p&gt;http://example.com&lt;/p&gt;

&lt;p&gt;So I dug into the code, and come up with this patch (apply into revision &lt;a href=&quot;http://bitbucket.org/alexg/syntaxhighlighter/src/b7578b438a69/scripts/shCore.js&quot;&gt;b7578b438a69&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-diff&quot; data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;gd&quot;&gt;--- a/scripts/shCore.js&lt;/span&gt;
&lt;span class=&quot;gi&quot;&gt;+++ b/scripts/shCore.js&lt;/span&gt;
&lt;span class=&quot;gu&quot;&gt;@@ -286,7 +286,6 @@&lt;/span&gt;
  highlight: function(globalParams, element)
  {
    var elements = this.findElements(globalParams, element),
&lt;span class=&quot;gd&quot;&gt;-     propertyName = &amp;#39;innerHTML&amp;#39;, &lt;/span&gt;
      highlighter = null,
      conf = sh.config
      ;
&lt;span class=&quot;gu&quot;&gt;@@ -322,7 +321,7 @@&lt;/span&gt;
          continue;
      }
      
&lt;span class=&quot;gd&quot;&gt;-     code = target[propertyName];&lt;/span&gt;
&lt;span class=&quot;gi&quot;&gt;+     code = target.innerText || target.textContent;&lt;/span&gt;
      
      // remove CDATA from &amp;lt;SCRIPT/&amp;gt; tags if it&amp;#39;s present
      if (conf.useScriptTags)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The text to highlight is now obtained from the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms533899&quot;&gt;innerText&lt;/a&gt; (works on IE / Chrome) or the &lt;a href=&quot;https://developer.mozilla.org/en/dom:element.textcontent&quot;&gt;textContent&lt;/a&gt; (works on Firefox / Chrome) property.&lt;/p&gt;

&lt;p&gt;I’m left wondering why &lt;a href=&quot;https://developer.mozilla.org/en/dom:element.innerhtml&quot;&gt;innerHTML&lt;/a&gt; was used in the first place… anyway, it now works as I expected!&lt;/p&gt;

&lt;p&gt;– RGL&lt;/p&gt;
</description>
        <pubDate>Sun, 12 Dec 2010 20:30:00 +0000</pubDate>
        <link>http://blog.ruilopes.com/fix-syntaxhighlighter-to-display-tumblr-markdown.html</link>
        <guid isPermaLink="true">http://blog.ruilopes.com/fix-syntaxhighlighter-to-display-tumblr-markdown.html</guid>
        
        <category>SyntaxHighlighter</category>
        
        <category>tumblr</category>
        
        <category>url</category>
        
        
      </item>
    
  </channel>
</rss>
