R2D6

The Blog of Erik van Eykelen

Geek, developer, entrepreneur

R2d6_header
Chicago

Overriding localized Google search page

Wednesday April 13th, 2011

When you travel a lot you'll notice that Google constantly tries to be smart in its attempt to serve the localized Google search page. Some people may like this but I find it pretty annoying. Especially if you're using Chrome it can be quite hard to get rid of this behavior.

Go to the Chrome preferences screen and click on "Manage Search Engines" on the Basics tab. Overwrite the first row with the following settings:

Google search engine settings

The trick is to use google.com/ncr which tells Google not to play funny games in trying to locate you. You can use this in any browser but I've used Chrome as an example since its search engine management is clumsy.

Leave a comment

Setting up private streaming with Cloudfront and Ruby on Rails

Sunday March 27th, 2011

I had to setup private streaming using Amazon's Cloudfront for a project recently. I thought it would be pretty straightforward but it took me a bit longer than expected. I hope this blog post gives you a kickstart with Cloudfront and Rails.

Let's summarize the entire process first before going into the details. In order to setup private streaming you have to take the following steps:

  • Create an S3 bucket and upload some video files to this bucket.

  • Create a CloudFront distribution.

  • Give CloudFront access to your S3 bucket.

  • Create an AWS public and private Key Pair.

  • Look up your AWS Account Number.

  • Create a test web page and test whether you can playback your video files.

Below are the details for each step:

I'm using a tool called Bucket Explorer for OS X (it also works on Windows and Linux). It is aptly named because it's a bucket of hurt. It is ugly (like most Java desktop apps), it's buggy, riddled with spelling mistakes and confusing, inconsequent wording but it gets the job done and it is (as far as I know) the only app for Mac that enables you to manage the complete cycle described below. For Windows you might want to check out an app called CloudBerry.

Create an S3 bucket and upload some video files (FLV, MOV, M4V or whatever you prefer) to this bucket. Set the "Group: All users" permissions to None, if this is not already the case. You don't want folks to be able to simply download your files from S3 defeating the whole purpose of private streaming.

Launch Bucket Explorer and create a new distribution:

Create new distribution

Figure 1

  • Choose the S3 bucket you created from the "DNS Name" drop-down.
  • Select "private streaming" from the "Type" drop-down.
  • Add an optional CNAME. I recommend doing this later, after you've checked that everything works without a CNAME because it introduces an extra point of failure if you do it wrong.
  • Tick the "Enable Distribution" check box.
  • Click the "Advanced" button (see next screenshot).

Advanced settings

Figure 2

In the Advanced window you must do three things:

  • Tick the "Make Private Content Distribution" checkbox.
  • Click the Generate Origin Access Identity button. You should only do this once. You'll be able to re-use the ID for other distributions.
  • Click the "Trusted Signer Account Number" field and paste your AWS Account Number. Click the "+" button to add the Account Number.

You can find your Account Number in your AWS Account Settings screen:

Account Number

Figure 3

Click OK in the Advanced window to save your changes. If you go back to the Advanced window and you don't see your Account Number listed then don't despair. If the account you are using to sign into S3/CloudFront is the same account to which this Account Number belongs then Bucket Explorer will not show this number.

When you click "Create" (or "Update") in the Distribution window then your distribution will be picked up by the CloudFront edge servers. Note that this can take a while, I've seen it taking anywhere between 5 to 15 minutes. During this time the Status will be "InProgress" (sic).

Bucket Explorer

Figure 4

You'll end up clicking the Refresh button a lot in Bucket Explorer because it hardly ever refreshes the UI automatically.

While you're waiting for your distribution to be pushed to far away places on the planet, you should copy the so-called "S3 Canonical User ID" to the clipboard. You do this by clicking the "Origin Access Identity List" button which opens a window containing one or more IDs. Select the one you used in the Advanced window (see figure 2). Then click "Copy S3CanonicalUserID" to copy the ID to the clipboard (notice the sloppiness of the Bucket Explorer developers when it comes to spaces and lower/uppercase).

Bucket Explorer

Figure 5

Now close the Distribution window and return to the list of S3 buckets. Select the bucket you wish to make available to the CloudFront distribution you just created. After selecting the bucket, click the ACL(s) icon to open the ACLs Preferences window. In there, click the "Add access by Email-ID/ID" button. Paste the S3 Canonical User ID from the clipboard into the text field. Click OK to save. Do not forget to tick the "Read" permission for this new "user". Click "Update ACL" to set the permissions for this bucket and its files.

Bucket Explorer

Figure 6

I've had a fair share of issues setting permissions to buckets and files inside buckets. Sometimes it seems Bucket Explorer does not set the permission to all files inside a bucket. I have not been able to pinpoint the exact reason. Just make sure that the bucket and file(s) you're testing with are set to the proper permissions.

You can check whether the permission for a bucket or file is properly set by selecting an object and clicking the "ACL(s)" button again. If all is well, the S3 Canonical User ID should match the details as shown in figure 5 (in this example notice that the origin ID in figure 5 and 7 both end with "…GI").

Bucket Explorer

Figure 7

We're almost ready to start testing the new distribution in a Rails project. Two steps remain though. In the code example you'll notice a reference to a streamer URL. This is the URL of the CloudFront (streaming) distribution server (Amazon actually provides the capabilities of Adobe's Flash Media Server). Go back to the Distribution window, select the distribution you just created and right-click to reveal a contextual menu. Select "Copy DomainName" (sic) to copy the URL to the clipboard. Store it somewhere because we'll need it later on.

Bucket Explorer

Figure 8

Another piece of data we'll need later on is a private key and Key Pair ID. You can create these by going into your AWS account (look for the "Security Credentials" menu).

Bucket Explorer

Figure 9

You can create up to two key pairs. Create one now if you haven't already. Be very careful to store the private key in a safe place because AWS only hands it out once (they don't even store it, obviously). Also copy the "Key Pair ID" and store it somewhere because we'll need it later.

Now we're finally ready to test the private streaming distribution. Before you start coding, check whether the distribution status says "Deployed" (see figure 4).

In order to test the streaming distribution, create a new Rails project and add the class below to the models folder (or place it in a "lib" or "extras" folder, I like to separate ActiveRecord models from other classes).

class Cloudfront

  require 'openssl'
  require 'digest/sha2'
  require 'base64'

  KEY_PAIR_ID = "---replace-me---"

  def self.get_url(_request, _resource)
    url = get_signed_url(_resource, _request)
    # Escape characters for proper embedding in Flash parameters
    return url.gsub("?","%3F").gsub("=","%3D").gsub("&","%26")
  end

  protected

    def self.get_signed_url(_resource, _request)
      pk_file        = Rails.root.join('config','--your-private-key--.pem')
      key            = OpenSSL::PKey::RSA.new(File.readlines(pk_file).join(""))
      policy         = create_policy(_resource, _request)
      sigcrypt       = key.sign(OpenSSL::Digest::SHA1.new, policy)
      urlsig         = escape_string(Base64.encode64(sigcrypt))
      encoded_policy = escape_string(Base64.encode64(policy))
      return "#{_resource}?Policy=#{encoded_policy}&Signature=#{urlsig}&Key-Pair-Id=#{KEY_PAIR_ID}"
    end

    def self.create_policy(_resource, _request)
      expires = 1.hour.from_now.to_i
      # Skip IP check for localhost (AWS:SourceIp does not work with localhost)
      if Rails.env.development?
        policy = %{ {"Statement":
          [{ 
            "Resource": "#{_resource}",
            "Condition": { 
              "DateLessThan": { "AWS:EpochTime": #{expires} }
            }
          }]}
        }
      else
        ip = "#{_request.remote_ip}/24"
        policy = %{ {"Statement":
          [{ 
            "Resource": "#{_resource}",
            "Condition": { 
              "DateLessThan": { "AWS:EpochTime": #{expires} },
              "IpAddress": { "AWS:SourceIp": "#{ip}" }
            }
          }]}
        }
      end
      return policy
    end

    def self.escape_string(_str)
      _str.gsub('+','-').gsub('=','_').gsub('/','~').gsub(/\n/,'')
    end

end

Finally you can create a view:

<% 
  # If your S3 path looks like this: https://bucketname.s3.amazonaws.com/videos/video1.flv
  # then filename must be 'videos/video1.flv'
  filename = 'videos/video1.flv'
  file = Cloudfront.get_url(request, filename)
  player = '/swf/player-5.5.swf' # E.g. JW Player
  streamer = 'rtmp://--replace-me--.cloudfront.net/cfx/st' # Your distribution URL or CNAME, no trailing slash!
  width = 640
  height = 480
  flashvars = "file=#{file}&streamer=#{streamer}&height=#{height}&width=#{width}&autostart=true"
%>
<object type="application/x-shockwave-flash" id="player" name="player" data="<%= player %>" width="<%= width %>" height="<%= height %>" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000">
  <param name="wmode" value="transparent" />
  <param name="movie" value="<%= player %>" /> 
  <param name="allowfullscreen" value="true" />
  <param name="allowscriptaccess" value="always" />
  <param name="flashvars" value="<%= flashvars %>"/>
  <embed type="application/x-shockwave-flash" src="<%= player %>" width="<%= width %>" height="<%= height %>" allowscriptaccess="always" allowfullscreen="true" flashvars="<%= flashvars %>" />
</object>
  • The "filename" variable must be set to the file name without the bucket part. This is crucial but logical. The distribution already points to your bucket, so it knows the base path for your files.
  • The "player" variable must point to a Flash video player. I use JW Player but other players should work as well. If you don't get it working with another player then first try JW Player and then try to get this other player working by iterative debugging.
  • The "streamer" variable must be set to the domain name you previously copied (see figure 8). Paste it where the code says "--replace-me--". Do not put a slash behind the ".../cfx/st" part of the streamer URL.

Once you've modified the variables to match your setup, hit reload and your video should start to stream from your secure distribution.

4 comments

The largest project ever

Sunday March 6th, 2011

[Disclaimer: fantasy ahead]

China is run by leaders who are engineers and scientists who became political leaders. China is also the second largest economy in the world. Now there’s one thing engineers really like and that is big projects.

One day these leaders will show the world that China can pull of the greatest stunt in the history of mankind. In fact, it would be the largest and boldest undertaking in our solar system.

Historically China has not taken part in discovering new continents. The historical emperors were too occupied getting and keeping their vast empire under control. Not much has changed since.

I bet China is going make up for this. It's going to discover and colonize a new world instead of a continent. It's going to create a second China. A China with room for billions of people. This new place will be Mars.

Why would China do this? Because they can, because they have the means, and because it's plain cool to bring the Chinese culture to another planet and start all over over on a pristine planet.

This project will cost approximately 50 billion per year during the first 10 years (in comparison: China spent $98 billion on defense in 2009). The project will continue to cost this amount for at least 30 years. Now 1500 billion is a lot of money but it’s the same amount the US spends in less than three years on defense alone and the entire Apollo project cost roughly $170 billion in 2005 dollars.

For this money China would first build a smart way to deliver heavy payloads to space. Not using big rockets, but by using thousands of robot airplanes slowly circling the planet, getting higher and higher over the course of several days. Rockets are big and dangerous. Slowly gliding into space is zen, and you only need a small rocket for the final push into low earth orbit. Robots are not in a rush anyway and they don't need sleep.

Astronauts will assemble China's first space station (robots and socket wrenches still don't agree very well). The purpose of this station is not to make dull circles around Earth. One day massive boosters will fire and the space station will become a cargo ship and set sail for Mars. No humans will be on board this first trip. Again, they take the slow lane, making use of the Moon and Venus to gain speed enabling the station to save on propellant needed for slowing down at the end of the journey.

When the cargo ship arrives at Mars, it will dock with Phobos, the largest of Mars' two moons. Hundreds of container-like modules will be dropped onto the surface of Mars using parachutes and reverse thrusters. Robot trucks inside those containers will collect other containers and haul them to a single spot on a flat plane. Only 5% of the containers need to be retrieved, more is nice but not necessary (humans can always retrieve the redundant, hard to find containers in later years). The collected containers contain food, water and materials for humans to survive for five years. Among the stuff sent to Mars are small nuclear reactors, solar panels, factories-in-a-box, greenhouses (to grow vegetables) and tons of mining and farming equipment and construction tools.

Once everything is up and running, and at least two of the nuclear reactors are properly working and robots have assessed that the life support systems are in good order, the next step will be taken.

The next step involves getting a hundred people to Mars. Not just five, one hundred. And they will not be able to go back.

This team will get to Mars using a second space craft, similar to the first one but with tons of extra insulation (mostly just water) to protect them from solar flares during the trip.

Besides this passenger space craft, the thousands of robot planes that were used in the construction of the two stations will accompany the passengers on their journey to Mars. Along the way to Mars, one relay station after the other will unhook from the caravan and take up a strategic position between Earth and Mars. These stations can act as signal boosters, to improve communications between Mars and Earth, and act as safe havens storing food, water, energy and spare equipment for when new waves of humans are starting to travel to Mars.

Mars terraformed The first hundred Chinese who land on Mars will construct living quarters, set up the factories and be mostly involved with mining and farming over the course of 5-10 years.

Only when iron ore and other resources like water have been found in large enough quantities, green light will be given to send the next hundred. Over the course of 20-30 years hundreds of thousands Chinese will land on Mars.

After 50 years the third phase will kick in: the new Martians will have developed space craft able to get back to Earth. A steady supply of rare metals and other natural resources will be shipped back to Earth, creating the first interplanetary trade route.

Whether the settlers are able to terraform Mars is unknown. It requires immense amounts of energy to warm the entire atmosphere and pump oxygen into it. But new scientific breakthroughs might make this not necessary, creating self-replicating glass structures to build huge domes over canyons and craters. It's much easier to terraform a small patch of land than an entire planet.

China will show the world (that other world, called Earth) that it is capable of discovering and colonizing a new frontier, surpassing the West by several orders of magnitude in difficulty and investment compared to what Columbus and Vespucy did.

It will be a special day when the first web server is fired up on Mars, and Earthlings will be able to go to http://marsdaily.mars to read about the latest news from the new frontier.

One comment

User interface URLs

Monday February 21st, 2011

The new HTML-based preference screens in Chrome have one, perhaps unintended, side effect: you can send a link to someone pointing to a particular preference screen. This is very handy for support desks who can now simply instruct the user to go to chrome://settings/advanced.

What is not yet possible (as far as I know) is to highlight a section of the preference page that deals with the user's question. Wouldn't it be great to be able to do this: chrome://settings/advanced#Web+Content (the fragment identifier is mine):

User interface URLs

Optionally the fragment identifier could be preceded by e.g. ! to indicate that the section should be highlighted (if omitted the page will simply scroll to the section which is normal HTML behavior).

This idea could be extended to any site to improve customer support with a simple JS include. The fragment identifier can consist of human-readable titles (like the example above, in which case JS must translate the ID to a DOM element) or contain a CSS selector expression.

Leave a comment

10 things to fix with hotel internet connection services

Sunday February 6th, 2011

1 - Don't make me sign-in[1] with long access codes that make no sense. The room number plus my initials should suffice e.g. 511eve.

2 - Don't redirect me your (cough) Flash hotel home page after I've signed in. Instead, redirect me to the page I wanted to go to in the first place.

3 - Allow me setup my own mini wireless network[2]. In this way I can use my phone, a tablet and laptop in my room without having to sign in again on every device. Often this is not possible due to frustrating 'smart' blocking on MAC addresses, user agent headers and what not.

4 - Always provide a sign in code to every guest, don't make me have to ask for it when checking in or call down to the lobby.

5 - Don't charge extra for the internet connection. You don't charge extra for the use of water, electricity, or air conditioning. I expect hot water to be present in the room, the same applies to an internet connection.

6 - Let the connection session time-out after e.g. 34 hours instead of 24 hours. It's likely that I check my email every morning around the same time so timing out after 34 hours means I have to sign in less often.

7 - Provide enough bandwidth. Perform a regular speed test yourself and upgrade the pipe if the speeds drop below 2 mbit on average, measured daily over 2 weeks.

8 - Don't make guests have to switch rooms because the room has a spotty wifi signal. Having to switch rooms is annoying for the guest and expensive for the hotel (two rooms to clean and prepare for the next guest). Installing a repeater is cheaper (when you look at the bigger picture, including customer churn and housekeeping costs).

9 - Don't block ports or protocols. Let me use SSH. I need it for my work.

10 - Don't force me to keep open some lame pop-up to stay signed in. It's brittle and it doesn't work with modern browsers with built-in pop-up blockers. Moreover it doesn't work on smart phones, tablets or a personal wifi router.

[1] Many hotels are in densely populated urban areas. Nearby offices should not be able to have a free ride on the hotel network so I understand the requirement to sign in.

[2] I always bring my Apple Airport Express with me when travelling since it's not much larger than a laptop charger.

Leave a comment

About me

My name is Erik van Eykelen and I help launch and build technology companies. Born in 1968, raised in The Netherlands, living mostly in France with my wife Rieta and our son David. More...

Ventures

Transp

Transp

Transp