Controlling ssh access with GitHub organizations

Screen Shot 2016-04-27 at 17.54.47

Ok, I’m coming clean. Controlling access to our various servers has been a mess. Sure, we’ve stored passwords in a safe way (1Password for teams ftw!) but what happens if someone leaves the company or that root password somehow were to get out… Well, we did not have a plan for such a thing.

Sure, setting up ssh keys is easy, but we never got around to it. We manage more than a handful servers, and making sure the authorized_keys on these boxes is up to date just felt unmanageable.

This changed today when i got the idea to make use of this GitHub’s feature which exposes the public keys. I wrote a little script that fetches all users within our GitHub organization, pulls down the public keys and updates the ~.ssh/authorized_keys-file nightly with a cron job.

Yes, this is PHP but when all you’ve got is a hammer – everything looks like a nail. This needs some error handling too, but I thought I’d share it anyway.



An analog computer game on a modular synthesizer

Here’s a “Whac-A-Mole” type game made on a modular synthesizer, acting as an analog computer.

We got excited at the office over some images of old analog computers. This is a pretty fresh look for a machine:

This is the Donner 3500 portable analog computer.

The Donner 3500, a portable analog computer from the 1950s.

We are so used to the digital computer concept that it’s easy to think of an analog computer as the same thing but with older technology like op-amps, knobs and switches and lacking memory and storage. But an analog computer works with the value of a continuous input, instead of a quantized representation of the value as in the digital realm.

Analog computers are speedy with computing real time data, for example doing simulations or calculations of natural data. Not with the best precision though, due to analog noise. Digital values of 1s and 0s of course eliminates this noise. Hybrid computers, with analog speed and digital precision, were produced far into the seventies and some were still used in the 00s. TV graphics in the 70s and 80s were often made on analog computers, a popular system was the Scanimate.

So these cute analog computers with jacks and knobs ought to be far gone, right? Well the other day i realized we actually had one in our office, at least a close relative – the modular synthesizer.


Eurorack and Serge synthesizer modules.

Normally a sound creating machine, but why not simulate commuter train delays or calculate taxes with this thing? Or hey, let’s make a game.

It’s a game of reaction. You’re supposed to touch the plates as quick as you can when they light up. The quicker you are the more points you’re given. The score can be read on a volt meter during the game. The synths also got to make some game sounds.

The video at the top shows Pärs best round, scored over 100. Jakob tied that later though.

The setup is like this: An accelerating trigger pulse loop lights up new random key. The selected row output sends out a set voltage. When you hit a key with your finger another jack outputs a different voltage. These voltages were inverted, attenuated and summed to zero volt when you hit the correct key. A comparator triggers on zero volt = score. Along with the original trigger pulse we also got a sloped output and when Pär scores we “sample” the curve with a sample and hold module, which gives you more points the quicker you are. The sampled value get mixed together with itself, i.e. the previous sampled value, so the score accumulates over time.

The game sadly got no highscore list.

My family uses Slack. It’s pretty interesting.

Everything changed for the better when we started using slack at work. We’ve made countless custom integrations; doorbells, intercoms, travel cards, reddit, lunch menues, git hooks, server monitoring, you name it – we haz it.

My family has been using Google Calendar for a few years. Me and my wife used to think that we we’re busy every night and that there was no room for improvisation. Google Calendar showed us that we had lots of free evenings and weekends, which has been great.

When it was time to evaluate a group chat app, I saw no reason to use HipChat, Skype or anything like that. Slack to the rescue!

Slack’s free tier gives us 10 integrations, search for the latest 10 000 messages and 5GB storage. This is plenty for a family of 4. In this blog post I’ll go through how we use it and the integrations we have made to aid us.

Screen Shot 2016-02-01 at 15.15.44

We use channels just the same way we use them at work. “fixahuset” is a channel for stuff that needs to be fixed around the house, “general” is important stuff, “handla” is for picking up milk on the way home, “mathem” is an integration i’ll get to in a bit, and “random” is the usual cat gif mayhem we’ve all learned to love/hate. “pedertest” is where i test new integrations.

Integration no 1: Where are the kids?

We, as most parents to 10yo kids, ask this question daily. Picking them up at school, but they’re at a friend’s house, etc. Gah. This is a custom Slackbot command, which calls out to my server and returns the result.

My server runs a little curl script that calls out to Find My iPhone and returns a static GoogleMap image. The kids will probably start to question this thingie eventually, but works for now.


Integration no 2: Google Calendar

Our old Google Calendar integrates very smoothly, just hook it up and let Slack know when you want the notifications.

Screen Shot 2016-02-01 at 15.27.16

Integration no 3: School information

It turns out our school is living in the future, providing a RSS-feed per child. I had no idea. RSS works very well with this setup.

Screen Shot 2016-02-01 at 15.32.12

Integration no 4: Online food shopping

In Sweden, MatHem is one of the biggest e-commerce sites for groceries. We use them for a weekly delivery, and it works great. The night before delivery we generally take 10 minutes and cram everything we can come up with into our cart, which means that we miss a lot of essentials. What if we could add uhm… juice to our cart throughout the week, the moment when someone realise that we’re out of uhm… juice (“sök” means search, “köp” means buy).


This integration is not kosher at all, and I’m probably breaking some terms and conditions. But we need this, and it could be done, so hey. If you work at MatHem or is offended by this in any way – please let me know and I’ll cease and desist.

That’s all the stuff we’ve got now, but more to come. Applying tactics from work to family life may seem cold, but I see this as a way to make the most out of our time. It’s not like we’re writing Jira stories or planning our vacation in Trello. Yet.


Lots of people wrote and talked about this, like, ForbesNyTeknik (Swedish) and Apparat (Russian). And on Twitter (1) (2) (3) (4), Hackernews and CBC Spark also made an interview, which was great fun.

Making a silly game using Google Cloud Vision and Instagram

I was recently invited to the first alpha release of Google Cloud Vision, which is a game changing new API from Google. I can programmatically upload any picture and get this kind of stuff back:

  • Face detection, with pixel annotations of the corner of the mouth etc, plus unexpected values like sorrowLikelihood
  • Landmark detection, with LatLon polygon boundaries to real world landmarks
  • Logo detection
  • Text detection
  • Safe search detection, which can detect medical, nude and violent content

I wanted to dig right in, and decided to build a really silly little game. I call it Game Of Cats, and has nothing to do with Game of Thrones at all.

A user logs in using their Instagram credentials. My game engine starts polling all recent pictures from the people the user follows, and awards a point for every cat picture that occurs. The game goes on forever, without any interaction.

Screenshot 2015-12-08 22.35.28

I won’t bore you with details about how Instagram handles OAUTH, but you might be interested in how Google Cloud Vision wants to talk to an app like this? I built this quick and dirty as it should be, in PHP.

I would love to have the energy to build a WordPress plugin that adds a taxonomy to the media library, and automatically tags all uploaded images using Google Cloud Vision, but I don’t. Someone else will, and they write better code than I do anyway.


Note: I can’t post the URL to the actual game, yet. The alpha’s terms and conditions prohibits me from deploying to production.


Hooking up the voice intercom to Slack

The intercom from the street to our office was connected to an old GSM phone, and letting people in required us to pick up the phone and press the digit 5. Simple, sure, but it doesn’t feel like 2015. I had also been meaning to try the Twilio API for some time.

Task: Connect the Intercom to Slack.

The Twilio API is great, so it was actually really easy to accomplish. I bought a local number and asked our landlord to forward the Intercom to it. Then I set up this simple TwiML script on a web server:

  <Say>Welcome to Earth People. Please stand by.</Say>
  <Enqueue waitUrl=""> </Enqueue>

What happens here is that Twilio will pick up the call and greet the intercom user using Twilio’s text to speech service. It will then put the “call” into a new phone queue. Twilio will generate a phone queue id and pass it via POST to the waitUrl, below:

header("content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
file_put_contents('input_porttelefon.txt', $_POST['QueueSid']);
# curl post to slack
$data = array(
  "channel" => "#general",
  "username" => "Intercom",
  "text" => "Meep Meep! Open the door with 'Intercom'",
  "icon_emoji" => ":door:"
$url_send = "";
$str_data = json_encode($data);
$ch = curl_init($url_send);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $str_data);

The waitUrl will save the phone queue id to a text file, make an incoming webhook to Slack and of course play a funky tune to the intercom user. Now Twilio will play the funky tune until it ends, or an incoming HTTP-request is made to the Twilio REST API, using the queue id.

Slack is set up to make an outgoing webhook to a URL. This URL just pops the only call in the queue to the front of the queue.

# when incoming hook: read call sid from file and call twilio.
$QueueSid = file_get_contents('input_porttelefon.txt');
  $sid = "xxx";
  $token = "xxx";
  $client = new Services_Twilio($sid, $token);
  $member = $client->account->queues->get($QueueSid)->members->get("Front");
    "Url" => "",
    "Method" => "GET"
  file_put_contents('input_porttelefon.txt', '');
  echo '{"text": "Ok, opened."}';
  echo '{"text": "No one is at the door."}';

The last step is to have Twilio play the sound of the digit 5, which opens the door, using the same kind of XML as step 1. Easy!

Next up is to let intercom users, which we don’t let in for some reason, leave a voice message which is posted to Slack. Totally doable, but not we’re quite there yet.


Figurerunning a corgi

I like running, and figurerunning makes it even more fun. Don’t know what figurerunning is? Oh! Basically it’s just GPS tracking helping runners draw dicks on maps while running. What’s not to like?

We made a tool helping runners being creative while planning their routes. In this proof of concept we let users draw figures which automatically snap to roads and bike paths. For every waypoint we store latitude and longitude together with directions. This way we can play audio cues to the user while running.

Below is a GIF showing the proof of concept.


Turns out it’s really hard to draw good routes! I tried to draw a corgi for our NYC-based Emelie to run, but there weren’t any corgi shaped neighbourhoods in Brooklyn. It just barely looks like a dog (a corgi doesn’t look like a dog either so well…).


How to make a wind chime door bell

Our doorbell was already connected to the Internet via an Arduino, but we couldn’t stand the sound it made. We needed a warmer sound, a sound that didn’t make us want to kill the doorbell users (mostly clients).

Step 1:
Buy an old Wind Chime, preferably with a coconut base (because awesome).
2015-01-22 14.34.26

Step 2:
Pick up a few Littlebit modules (Cloudbit, servo motor and power supply).
2015-01-22 15.41.33

Step 3:
Drill, glue and duct tape a bambu stick to the servo motor. Hide all the crap in a classy box.

Step 4:
Make the old Slack door bell script also make a little curl post to the Cloudbit.

$data = array(
	"percent" => "100",
	"duration_ms" => "10000"
$url_send = "";
$str_data = http_build_query($data);
$ch = curl_init($url_send);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer XXX','Accept: application/vnd.littlebits.v2+json'));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $str_data);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 
echo curl_exec($ch);

Step 5:
Ring the door bell. Voila!

Integrera Swish i egna tjänster

I’ll write this in Swedish because it only applies to Swedes.

Swish är ju en väldigt lyckad tjänst. Den har, liksom t.ex. Uber, förändrat ett beteende. Över 2 millioner svenskar använder appen. Självklart borde man göra något smart på Internet med detta, nu när nästan hela Sverige har appen i fickan. Dock har Swish inget publikt API, vilket förmodligen är anledningen till att det inte hänt så mycket ännu.

Det man vill uppnå är att låta en egen tjänst/kampanj/server veta när en viss användare skickat pengar till ett visst Swishanslutet nummer. Och genom att använda lite tveksamma metoder gick det vägen.

Koden är alldeles för risig för att dela med sig av, men ett första proof of concept funkar. Här t.ex. skickar min vän Bruno 1 krona:


…och här tar jag emot den på vår utvecklingsserver:


Känns såklart lite olustigt att haxa fulkod mot sina egna banktjänster, men det kändes viktigt att komma i mål. Får se vad det blir för projekt av detta, men kul att det går iaf. Puss.



Let Slack nag you that it’s time to return that commuter pass

Another week, and yet another Slack integration here at Earth People.

This time we’ve added an integration to the public transport system here in Stockholm.

At Earth People we like to use public transportation when going to meetings with clients. That’s why we have bought a couple of commuter passes that we can use whenever we need to go to a meeting.

It works great. But there is one problem however: we only have a few cards, so when you return from the meeting you must remember to return the card so others can use it. And that’s were our latest integration comes into play:

Screenshot showing a message posted to a slack channel, with the date and time of a journey Yup, shortly after the card has been used, a message from the card will appear in our slack channel. That works pretty good as a reminder.

And as a plus feature it also shows how much cash that is left on the card, so we will also know when it’s time to refill the card.

There you have it: another super useful integration for Slack.

Oh! And thanks to mysl for their API-wrapper for “Mitt SL”, that led us into the right direction when researching the API.

Let Slack tell you what songs are currently playing in the office

At Earth People, there’s always music in the air (and the birds sing a pretty song).
Most of the stuff we play is fairly unknown to most of us, and in many cases only played once, ever.

To get rid of all the “Hey what’s this song”-chatter or Slack, I made a litte script which we run as a Slack Command.
The script just checks all the of the people usually playing music, and returns what’s on.

Screenshot 2014-10-15 16.51.02

By no means magic, but adds another bit of homey feeling to Slack.
Here’s the Gist, be our guest.



require 'vendor/autoload.php';

use GuzzleHttp\Pool;
use GuzzleHttp\Client;

$client = new Client();

$users = array('suprape','musikmarskinen','dafeather','brunobrandstrom','Algoritm','mjelle','hjalle','johannagrip','tumde');

$requests = array();
foreach($users as $user){
	$requests[] = $client->createRequest('GET', '', [
		'query' => array(
			'method' => 'user.getrecenttracks',
			'limit' => '5',
			'api_key' => 'GetThisFromLastFm',
			'format' => 'json',
			'nowplaying' => 'true',
			'user' => $user

$results = Pool::batch($client, $requests);
$nowplaying = array();
foreach ($results->getSuccessful() as $response) {
	$recenttracks = json_decode($response->getBody()->getContents());
		foreach($recenttracks->recenttracks->track as $track){
				$temp = new StdClass();
				$temp->artist = $track->artist->{"#text"};
				$temp->title = $track->name;
				$temp->album = $track->album->{"#text"};
				$temp->image = $track->image[3]->{"#text"};
				$nowplaying[] = $temp;

header('Content-type: text/plain;charset=utf-8');
echo "Verkar som att ".count($nowplaying)." låtar spelas på kontoret just nu:\n";
foreach($nowplaying as $track){
	echo '- "'.$track->artist.' - '. $track->title.'"';
		echo ' från skivan "'.$track->album.'"';
	echo "\n";