All posts by Dean

I unscramble eggs for a living. When not working I make, judge & drink beer. Whether working or playing I enjoy exercise & sporting, folksy-punk-rockish-bluesy-nerdcore music and mathematics. Around me is the best wife, loving family & great friends.

Setting User Preferences with Mission Control Desktop

A challenge with software

Managing software for thousands of users presents a formidable challenge to the system administrator. Publishing corporate policy, using standard environments and providing clear end-user documentation helps. However, it doesn’t beat automatically doing it right.  This is the power of MCD autoconfig.

In an earlier post, I introduced MCD as a way to configure Mozilla products (Firefox, Thunderbird, Prism, etc) and provided background on building them with autoconfig support.  This post covers how to get started with the standard javascript API.  In forthcoming posts I’ll detail the useful enhancements I built using this API.

The environment

First, a quick rehash of my world.  I work in a Solaris shop with over 33,000 users.  Supported users log into a shared Sun Ray server or their personal workstation which mounts a shared NFS directory.  That directory houses the software I support along with about 700 other programs.

While this post is unix-centric, other operating environments that launch managed software can make use of MCD. See the introductory post for  a little more detail.

Mozilla Preference System

Firefox and Thunderbird use a simple preference tree to store all configuration options. Leaves of the tree are strings that store the option’s value.  For example, the preference browser.startup.homepage is a string containing the URL(s) of Firefox’s homepage.  mail.forward_message_mode contains an integer indicating how Thunderbird should forward email messages (inline or as an attachment).  You can find every available setting and their values in the config editor for Thunderbird and about:config in Firefox.

When a user changes his or her preferences the changed values are stored in a file called prefs.js in their home directory. On my MacOS laptop, this is $HOME/Library/Application Support/Firefox/Profiles/kzssiknu.default.

The Application Programming Interface

The autoconfig acts on preferences through a javascript API defined in the file MOZILLA_LIB_DIR/defaults/autoconfig/prefcalls.js.  I will talk about the most useful in this post and cover the LDAP parts of the API later.

// Used most often
function defaultPref(prefName, value);
function lockPref(prefName, value);
// Sometimes used
function displayError(funcname, message);
function getenv(name);

defaultPref() and lockPref()

These two functions perform the bulk of work in an autoconfig script.  A default preference setting may be overridden by the user, but a locked preference may not.

getenv() and displayError()

getenv() acts as you would expect from its name. This function returns the value of an environment variable.  I use it to get $USER and $HOME. displayError() pops up an error message.  It is useful for debugging, but a user should rarely see it.

Putting it all together

We now have some basic building blocks to configure thousands of users. Here is a look at a simple autoconfig.js file for Firefox.  These settings will apply to every user.

// Catch errors
try
{
   // Set  downloads directory to a folder on the user's desktop
   var download_dir = getenv("HOME") + "/Desktop/Downloads";
   defaultPref("browser.download.defaultFolder", download_dir);
   defaultPref("browser.download.dir", download_dir);
   defaultPref("browser.download.downloadDir", download_dir);
   defaultPref("browser.download.folderList", 2);kk
 
   // Length of Time to Remember Visited Pages For (Days) - 30
   defaultPref("browser.history_expire_days", 30);
 
   // Automatically Add 'www.' and '.com' to the Location if a Web Page is Not Found - Enabled
   defaultPref("browser.fixup.alternate.enabled", true);
 
   // Lock the cache size to 60MB for shared performance
   lockPref("browser.cache.memory.capacity", 60000);
   lockPref("browser.cache.disk.capacity", 60000);
 
   // fix memory usage with lots of tabs
   lockPref("browser.sessionhistory.max_total_viewers", 2);
 
   // Set animated images to loop once
   defaultPref("image.animation_mode", "once");
 
} catch(e)
{
   displayError("autoconfig.js failed", e);
}

Learning preference strings

Finding the right preference setting or combination of preferences that change the program’s behavior sometimes presents a challenge.  I use the About:config entries page on the Mozilla Zine knowledge base.  That page also has a pointer to three more resources.

Another technique is to watch your own prefs.js file for changes when you twiddle settings.  Save a copy of prefs.js before flipping a preference.  Immediately quit the application after the change and diff the two files.

[Edit: I wrote up an entire post on this subject.]

Using LDAP and more fun things to do

In following posts I will cover retrieving information from LDAP, better error reporting, reading local files like $HOME/.printers, and simplifying Thunderbird email account management. Stay tuned.

An Introduction To Mission Control Desktop

What is MCD?

MCD (aka AutoConfig) is a script used to programmatically configure Mozilla products such as Firefox and Thunderbird in the enterprise for multiple users.  Part of my job is to ensure 33,385 people have the right settings to check their email and browse the web.  Centralizing their set up with autoconfig removes the burden from the user.

Why write about it?

Documentation on MCD is old, but not exactly out of date.  The basics of autoconfig have not changed since the age of the Netscape browser.  From trolling newsgroups, IRC and Google, I know many people use MCD, but share little about the subject. (Some do.)  Over the course of my work I wrote object prototypes, extended error reporting and generally tried to make using this bit of javascript easier. I want to reach out to the community and give a little back.

A quick run-through

Most people think of javascript as a browser technology. But, MCD has access to XPCOM, a bridge between C++ libraries and javascript, which gives the developer power to poke at Mozilla internals.  When Thunderbird (Firefox, Seamonkey, etc) launches, it executes a javascript script that makes use of a configuration API.

The autoconfig sets preferences exactly as a user would using about:config. It can also render preferences immutable, locking them down according to corporate policy.  When I inherited the script it was  simply a long string of preference directives with a little LDAP voodoo.

defaultPref("news.server_change_xaction", 0 );
defaultPref("mail.migration.copyMailFiles", false);
defaultPref("network.cookie.disableCookieForMailNews", false);
   lockPref("mail.remember_password", false);
defaultPref("javascript.allow.mailnews", false);
defaultPref("mail.addr_book.lastnamefirst", 1);
defaultPref("mail.toolbars.showbutton.file", false);
defaultPref("mail.toolbars.showbutton.junk", true);
defaultPref("mail.forward_message_mode", 2);
defaultPref("mailnews.wraplength", 72);
defaultPref("mail.wrap_long_lines", true);
defaultPref("mail.collect_email_address_outgoing", true);
defaultPref("mail.collect_email_address_incoming", true);

Not the easiest thing to grok.

After Thunderbird executes the autoconfig it starts up normally, applying saved user preferences. defaultPref settings are overridden by user preferences, but lockPref are not.

If you want to turn on a proxy server and force SSL in Firefox for every user it becomes easy to do:

// Set http proxy to your.server.domain
lockPref("network.proxy.http", "your.server.domain");
// Require and lock SSL
lockPref("network.proxy.ssl", true);

Details, implementation details

There are a number of things required to get MCD working.

Build *zilla (Firefox, Thunderbird, etc) with support

Your Mozilla product needs to be built with pref extension support. Add this to your .mozconfig file:

ac_add_options --enable-extensions=pref

To utilize LDAP (you do want to use LDAP, don’t you?) check the configure script for:

MOZ_LDAP_XPCOM=1

You can check about:buildconfig in Firefox to see if your build is good to go. While MCD documentation is sparse, the Mozilla Developer’s Center has plenty of build instructions.

Software distribution

I work in a Solaris world. Servers and desktops mount a shared NFS directory from a network of servers housing some 735 programs, including Firefox & Thunderbird.  The directory is mounted read-only so average users are not tempted to twiddle with the software.  Although I wrote this paper from a unix perspective the implementation will work in a Linux, Windows, or MacOS environment.  Mounting a shared software repository makes the system robust, however MCD works in a network of stand-alone desktops.

Breaking .cfg “encryption”

*zilla products first read a javascript configuration file in the lib directory called, for example, firefox.cfg.  In the beginning-time, Mozilla developers chose to ROT-7 encode the file, obscuring its contents from users.  When Netscape 7 came out, they did away with ROT-7 in favor of ROT-13. Many Firefox and Thunderbird .cfg files are still encoded this way using moz_byteshift.pl.

The rotary encoding is controlled by a setting in $MOZ_LIB_DIR/greprefs/all.js. At packaging time I patch this file, setting encoding to 0.

// ROT-encoding is bad, mmmkay?
pref("general.config.obscure_value", 0);  // for MCD .cfg files

This tells *zilla not to ROT-decode the .cfg file.

This shadowy file mojo likely came from the day of stand-alone workstations where users had root access and the software maintainers wanted to have just a little control over Netscape preferences.  Hiding the configuration file’s location gives you the illusion of control.

Now, the .cfg file is on a read-only mounted partition and nobody on the system has super-user level access. There is little danger of a user skirting corporate policy by turning off autoconfig.

Pointing *zilla at the autoconfig

When Firefox starts up it checks for and executes javascript a .cfg file giving it the autoconfig script’s path.

// $MOZ_LIB_DIR/firefox.cfg
// the output from the obscuration is still more readable than MORK!
lockPref("autoadmin.global_config_url","file:///path/to/firefox,v3.0.17/share/autoconfig.js");
lockPref("autoadmin.offline_failover", true);
lockPref("autoadmin.refresh_interval", 60);

I left the MORK comment line in there to remind me how far we’ve come already.

These directives:

  • Set the autoconfig url
  • Tell *zilla to automatically fail over to offline mode if online browsing fails
  • Re-fetch the autoconfig file every 60 minutes

Any URL *zilla understands is a valid value for autoadmin.global_config_url meaning you could house the autoconfig script on a web server.

Away you go

Now your Mozilla product will read and execute the javascript autoconfig script you indicated.  There you can set or lock application preferences using a specialized XPCOM API.  I will cover the API in a following post.

Barrelling Day


All those fermenting vessels under the looming Merlot barrel contain Russian Imperial Stout. Yesterday the TAbc drained the beer into that barrel to condition over the summer. The first task of the day was to sanitize the barrel with 20 gallons of boiling water.






The barrel sits high on its rack making gravity transfer tricky. The duck-in cooler gave us the necessary height.


Surprisingly little beer spilled, but what did come out flew across the room, landing on Ruth.

After a long day of barreling, the beer came to rest in my cold room, where it will sit until we bottle it in October.


I bottled a 12-pack pre-barrel for comparison.

Alt Two

My second try at an Altbier turned out better than the first. Alt One got an infection from the MiniBrew plastic conicals I was using. A tragedy, because it tasted so good coming out of the kettle.

Alt Two is not my own recipe, but a concoction from Jamil Zainasheff’s Brewing Classic Styles. Scaled up to 10 gallons the recipe is:

Fermentables

  • 18 lbs Pilsner
  • 2 lbs Munich
  • 0.5 lbs Debittered Black malt
  • 0.5 lbs Caramunich 60L
  • 6 oz Pale Chocolate malt 200L

Mashed starting at 151º, falling to 145ºF over the course of 60 minutes. (Need winter insulation for my mash tun.) Mash out at 160ºF. Sparge. Collected 12.5 gallons 11% B sweet wort. Boil 90 minutes.

Hops

  • 2.5 oz 8.1% AA Perle 60 minutes

Fermentation

Pitch a 1600ml starter of WLP 029 German Ale yeast into 14.3% B original gravity wort.

Fermented two weeks between 58º & 66ºF. Lagered for 26 days.

Notes

  • 2010-02-15 9.6%B Vinous notes
  • 2010-03-13 8%B Vinous flavors reduced. Ready to package.

It pours a deep copper brown with no appreciable head. Carbonation has not quite developed and I expect to get a good stand of foam in a few more days under pressure. There is roastyness up front and that vinous flavor refuses to disappear completely. This Alt puckers the mouth just a little, a problem attribute to poor scaling of the recipe from 5 to 10 gallons. The percentage of dark roasted malts may be too high. Bitterness is present and polite as appropriate for this malt-centric beer.

For my third Altbier I will find a common ground between One and Two. Not so much roasted malt as #2 and not so much Munich or Vienna as #1.

Tasting & Bottling Something Else

It is 14.6° Plato and Something Else is three weeks old. Starting at 25.2º P, the big gravity beer weighs in at a small 6.2% ABV. Before putting it all away for conditioning a little evaluation is in order.

There is a little ester in the nose. No hop aroma. The uncarbonated beer is sweet, bitter, roasty, “stout-like”, and lacks much fermentation character. Tastes a little like an over-hopped milk stout might. It sticks to your mouth.

It is close enough to be a Russian Imperial Stout, but lacks nuance due to the simplistic grainbill.

I have about 80 fluid ounces to bottle. The small volume batch is a breeze to work with. Next time I will remember to add priming sugar. Not to worry, the gravity is still drifting downward.

The Domestic & Something Else

Read from the bottom up:

twitter feedToday I brewed The Domestic for a second time. It is a Classic American Pilsner, also called a Pre-Prohibition Lager. The recipe is from Jamil Zainasheff’s book Brewing Classic Styles.

  • 12.5º Plato OG
  • 80% German Pilsner
  • 20% Flaked Maize
  • Rest at 148ºF for 60 minutes
  • Mash out to 160ºF
  • Collect 11.5 gllons
  • 2 oz 8.1% AA Perle FWH
  • 0.5 oz 3.8% AA Czech Saaz 30 mins
  • 1 oz 3.8% Czech Saaz 10 mins

I recently started doing a mash-out and this is my second brew session doing so. Combined with a slow sparge, I saw improved efficiency the first time. Today I ran into problems.

My mash tun is direct-fired and I recirculate the wort to prevent scorching. During vorlauf today my flow rate slowed to a trickle. Most of the time the March pump loses prime and I goose it a little to get it going again. When that didn’t work I stirred the grainbed and restarted the vorlauf. None of the usual tricks got the wort flowing again. But this was no ordinary problem.


That piece of hose pokes through the mash tun’s false bottom, acting as the pick-up. Heat from the burner melted it partially closed. Wort in the bottom of my tun scorched from lack of movement.


The sparge marched onward and I collected 11.5 gallons of sweet wort. I measured the gravity at 9.6º Plato, or 1.038. At that strength my post-boil gravity comes out to 1.043; 7 points too low. Reducing the volume to hit the gravity posed two problems. First, the style demands a light-colored beer and a prolonged boil would darken it too much. Secondly, the first hops were in the kettle and would throw off the bitterness balance. I cursed a little, tweeted then pushed on.

Ninety minutes later the brew was boiled then chilled and in the fermenter. When I lowered it into the converted chest freezer the bulges of the keg would not fit. Previously, I had tried to put the keg in the freezer with the same result, so I should have known. I grumbled a little.


It is now in my ale fermentation cooler, turned up to full blast cooling. When it comes time to lager this baby, I’ll split it into two carboys and put them in the freezer. Notice I hit my target starting gravity of 12.5º B.

After collecting the desired pre-boil volume I became curious how much wort I had left in the mash. Opening the spigot on the tun I dumped 6 liters of 9.6º B pale sweet wort into a bucket. With everything that went wrong today I was not about to waste so much potential beer.

Looking at my grain store, I picked an additional 2 lbs Crystal 60ºL and one ounce of chocolate malt. Approximating the recipe gives this:

  • 2 lbs German Pilsner
  • 2 lbs Crystal 60º L
  • 1 oz Chocolate

Post-boil volume would be less than a gallon

  • 0.3 oz 9.1% AA Centennial 60 mins
  • 0.5 oz 9.1% AA Centennial 15 mins
  • 0.5 oz 4.5% AA Fuggles 10 mins
  • 0.5 oz 4.5 %AA Fuggles 1 min


The final gravity turned out to be 25.2º P (1.107). It will probably be an Imperial Stout-ish. The yeast is a German ale/kölsh strain coming right out of an Altbier I put into lager tonight. Hope it can handle high gravity.

As an aside, I am quite fond of the brew-in-a-bag method those Aussies invented. Tonight’s second brew session was essentially that.

Basic Equipment

One of my friends asked what equipment she should get her boyfriend so he could start making beer. There are many equipment articles out there and here is one more

Note: If I were to write this up again, I would recommend the Australian brew-in-a-bag method rather than all the all-grain equipment.

I don’t know what your budget is… you can easily spend a few hundred dollars for a good kitchen setup.

The Minimum:

A large pot. Stainless steel is best, but aluminum is cheap. Like I said before, at least 2 gallons. The bigger, the better. Best is 6 gallons so he can do a full-wort boil where he doesn’t have to top off the fermenter with tap water. Boiling 5 gallons of wort on a kitchen stove is a big pain though, consider getting one of those turkey fryer burner deals. The one I used to have was a 7-gallon aluminum pot and a burner. Never did fry a turkey.

A fermenter. Go for the 6 gallon variety. I used glass carboys, but I have heard very good things about the Better Bottle. If I needed another (cheap) fermenter, I’d try one out. The homebrew shop will probably tell you need a primary & secondary fermenter, but that’s a big myth. I do my fermentations in a single vessel and make pretty good (damn good) beer. Politely decline.

Transfer tubing, bottling wand and a racking cane. Not too much to say here – the homebrew shop will know what you need. I recommend a stainless steel racking cane over a plastic one. It’s worth the extra money.

A bottling bucket.

Bottles. Five gallons of beer fills a little fewer than fifty bottles.

Sanitizer. Go for the “no rinse” variety. I switch between iodophor and 5-Star to keep the nasties on their toes. Buy in bulk.

Testing equipment. A floating thermometer or a digital thermometer on a probe. Also a hydrometer and a cheap graduated cylinder to take specific gravity readings in. Long ago I ditched the cylinder & hydrometer in favor of a refractometer. Really worth the extra money (but maybe only if you’ve been using a hydrometer for a while 🙂

That equipment will be enough to get him started doing “extract with specialty grain” (also incorrectly known as “partial mash”) brewing. The recipe kits are classified by the level of equipment you have. Since he’s got some brewery experience he will probably want to get into “all grain” brewing pretty soon. All of the above equipment will serve for that purpose, plus a few additional pieces.

All Grain

You definitely need the full sized pot.

A hot liquor tank (HLT). Ideally this is a vessel you can heat, but anything that keeps 3-5 gallons of hot water is fine. Many people use Rubbermaid or Gott coolers.

A mash tun. This is a vessel to hold the grain and hot water for making sweet wort. It’s slightly specialized because you need a filter at the bottom used to separate the sweet wort from the spent grain. If either of you is crafty you can make one on the cheap. Mine was a large cooler with the drain plug removed replaced by some copper fittings. Some rigid copper tubing with small holes drilled in it sat in the bottom connected to a brass ball valve on the outside. Served me well for five years.

Here’s a good shot of my previous all-grain setup. Left to right in the picture is a 5-gallon aluminum pot that I punched a hole in for the drain and spigot. It served as my HLT. Next is my mash tun which I described above. Lastly is a 10-gallon aluminum pot sitting on a burner. It also has a drain and spigot.

Consider a subscription to Zymmurgy or BYO Magazine. One of the books I recommend to everyone is Designing Great Beers. Really helped me understand the process.

Get involved in a homebrew club. They are the best places to learn the hobby. There are at least two in Oakland: The Draught Board & Bay Area Mashers (BAM). If you go to a Draught Board meeting tell Roger St Dennis I say hi.

I’ve gone on for a while now. There are a billion other brewing resources on the web.