Changing Elastic Beanstalk (Ruby) Passenger ngnix Config

January 19, 2014 16:20 by docbliny 

Is that title geeky enough for you? If so, keep reading…

Problem

I had to get Amazon CloudFront CDN configured this weekend for a Ruby project. This was mostly straightforward, and there are plenty of instructions on the web on how to go about that.

However, static assets are delivered by Phusion Passenger Standalone under the Ruby container for Amazon Elastic Beanstalk. This means you can’t set headers for those files in Ruby. Why is this an issue? Well, if you’ve got custom fonts, you’ll need to set CORS headers for those fonts to work on Internet Explorer and Firefox:

Access-Control-Allow-Origin: *

Solution

OK, this is where it gets to the usual “I just lost a day” situation. All the pieces were available, but getting everything glued together, and going through a rather slow deployment to test each iteration was a time sink. What you need to do is:

  1. Change the nginx configuration to add the CORS header to all font files by patching the Passenger config.erb template file.
  2. Patch Amazon’s broken /etc/init.d/passenger file so you can actually restart the service.

Note: I'm leaving the layout of this page broken in the file examples below to avoid confusion with line wrapping.

Modifying the nginx config template

You’ll need to create a file in the projects .ebextensions folder similar to the following:

00-passenger.config

files:
  "/home/ec2-user/inject_headers.sh" :
    mode: "000777"
    owner: ec2-user
    group: ec2-user
    content: |
      #!/bin/bash
      CONFIG_FILE=$(passenger-config --root)/resources/templates/standalone/config.erb
      MATCH=$(grep '(eot)|(ttf)|(woff)' $CONFIG_FILE)
      if [ -z "$MATCH" ]; then
        cp -f $CONFIG_FILE $CONFIG_FILE.bak
        sed -e'/location @static_asset {/a \\t if ($request_filename ~* ^.*?\.(eot)|(ttf)|(woff)$){ add_header Access-Control-Allow-Origin *; }' $CONFIG_FILE.bak >$CONFIG_FILE
      fi
commands:
  00-inject-font-headers:
    command: sh /home/ec2-user/inject_headers.sh
    cwd: /home/ec2-user

Then patch /etc/init.d/passenger:

01-patch-passenger.config

commands:
  01-patch-passenger-init:
    command: sed -i 's/passenger stop \$OPTS/passenger stop -p \$EB_CONFIG_HTTP_PORT --pid-file \$EB_CONFIG_APP_PIDS\/passenger.pid/' /etc/init.d/passenger

...and finally restart passenger so this goes into effect before CloudFront can hit font files and cache them without the correct headers:

02-restart-passenger.config

commands:
  02-restart-passenger:
    command: /etc/init.d/passenger restart

notes

  • This was done on the 64bit Amazon Linux 2013.09 running Ruby 1.9.3 container.
  • The real runtime nginx configuration file ends up under /tmp/passenger-standalone.[random]/config. Check it to make sure the changes are applied.
  • /log/var/cfn-init.log is your friend when debugging the .ebextensions.
  • I was having issues with the initial deployment for a newly created environment not being applied (I just got the placeholder page from Amazon). This was always resolved by pushing the same application version again to the environment. The error in the Beanstalk event console was: The following instances have not responded in the allowed command timeout time (they might still finish eventually on their own)

Is your Ajax application really slow on IE7? Here’s a tip

July 11, 2011 11:56 by docbliny 

Is your Ajax application running really slowly for users on IE7 (poor folks)? Have you narrowed down the cause to updating the history with location.hash? Is dynaTrace showing you that it’s actually the native DOM call hanging for more than 5 seconds?

If so, disable the Internet Explorer 7 Developer Toolbar and associated Browser Helper Object (BHO).


GWT Tip Of The Day

February 13, 2011 08:16 by docbliny 

Here’s a quick for anyone who is using Google Web Toolkit rebind and code generators. If you want to see the output of the created .java source file(s), add the “-gen gen” parameter to the compiler options. This will cause the GWT compiler to emit the files your generator created into a folder named “gen” next to the “src” directory.

CodeGen


Getting i18n with UiBinder up and running in GWT

April 12, 2010 16:24 by docbliny 

OK, fiddled around a little today with GWT trying to get i18n working with UiBinder. Ran into some issues that I was able to sort out so here’s the obligatory post. I’ll leave reading the basic information from the GWT docs up to you and only highlight the steps that seem to be missing. GWT 2.0.3.

 

Rough Overview

  1. Create a UiBinder *.ui.xml file with <msg/> elements.
  2. Compile the project using the –soyc or –extra compiler argument. –soyc does some extra legwork, so you may want to configure –extra instead. This generates .properties files in the extra folder.
  3. Copy the generated properties file(s) from the extras folder into the folder where the *.ui.xml lives.
  4. Rename the properties file(s) removing the namespace from the beginning. Note that the class name is duplicated. For example, if the your UiBinder file is named MyView.ui.xml, then the properties file should be named MyViewMyViewUiBinderImplGenMessages.properties.
  5. Create translated properties files by appending _XX (language, independent of country) or _XX_YY (language_country) to end of the filename, before the extension. For example, MyViewMyViewUiBinderImplGenMessages_fi_FI.properties.

Editing Properties Files In Eclipse

Please be aware that the properties files need to be encoded as UTF-8 and by default Eclipse will encode using ISO-8859-1. You’ll probably want to change the default encoding for .properties files as follows before editing them. Otherwise, Eclipse will simply save them with the incorrect encoding.

  1. In Eclipse, click the Window-menu, and then click Preferences.
  2. Expand and select General/Content Types in the options tree on the left.
  3. In the Content types list, select Java Properties File.
  4. In the Default encoding field, type UTF-8.
  5. Click OK.

 

Set Default and Fallback Language

[Untested, beware] By default GWT uses a locale named “default”. You’ll most likely want to change this to whatever your real default language is. You do this in (each of) the module XML files, for example MyModule.gwt.xml. Here’s what I did to switch to “en” as the default and remove the “default” from the compile permutations.

<extend-property name=”locale” values=”en”/>

<set-property name=”locale” value=”en"/>

<set-property-fallback name=”locale” value=”en”/>

And then I added another language:

<extend-property name=”locale” values=”fi”/>

 

Optimizing Compile Permutations

While I’m almost still on the subject of compile permutations, you can continue to edit the MyModule.gwt.xml file to optimize how many permutations GWT creates for languages and browser combinations. To remove languages for development, just comment out the extra languages you added in the previous step. To modify which browsers should be compiled to, add and edit the following like:

<set-property name=”user.agent” value=”safari,ie8"/>

Separate multiple browsers with a comma. Here are some supported values:

  • safari
  • gecko
  • gecko1_8
  • opera
  • ie6
  • ie8

"MX" records for Google Wave?

November 11, 2009 08:29 by docbliny 

Does Wave (the Wave protocol really) have any notion of DNS records similar to MX records for email? As a user, I find it confusing that I have to add people to my contacts as "user@googlewave.com" when their real account is "user@gmail.com" for example. As far as I have bothered to look into it, this is because the user's identity is tied to the Wave server directly (for federation). This in itself is a step backwards. There's a reason OpenID was created, namely to associate identity with a user and not a system. Though how you'd really implement that type of disassociation with Wave Federation isn't something I could say.