Sunday, April 6, 2014

Beta Testing a Headless Raspberry Pi Confgurator

So I finally had the time to hobble together an open source version of the headless Raspberry Pi config interface I've been working on. It's used in applications where you want your Raspberry Pi to act as a "headless" server (i.e. - it doesn't have a video screen.) The configuration steps you would normally perform using the raspi-config utility are performed using a web page accessed over the network.

If you have a Raspi with a USB wireless adapter (like this one, sold by Adafruit) you'll be able to test it out. Note. This rev only works with the adapters that use the RTL 871X driver. The official version will support many more USB devices, and you can always access the interface over the wired network connection.

To try it out, download the image from http://sm5.us/2014-01-07-starless-raspbian.img.bz2, unzip the file, then write the image to a SD card. After that, you just boot your raspi and look for a wireless network whose name is something like starlessXXXXXX. Connect to the wireless network using the pass phrase starless, and then go to http://y.sm5.us/ to see the admin interface.

I haven't configured mDNS yet, so accessing the interface via the wired interface on a Model B is a little trickier. It's setup to do DHCP on eth0, so if you have your raspi working now with DHCP, it should still work. You'll have to figure out what the IP address is by yourself, but that's the hardest part. I've configured my DHCP server to always hand out the same IP address to my raspi, so i just added the line

192.168.1.3  y.sm5.us

to the /etc/hosts file. Your raspi probably has a different IP address, so... substitute 192.168.1.3 with whatever your IP address is.

The interesting bit I'm trying to test out right now is to make sure the interface works with popular mobile phones and tablets. Unlike previous web experiments, I'm not doing anything fancy, so as long as you have a reasonably modern browser that handles JavaScript and jQuery, you should be fine.

If you have questions, comments or just want to tell me you tried it and it worked, ping me at @OhMeadhbh on twitter or via email at OhMeadhbh [at] gmail [dot] com.

-Cheers!

p.s. - like most of the project names I use, the name "starless" comes from a King Crimson song; "Starless and Bible Black" in this instance.

Tuesday, March 25, 2014

Why I Don't Care About Brendan Eich's Prop 8 Donation

The social media universe is all a'twitter about Brendan Eich's recent promotion to CEO of the Mozilla Corporation (MoCo). Brendan Eich is, as you probably remember, the guy who invented the JavaScript programming language. Eich was at the time, an engineer at Netscape, moving over to the "Mozilla Organization" in 1998 and then the Mozilla Foundation (MoFo) in 2003. By this time he had risen to a position of technical leadership and was, in fact, one of co-founders of the official Mozilla Foundation 501(c)(3). As the Mozilla Foundation morphed into the Mozilla Corporation for tax reasons, Eich eventually landed as MoCo's CTO.

The thing that has the twitter-verse up in arms is Eich's contribution in 2008 to a Pro-Prop-8 organization. For people outside California, Proposition 8 (aka Prop 8) was the "marriage is legally defined in California as being between one man and one woman" proposition that went before the electorate and (somewhat surprisingly) passed. Prop-8 has since been overturned by the courts and all is as it should be.

But there are a lot of us queers in the tech industry and it turns out we have access to political donation rosters (actually, everyone has access to these rosters, they're public information.) And we apparently have reasonably good memories. In 2012 someone noticed the donation and a brouhaha emerged. When Eich was named MoCo's CEO yesterday, the brouhaha re-emerged with some people saying we should boycott Mozilla. Rarebit, for instance, removed their color puzzle app from the Mozilla Marketplace in protest.

In the interests of full disclosure, I worked for MoCo for a brief period of time in 2013 and met Mr. Eich several times. I did not work especially closely with him, nor did we discuss politics. But I had enough encounters to develop this impression: Brendan Eich is a Geek (and I mean that in the good way.) He is, like many in Sili Valley, slightly nerdy, a little more focused on tech subjects than on intra-personal skills. He's not rude, it's just clear he would annoy the living hell out of Emily Post.

I've seen Eich interact with people at MoCo, including people I know he knew were gay. He didn't appear to treat them in any way differently.

And yes, it is troubling to find the CEO of Mozilla's name on a list of people who donated to political causes that sought to deny basic human rights to a minority population. But I personally believe the issue is not so much an issue of homophobia than it is ignorance. I honestly believe Brendan Eich grew up in an environment that reinforced ideas of the moral superiority of "traditional" relationships and he never gave it a second thought.

It would be very nice if Mr. Eich would come out and say something like "Totally sorry about that Prop-8 donation. Upon further reflection, I think it was an inappropriate thing to do." But honestly, I don't think he's under any obligation to do so.

Corporations aren't people, nor are they responsible for the beliefs of their employees. By boycotting Mozilla (the corporation) because one employee did something politically objectionable, you are asking the corporation to police not only the behaviour of it's employees, but also their beliefs. I find Eich's support of Proposition 8 objectionable, but it is more objectionable to ask corporations to deny promotion to individuals who exercise their right to support political efforts outside the corporation.

If you're looking for reasons to hate on Mozilla, there are several to choose from: FirefoxOS' "race to the bottom" strategy, declining market share or questions surrounding the post-2014 funding from Google now that MoCo competes with Android, etc. But having a CEO who thinks my marriage was abhorrent? That's just life in a pluralistic society.

Wednesday, March 19, 2014

Chapter 3 of my still unnamed Space Vikiing saga

"Hierophant of Discord," Fram said while slapping down his card, "ditch 'em if ya' got 'em!"

An audible sigh came up from Gerstlauer; he had bid blind, not knowing if Fram could cover him.

Gunnr played next, wincing as she threw down the Queen of Discord. She had been saving it to win the next trick and now her plans fell apart. Fram and Gertlauer giggled like kindergartners at the site and broke into full-on laughter as Gert threw down the King of Claw.

"You bid zero with the King of Claw, you have huge balls, my friend!" Wido, the fourth of the card players, cracked at the sight.

Gunnr retorted sourly, "He bid blind. He couldn't have known. His balls are of normal size." The only one of the four to take the loss personally, she complained "come on, let's finish it and get back to work."

"Gunnr, it's just a game. Many days you take us for five times as many points as you lost here," sagt Fram, just becoming aware of her sourness. "But yes, we have three minutes before work resumes. My last two cards are shit," he said, throwing them down face-up on the table leaving Wido and Gerstlauer to argue over who took the last
two tricks.

Gunnr was up and walking back towards her work-station at the forge control. Every bit of her body language screamed tenseness.

Fram caught up with Gunnr, who had already made it several meters from the table. Summoning every bit of grandfatherly softness he could, "what's wrong?"

She waved him away, "Don't try that grandfather business on me! You're not _that_ old," she shot back with surprising venom for someone who had worked with Fram for almost a decade.

It was true Fram wasn't quite old enough to be her grandfather, but could easily be her father. Genetics on the colony were such to make it impossible, of course. But genetics don't stop people from familial attachments; the entire colony would be in a sorry state if it did.

Growing concerned with Gunnr's mood, he tried a different tack, "Gunnr. You have to be here every moment of every day. I won't have you risk injury on my rig 'cause your head is a million miles away."

"No Fram. It's okay. I'm fine." she protested.

Fram was trying to figure out if he had asked her two or three times. Traditions varied amonst the colonists, but all bought into the concept of the heroic self-sufficient individual. Common manners were to deny any sort of help two or three times before admitting you were in need. Fram was old enough to realize what kind of crap this tradition was. He had seen too many people get into too much trouble 'cause they were too proud to let someone help them. The simple fact of the matter was the colony's existence was too tenuous for pride to get in the way of survival.

"Gunnr. I am your work foreman and your friend. I will stay here all day playing stupid manner games, but I will not leave until you tell me what is wrong."

Gunnr leaned in close and whispered a few words in Fram's ear.

All Fram could say in reply was, "Holy shit."

"Yeah," she replied, "you want me here, still?"

"You want to take a day or two off? We're way ahead on our quota, we can manage without you a couple days."

"No Fram, I think I want to be here. Working will take my mind off it." Gunnr replied.

"That's fine. But I want to slow down a bit; no sense tempting fate," Fram said, his eyes darting back and forth the way they do when he's crafting a plan, "Tamsen will ask why we're slowing down though, so let's make up a story of instrument failure or something."

In the eight years Fram had known Gunnr, the hug she gave him was the first time he had know her to do anything even slightly feminine. Taken aback a little, "I love you too, sweetheart," was the only thing he could think to say as he hugged her back.

Thursday, January 30, 2014

A Quick Note About the Space Economy

In the last week I've been in a couple very good conversations with people about developing the "space economy." And it's all good; from private launch companies like Orbital and SpaceX to cohorts of enthusiasts willing to die on Mars in the name of exploration and reality television ratings. But there's one thing people have been missing... the space economy isn't about going there and bringing things back, it's about going there, in-situ resource utilization and then staying there a while

So it's great when we can launch people to the ISS to research what happens to pumpkin seeds in zero-g, but until they can order a pizza for delivery in LEO, we don't really have a space economy. At best, we have a terrestrial economy with brief forays into orbit. Until we have enough development of non-terrestrial resources that the majority of productive activity is for the benefit of other non-terrestrial development, we're not going to have a space economy.

Just Sayin'.

Tuesday, January 28, 2014

Using SN-App to Avoid Reinventing the Wheel

Software people who know me know I don't like cut an paste programming. If you can refactor common bits of code out of a program, you probably should. Copying code leads to drudgery and errors if you find you have to change all those places where you hit Ctrl-V. So you can imagine how torked I was at the Node.JS common practice of building new code every time you built a new app. (Granted, it's less common than it used to be, but it's still surprisingly common.)

After the first three connect.js apps I wrote, I refactored the common bits out and made a quick "app runner" that read a config file, used its contents to decide what bits of connect.js middleware to use and then call a different JavaScript module... the one with the "real" code in it. After a couple years of refining, I recently released it as SN-App.

If you use connect.js or express.js, you might find it useful. Rather than writing code to explicitly add commonly used middleware to your Connect or Express app, you build a JSON file listing which bits of middleware you want to load and their parameters. SN-App reads this file and adds the appropriate middleware for you.

Here's a simple SN-App config file. Readers familiar with Connect can probably guess what will happen when it's processed:

properties.json:
{
  "title": "SampleApp",
  "favicon": "static/favicon.ico",
  "static": "static",
  "listen": {
    "port": 80
  }
}

When you execute the SN-App application with the command `sn-app --config file://properties.json`, it loads Connect's "static" middleware to serve static files out of the directory "static" and listens for requests on port 80.

But why use Node if you're just going to serve static files? If you add these lines to the config file, it will turn on the Body Parser middleware and load an additional JavaScript module from src/logic.js:

  "bodyParser": true,
  "source": "src/logic"

And if you're a little lazy, you can ask SN-App to build a skeletal web application for you, complete with a skeletal Bootstrap or Semantic-UI front page. If you wanted to build a simple app to run on port 9001 and served a Semantic-UI index page, just do this:

sn-app-build --title SampleApp --port 9001 --static static \
  --css semanticui
make
sn-app --config file://SampleApp.json

Up and running in seconds flat. If you want to do anything interesting, you'll likely have to edit the SampleApp.json file to do anything interesting, but hey, you were going to do that anyway. SN-App doesn't write the interesting bits for you, it gets the boring bits out of your way so you can get straight to the fun stuff.

Lastly, you can ask SN-App to build a debian init file for you. After running sn-app-build to build the app skeleton and running sn-app to make sure it works, the sn-app-initgen command will generate an init file suitable for inclusion in >/etc/init.d:

sn-app-initgen --name SampleApp --desc "A Sample Application" \
  --dir `pwd` > /etc/init.d/sample
ln -s `which sn-app` SampleApp
chmod 755 /etc/init.d/sample
insserv sample
# Older debians may have to use update-rc.d instead of insserv.

Installing SN-App is pretty straight-forward as well; just use NPM:

sudo npm install -g sn-app

And with that, you're ready to go. For detailed info about properties file options, see the documentation at https://github.com/smithee-us/sn-app - and as always, ping me with questions or comments.

Sunday, January 26, 2014

Why I Developed the SN-Props Package for Node.JS

People who know me know I'm a bit of a nut for Node.JS, the JavaScript Application Framework. Over the past several years, I've been writing packages to make developing applications easier. The one that can have immediate utility to virtually all Node developers is SN-Props (fomerly node-props.) On the surface, it looks like a simple package that reads a JSON configuration file from the command-line and passes it to the program shortly after launch. It certainly does do that, but it's even a little more capable, so I figured it would be useful to describe what I was trying to build and the problem I was trying to solve.

In the old days the preferred method of changing the behavior of a program from "Development Mode" to "Production Mode" was via the NODE_ENV environment variable. Before you launched the program, you set this variable to "production" or "development." Inside the program, you would check the environment variable and change your settings appropriately. This led to code that looked like this:

var listen_port;
var listen_addr;
var db_addr;
var db_pass;

if( "production" === process.env.NODE_ENV ) {
  listen_addr = "0.0.0.0";
  listen_port = 80;
  db_addr = "prod-db.example.com";
  db_pass = "DJl87sJXX01";
} else {
  listen_addr = "127.0.0.1";
  listen_port = 8080;
  db_addr = "localhost";
  db_pass = "password";
}

The biggest problem I have with code like this is it makes Node applications brittle. You wind up hard-coding things like database addresses & passwords into the app. If your operations staff needs to change the IP address or password of a machine, you have to track down a developer. And worse -- you wind up committing your database passwords to your source repo.

So the next thing we tried was to read a different JSON configuration file based on the environment variable. That file would contain all your favorite settings in a separate file. During development, you would use the file "dev.json" and in production you would look for "prod.json":

prod.json:

{
  "listen_addr":"0.0.0.0",
  "listen_port": 80,
  "db_addr": "prod-db.example.com",
  "db_pass": "DJl87sJXX01"
}

dev.json:
{
  "listen_addr":"127.0.0.1",
  "listen_port": 8080,
  "db_addr": "localhost",
  "db_pass": "password"
}

This is MUCH better. You no longer have to hard-code config options into the source and your ops staff doesn't have to worry about inadvertently borking production code if they need to change production settings.

At about this time, I started working with "redundant arrays of indepensive web apps." A typical deployment for me would be to have six copies of an app server running simultaneously. And through the magic of virtualization, we would sometimes add an extra two or three servers to meet high-demand periods.

After trying to ensure that exactly the right version of a configuration file made it onto any given server, I realized I wanted was to store my config JSON files on an internal web server. Instead of reading a file on the local file-system for config settings, I just queried the web server. This worked pretty well: I only had to configure one or two files on a single web server to change the behavior of the entire cluster. Yes, I could have used SCP to copy config files, but it was a bit of a pain to program our deploy system to distribute the right file to newly started instances and time it so we pushed the file out before the app started but after the openssh server started. No. It was much better to have the application itself pull it's config data instead of having a central server push the config to new machines.

I was very happy with this solution until we split our app into shards. All of the sudden we needed to have a lot more per-machine config data. Our initial idea was to load up the config server with a bunch of different files, one per machine and make the apps smart enough to pull the right file. This turned out to be annoying due to the large number of config settings that were common to all machines. If you wanted to change a global setting, you had to change the setting in each of the per-machine config files.

The answer was to split our config settings into per-app and per-machine settings. The per machine settings included IP addresses of proxies & sometimes databases. The per app settings included things like tables, usernames and passwords for databases and the like. And after writing a few apps that made two explicit HTTP(S) queries after starting up, it made sense to move that behavior into it's own package.

And that is how the SN-Props was born (though we called it node-props back then.) And this is how I use it today. I put per-machine settings in a local file and per-app or global settings on an internal web server. The per-machine settings file would likely look like this:

{
  "listen": {
    "port": 9001,
    "host": "127.0.0.1"
  },
  "telemetry": "http://west-coast.telemetry.sm5.us/"
}

while the global settings file would look like this:

{
  "appname": "Cookr",
  "tagline": "Crowdfunding innovative recipes since 2014",
  "database": {
    "host": "cookr.db.sm5.us",
    "user": "cookr",
    "password": "DJl87sJXX01",
    "collection": "cookr_main"
  }
}

To start the service, I don't monkey with environment variables, i just create three versions of the various settings files: one for development, another for integration testing and a third for production. When i want to start the app, I list the URLs of the config files on the command line:
/opt/node/bin/node cookr.js --config file:///etc/permachine.json --config http://deploy.int.sm5.us/cookr.json

The SN-Props package is licensed with under a MIT License, so you can use it as well. Here's a code sample of how easy it is to use:

require( 'sn-props' ).read( function( properties ) {
  // Do something with the properties here. The object passed to this
  // function has the contents of all config files merged into it.

} );

Monday, January 13, 2014

Kill. The. Web.

While the world wide web has done a wonderful job of creating inter-operable network applications and distributed data repositories, it has also constrained our thinking about what it means live in a networked society. Despite efforts to make the web "bi-directional" it is still predominantly a one-way publication media.

This needs to change.

"The Web" means everything is reduced to electronic text and graphics that fit in a 960 x 800 array of pixels. This is an acceptable format for reading or even watching videos. Ubiquitous multimedia means we can even listen to music, radio programs or news. Content comes from a server, operated by a single corporate entity, usually a great distance away.

But watch this video excerpt from Adam Curtis "All Watched Over by Machines of Loving Grace:"


Loren Carpenter Experiment at SIGGRAPH '91 from Zachary Murray on Vimeo.

The web, for all its wonders, can't replicate this simple experiment from the early 1990's. The web is about dissolving locality and proximity. To be sure, this is a remarkable achievement. But it's not enough.

We need to think about proximity and closeness.

Not so much because we are social creatures, but because proximity facilitates feedback. The web is not about feedback. EMail, for all it's benefits, does not scale well with increasing numbers of human participants. Intent and meaning dissolve as more people participate in an email thread. Twitter and Facebook have better immediacy, but limitations on content and ownership make them frustrating to use for many tasks. IRC is a collection of text lines; good for many situations, but again, it is frequently difficult to understand why someone is or isn't responding.

Proximity facilitates rich interpersonal communication and rapid feedback.

The web is wonderful, but it was designed to demolish the effects of geographic distribution, not explicitly to support tasks requiring near-immediate feedback. The web doesn't really need to die, but it needs to be supplemented by tools to support meaningful real-time collaboration.