Author: Kris Nova

The SMTP protocol originated in 1982.

According to Wikipedia most large email providers have proprietary protocols for exchanging data, all of them use SMTP while delivering outside the scope of their know protocol.

I have put together a list of truths about email to bring to lite how utterly rude and lazy it is to send another human an email and have an expectation that they take your request sincerely.

 

Emails are idempotent

Ever tpoy in an email beofre?

I certainly have. Most communication standards today allow for updates to messages. Facebook, slack, Instagram, YouTube and many others all have an edit button next to your message.

In fact, there is a company called Twitter that explicitly does NOT allow editing of a message. This is controversial but is ultimately part of what makes Twitter so trustworthy.

There is a reasonable expectation that if a user is using Twitter, that they accept the fact that their messages are idempotent.

Why in the hell do we think it’s a good idea to send idempotent messages to other humans to organize our thoughts? Organizing thoughts is notoriously hard and complicated, and it would be great if we had the ability to edit a thought after having it.

Guess what? Humans change their minds some times. 

Imagine a text editor that didn’t let you use the backspace key.

There is a reason we no longer have typewriters…

Reasons for sending email

I would say 99% of the emails I receive fit into one of the following categories.

  1. Dead end content
  2. Convenience
  3. Request for action
  4. Scheduling

And if you think about it:

2 is really just an extension of 1 and 4 is really just an extension of 3

So to break it down even more granularly, here are really the 2 categories of email a person might receive

  1. Dead end content
  2. Request for action

Every email I have ever received in my life is genuinely in one of these two buckets.

Dead end content

This is content that does not require action on your end. Usually it is sent as a convenience, FYI, or just to help me sender feel better.

Ever get an email that just says thanks?

Ever get an email where the subject contains FYI?

There are so many reference emails that could hit your inbox that it takes large amounts of conscious effort to cipher through the noise. If you send these you should punch yourself in the face.

Imagine buying a book that was packaged like your inbox and instead of having chapters and a table of contents was just a pile of pages without any order. It would be hard to read the book, and would require a lot of effort just to abstract the story from the pages.

Furthermore what if some of the pages had requests for you to do something on them? And if you didn’t comply with the requests you would lose your job. Literally this is my inbox.

If you have something to say that does not require input or action from me it belongs on a web site, and not in my inbox. 

Request for action

This is probably the worst part of email. Humans actually do this, and I can’t understand why anyone thinks this is a rational thing to do.

Humans literally hide requests for action behind text blobs.

Hi Kris,

I was wondering if I could ask you a few questions?

I was wondering if I could talk to you about my company BoringCorp. We are a successful startup from Silicon Valley and are on series F funding. Today is our 3 month anniversary in business. We were wondering if you would be interested in attending our inaugural company ball as a guest of honor? It would be an honor to have. I hope you are well.

Regards,

J

 

There is a large block of text above, but let me break it down what just happened.

  1. The sender sent a message with an expectation that I will respond to their request for attending their company ball.
  2.  The sender did not provide all the information I would need to correctly respond to their request.
  3. The sender has implied that the event is important to them, so I should treat the request also as important.
  4. The sender sent a lot of information, and most of it isn’t relevant to the request.
  5. The sender’s name probably starts with J.

So now not only do I have to invest time into deriving the request for action from the email, but the sender has burdened me with guilt if I do not comply with their request. Thanks.

In the year 2017 we have an entire industry built around best ways to organize thoughts and ideas. We have large agile platforms like Jira, Asana, and Trello that help user’s organize tasks. In fact, in most cases there is a reasonable expectation that you won’t even be able to generate work without minimal criteria.

Imagine a request for action that contained information like when, and where, and how to define success? Imagine if a user couldn’t even request action from you if it wasn’t delivered in a way that was meaningful to the person you are requesting action from? This is a reasonable expectation for other parts of the internet, but email just seems like forgive people for acting like complete asshats and requesting action via text blob.

Imagine a restaurant that didn’t serve you a meal but rather gave you a huge blob of junk with your food buried somewhere in the pile of junk. That would be crazy. That restaurant clearly would not be successful if compared to restaurants that spend time and effort preparing a lovely meal for you.

Because packaging is important. And email encourages users to NOT package well; because the interface for sending an email is just a giant text field just waiting to be filled with complete garbage instead of small discreet text fields that represent minimal criteria for the person requesting action.

Emails come with implications

hi,

are u coming?

J

This is a completely normal email for me to receive, and that is completely unreasonable.

Here is what just happened

  1. J has covered their ass

That’s it. Now if anything goes wrong it’s my fault because “Well I sent her an email about it…”

But I don’t even need to explain all the things wrong with this message. It’s just completely bullshit content. There is nothing concrete here, and J seems to think I can just imply information like

  • What would I be coming to?
  • Where is this place at?
  • When do I need to be at this place?
  • Is this meeting important to you, or important to me? Neither? Both?
  • Do I need to bring anything to the meeting?
  • Is this even a meeting?

Implying is bad, and usually humans get it wrong. Period.

As it turns out, J was asking if I would be coming to the meeting he scheduled via text blob. It is important to him that I come to his text blob meeting.

Meanwhile I am too busy getting shit done to deal with deciphering text blobs all day.

Emails are lazy

So it’s easy to just dump into a text field. Anyone can do it, and it doesn’t require much thought.

Furthermore the act of sending an email is relatively safe, because the other person doesn’t have to respond immediately.

So sending an email is a way for a human to send some message, without having to concern themselves about how it was packaged.

Imagine if communication worked this way. Where you would just walk into a room and say whatever in the hell you wanted, and walked out with the expectation that whoever your message was intended for will receive and respond to your message.

If you send emails, you are lazy. 

If you want me to take action, we first need to have a discussion about how we will work with action requests moving forward. After we come up with a way for us to work together, we can begin to create viable action items.

If this sounds like too much work, consider how much time you spend deciphering bullshit from your inbox each day. I personally would be willing to trade time from me figuring out your bullshit, to you figuring out your own bullshit.

Be awesome.

Figure your bullshit out first, so I don’t have to.

 

Email clients are different.

Ever see an email that looks like this?

 

kris?

>

>

> >

> > >

> > > >

> > > > >

> > > > hi,

> > > > are you coming?

> > > >

> > > > J

Because my inbox is full of them.

It seems that ever piece of software in the world respects the golden rule except email clients.

It’s never okay to mutate data that is not yours

Email clients fucking love to mutate your data. We are gonna add colors, and characters, and tabs and spaces. We are gonna insert wingdings into your email. You name it, we are gonna do it.

So not only do I receive messages with vague text blobs that require effort on my end to understand, but chances are it’s not even the original bullshit text blob you sent anyway.

 

In conclusion

We need to figure out ways for humans to perform creating dead end content and requesting action that doesn’t involve email.

In the mean time, can you please for fucks sake be considerate of your messages to me?

I get upwards of 5 thousand messages a day, and the least you could do is spend a few seconds and make your message to me easily digestible.

And remember, if it’s dead end content then put it on Facebook, or Twitter. If I like it I will give you a 👍. But there is no reason to bundle that in with my other messages that may or may not be needing something from me.

 

 

 

10 Rules for writing an email that doesn’t suck

 

1. Start off the email by apologizing for using email.

Just get it out of the way, and admit you know what you are doing is evil. But please keep it short and sweet

Hi $name, sorry for sending you an email but $content?

 

2. Respect the subject

The subject of an email is an important as naming a function. It should be descriptive enough to explain what the email is about, and still let a reader know what to expect within the content of the email.

Furthermore, you should clearly define if your email is a request for action, or dead end content.

 

 

3. No more than 1 reply. Ever.

The rule is simple, it is only okay for one person to reply to any email once before the email is locked and nobody else can reply. If you feel like you need to send another message, draft a new email with a new meaningful subject.

 

4. Do one thing and do it well.

Yep. I Unix philosophy‘d you. Emails are only allowed to do one thing. If you combine multiple requests for action, or multiple sets of content in your email you are doing it wrong.

5. You get one sentence, use it wisely.

A complete sentence is used to express a complete thought. A single complete thought. Which means your email should never be longer than 1 sentence. If you are good, you can even combine that with your apology for using email.

Hi Kris, and I am so sorry for sending you an email, but I was wondering if you could attend our company ball [URL to more information about ball]?

 

6. End your sentence with proper punctuation.

Always make sure to use proper punctuation at the end of your sentence. In the case your email ends with a period . you should copy/paste the email into a Tweet or Facebook post and not send the email.

In the case your email ends with a question mark ? you should re-read your email to make sure it’s well crafted and check your subject to make sure it’s meaningful. Then you may press send.

7. No forwarding

Thats the rule, never forward email. If you forward email you are doing it wrong. You can copy/paste email content from one email to your personal blog. Then you can reference that blog from the next email you need to send.

8. No more than one recipient

If you send an email to more than one person, or ever hit reply all you should punch yourself in the face. If you expect each person you are sending a message to to respond to your message you need to demonstrate that you are willing to spend that much time on them. They get a personal email, or no deal.

9. Your signature must be smaller than 100 bytes

For your signature you get 3 choices

  1. Full legal name
  2. Preferred name
  3. Notable online handle

Your signature should never be more than 100 bytes.

10. No attachments

Ever. Never is it okay to attach anything to an email. You have two options for including media in your email:

  1. You may reference the media’s public URL
  2. You can opt out of using media.

Site Link
Twitter @kris__nova
LinkedIn  kris-nova
GitHub  kris-nova

My contact information. This will make more sense later.

 

Like all good blog posts. This too started out as a tweet.

 

 

 

The conversation was regarding me changing my Twitter handle, and Justin was bringing up a great point. Which is that my Twitter handle is hard-coded all over the internet. My engineer brain instantly started to draft up solutions to this problem, as I realized this was the perfect use case for pointer pointers!

Pointers in Go

Now if you are new to pointers in Go don’t worry. Pointers are easy.

Just think of pointers as URLs!

Seriously, a URL is just a pointer to a web page. In this case the URL itself (say https://nivenly.com) is the address and whatever the web page returns is it’s value.

See? Pretty easy right. I told you pointers were no big deal.

Pointer Pointers

So in the case of changing my contact information, let’s take a look at how things are today.

Notice how in this model, if I need to revise my contact information I would need to go an update every page on the internet that has my contact information linked to it. If we had a pointer page we could safely hard code all the pages on the internet to one page that I control. Say a page on my blog for instance. Then if we needed to update anything all we need to do is update the pointer page.

 

In this model, we no longer need to make a change to the web page on the internet as it will also be pointing to the pointer page.

An example in Go

 

Below is a concrete example of pointer pointers in Go, using the use case from the tweet. Needing to change your twitter URL without changing the higher level implementation.

 


package main

import (
	"fmt"
)

type ContactInfo struct {

	Twitter string
	LinkedIn string
	GitHub string

}

func main() {
	
	// -----------------------------------------------------
	// First version of my contact information
	kris := &ContactInfo{
		Twitter: "https://twitter.com/kris__nova",
		LinkedIn: "https://linkedin.com/in/kris-nova/",
		GitHub: "https://github.com/kris-nova",
	}


	// -----------------------------------------------------
	// Assign my contact information as a pointer pointer
	myContactInfo := &kris
	fmt.Println(**myContactInfo)
	
	
	// -----------------------------------------------------
	// Second version of my contact information
	kris = &ContactInfo{
		Twitter: "https://twitter.com/knovanetes",
		LinkedIn: "https://linkedin.com/in/kris-nova/",
		GitHub: "https://github.com/kris-nova",
	}
	
	
	
	// -----------------------------------------------------
	// Feel free to hard code myContactInfo anywhere and I 
	// can change it right from underneath you!
	fmt.Println(**myContactInfo)
}

Run it on the Go playground!

 

 

Cheersthanks!

 

 

 

I feel like half of my blog ideas come from Jessie’s twitter page… but after another one of her great tweets I had an idea.

 

 

Which was to make a proper theme for my mountain pictures for tech presentations.

And of course if you know anything about me, it’s that if I do something manually once, I have to automate it for my future self. So I started working on a new presentation, except this time spent the extra hour or so to put together a proper theme.

So feel free to use it! I took all the pictures myself, and even went through the process of giving you happy/sad slides so you can introduce conflict in your presentation.

Download 0.0.1

Name Download
PowerPoint Slides  nova-clouds-theme-0.0.1.pptx
 Background Images (16:9)  nova-clouds-images.tar.gz

Using with Microsoft PowerPoint

  1. Create a new copy of the presentation
  2. Open the presentation
  3. Begin using the default slide layouts

Using with Google Slides

  1. Create a new Google slides presentation
  2. Click the Theme... button on the top bar
  3. Click import theme and import the theme
  4. Begin using the default slide layouts

 

 

So hanging out at GothamGo this year has been inspirational! I have been able to rub elbows with the best of the best Go engineers in the world.

Last night I was introduced to what I think is..

..finally the solution to generics in Go!

The G Package

The Generics Package

So there is an Apache 2 open source licensed package that can be found on GitHub here. ‘

The package is clean, and elegant. So let’s take the package for a spin!

First things first, we need to install the G package. Luckily it using the Go idiomatic installation method go get.


go get github.com/StabbyCutyou/generics

Now we can import the package into our Go program.


import . "github.com/StabbyCutyou/generics"

The Implementation

We can now take ugly and non idiomatic (but flexible) Go code such as the following and implement a much more elegant solution for Generics.


func UglyUnIdiomaticQuoteGenericApproachUnquote(poorexcuse ...interface{}) []interface{}

with the G package now becomes the following


func Excellence(things ...G) []G

Backwards Compatibility

From the G package repository we can read a glorious compatibility statement:

G meets the standard of golang by matching its stance on backwards compatibility. Until a 2.0 release of generics, which may never happen, G will always be 100% Backwards compatible with it’s initial 1.0 release.

Behind The Scenes

The source code for G is simple and elegant, and I encourage all users to take a peak at what is going on behind the scenes. In my eyes it is a clean solution to Generics in Go, and I couldn’t be more pleased with the project.

I hope this helps.

Cheers.

So I am working on a Go speech today, and I got to a slide where I wanted to mention the C# programming language. Or more importantly, I wanted to mention how some internal teams at Microsoft are switching over from C# to Go!

The only problem with this slide is that I am supposed to be somewhat credible in what I say..

and I have never written a line of C# in my life.

Furthermore I run linux as my primary operating system. So of course I decided it would be a good idea to try to get a C# development environment up and and running on Archlinux. After a total of 10 seconds of searching Google I couldn’t find the step-by-step tutorial I wanted so naturally I am creating one.

So here goes…

 

Install VS Code

C# isn’t scary at all!

Download page for Linux

Tarball for Linux

Okay so you don’t need VS code, but the C# plugin is really legit. It feels like any other programming language!

But feel free to use any text editor you like. We are just going to be banging out a quick and dirty hello world.

If you plan on writing copious amounts of C# I strongly suggest you get VS code. It’s free and works fantastically on Linux.

Install Mono

(Seriously this is all you do)


sudo pacman -S mono

Write your hello world program

Create a new file called HelloWorld.cs anywhere on your file system.

HelloWorld.cs

// A Hello World! program in C#.
using System;
namespace HelloWorld
{
    class Hello 
    {
        static void Main() 
        {
            Console.WriteLine("Hello World!");

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

Thanks to the official Microsoft docs for the code snippet!

Compile

The mono mcs compiler works very similar to gcc and accepts an -out flag to specify the name of the executable.


mcs -out:helloexe HelloWorld.cs

Run

Then you can run your program!


mono hello.exe

What’s next?

I am going to do some benchmarking with C# and Go and explore some concurrency patterns between the two. Stay tuned for my findings!

Hey everyone!

So a huge thanks to Hashiconf for letting me come out and talk about this stuff in person! But for those of you who missed it, or want more information there is also this blog on the matter as well.

So this is just a quick technical follow up of the tool terraformctl that I used in my session to get Terraform up and running inside of Kubernetes as a controller!

What is terraformctl?

A command line tool and gRPC server that is pronounced Terraform Cuddle.

 

The GitHub repo can be found here!

 

It’s a philosophical example of how infrastructure engineers might start looking at running cloud native applications to manage infrastructure. The idea behind the tool is to introduce this new way of thinking, and not necessarily to be the concrete implementation you are working for. This idea is new, and therefore a lot of tooling is till being crafted. This is just a quick and dirty example of what it might look like.

Terraformctl follows a simple client/server pattern.

We use gRPC to define the protocol in which the client will communicate with the server.

The server is a program written in Golang that will handle incoming gRPC requests concurrently while running a control loop.

The incoming requests are cached to a mutex controlled shared point in memory.

The control loop reads from the shared memory.

Voila. Concurrent microservices in Go!

What is cloud native infrastructure?

Well it’s this crazy idea that we should start looking at managing cloud native infrastructure in the same way we manage traditional cloud native applications.

If we treat infrastructure as software then we have no reason to run the software in legacy or traditional ways when we can truly concur our software by running it in a cloud native way. I love this idea so much that I helped author a book on the subject! Feel free to check it out here!

The bottom line is that the new way of looking at the stack is to start thinking of the layers that were traditionally managed in other ways as layers that are now managed by discreet and happy applications. These applications can be ran in containers, and orchestrated in the same ways that all other applications can. So why not do that? YOLO.

What Terraformctl is not..

Terraformctl is not (and will never be) production ready.

It’s a demo tool, and it’s hacky. If you really want to expand on my work feel free to ping me, or just out right fork it. I don’t have time to maintain yet another open source project unfortunately.

Terraformctl is not designed to replace any enterprise solutions, it’s just a thought experiment. Solving these problems is extremely hard, so I just want more people to understand what is really going into these tools.

Furthermore there are a number of features not yet implemented in the code base, that the code base was structure for. Who knows, maybe one day I will get around to coding them. We will see.

If you really, really, really want to talk more about this project. Please email me at kris@nivenly.com.

 

 

So as I continue to find workarounds and fixes for running Archlinux on my Microsoft Surface Book I will post them..

Here is a great quick and dirty fix for the wifi issue.

Problem

After closing your Surface Pro, or sending your computer into a state of hibernation or suspension the WiFi agent quits working.

Solution

Found a handy dandy script that totally fixes the problem.


sudo wget -P /usr/lib/systemd/system-sleep nivenly.com/surface-hib.sh

 

 

So I joined a new team at Microsoft and we run Microsoft Teams for our primary form of communication.

So here is a quick walk through of getting it up and running on Archlinux.

Archlinux

Download the pacman package from Github

cd ~

wget https://github.com/ivelkov/teams-for-linux/releases/download/v0.0.4/teams-for-linux-0.0.4.pacman

Install with Pacman


sudo pacman -U teams-for-linux-0.0.4.pacman

Alias teams to run in the background


echo "alias teams='teams &>/dev/null &'" >> ~/.bashrc

source ~/.bashrc

 

Then you can run teams from the command line to launch the program. Happy Microsofting. J

 

Follow @kris-nova

What are we creating?

  • Kubernetes v1.7.3
  • Private Networking in Digital Ocean
  • Encrypted VPN mesh for droplets
  • Ubuntu Droplets

So at Gophercon I released my latest project kubicorn.

As I go along I want to publish a set of use cases as examples. This helps me exercise kubicorn and understand my assumptions. It would be really cool if others could step in and use these cases to improve the system.

7 Node Cluster in Digital Ocean

Creating your cluster

So the deployment process is pretty straight forward. The first thing you need to do is grab a copy of `kubicorn v0.0.003`.


$ go get github.com/kris-nova/kubicorn

Verify kubicorn is working, and you are running the right version.

$ kubicorn --fab

Also you will need a Digital Ocean access key. You can use this guide to help you create one. Then just export the key as an environmental variable.

 
$ export DIGITALOCEAN_ACCESS_TOKEN=***************************************** 

The project offers a starting point for a digital ocean cluster called a profile. Go ahead and create one on your local filesystem.

$ kubicorn create dofuckyeah --profile do

Feel free to take a look at the newly created representation of the cluster and tweak it to your liking. Here is what mine looks like

For my cluster all I did was change the maxCount from 3 to 7 for my node serverPool.

When you are happy with your config, go ahead and apply the changes!

$ kubicorn apply dofuckyeah -v 4

Then check out your new cluster and wait for your nodes to come to life!

$ kubectl get no
kubectl get nodes

What we created

We created 8 droplets, all running Ubuntu 16.04

The master droplet uses a fantastic tool called meshbird to create an encrypted private VPN service mesh on Digital Ocean private networking.

Each of the droplets get a new virtual NIC called tun0 that allows each of the droplets to route on a private VPN.

The nodes register against the master via the newly created virtual NIC.

The master API is advertised on the public IP of the master droplet.

You can checkout the bootstrap script for the master here, and for the nodes here.

And thanks to kubeadm

Poof. Kubernetes.

Want to learn more?

Check out the kubicorn project on GitHub!

Follow @kubicornk8s on Twitter to get up to the second updates!

Join us in #kubicorn in the official Gopher’s slack!

 

Follow @kris-nova

Follow @kris-nova

Just keep reading.. I promise this is worth it..

Okay so I made a new Kubernetes infrastructure tool (sorry not sorry). Introducing my latest pile of rubbish… kubicorn!

Check it out on github here.

Why I made the tool

I made the tool for a lot of reasons. The main one is so that I could have some architectural freedom. Here are some other reasons:

  • I want to start using (or abusing) kubeadm
  • I believe in standardizing a Kubernetes cluster API for the community
  • I believe in pulling configuration out of the engine, so users can define their own
  • I believe in creating the tool as a consumable library, so others can start to use it to build infrastructure operators
  • I wanted to enforce the concept of reconciliation, and pull it all the way up to the top of the library
  • I want to support multiple clouds (really)
  • I want it to be EASY to build a cloud implementation
  • I want it to be EASY to understand the code base
  • I want it to be EASY contribute to the project
  • I want it to be as idiomatic Go as possible

I am sure there are more, but you get the idea.

What it does

It empowers the user (that’s you) to manage infrastructure.

It lets the user (still you) define things like what the infrastructure should look like, and how the cluster should bootstrap.

It offers really great starting points (called profiles) that are designed to work out of the box. Tweak away!

It (eventually) will take snapshots of clusters to create an image. The image is both the infrastructure layer as well as the application layer bundled up into a lovely tarball. The tarball can be moved around, replicated, saved, and backed up. The tarball is a record of your entire cluster state (including infrastructure!).

What is next?

Please help me.

I need contributors and volunteers for the project. I want to share as much knowledge as possible with the user (you!) so that everyone can begin contributing.

What clouds do we support?

Today? AWS

Tomorrow? Digital Ocean (literally tomorrow.. checkout out the PR)

Next? You tell me. The whole point here is that the implementation is easy, so anyone can do it.

 

Kubicorn vs Kops

 

Feature Kops Kubicorn
HA Clusters
Easy to use library
Kubeadm
Bring your own bootstrap
Awesome as shit
API in Go
Digital Ocean Support
Kubernetes Official
Multiple Operating Systems (Ubuntu, CentOS, etc)
Requires DNS

 

Setting up Kubernetes 1.7.0 in AWS with Kubicorn

This is not ready for production! I started coding this a few weeks ago in my free time, and it’s very new!

Also check out the official walkthrough here!

Install kubicorn

go get github.com/kris-nova/kubicorn

Create a cluster API

kubicorn create knova --profile aws

Authenticate

You should probably create a new IAM user for this, with the following permission

  • AmazonEC2FullAccess
  • AutoScalingFullAccess
  • AmazonVPCFullAccess

Then export your auth information

export AWS_ACCESS_KEY_ID="omgsecret"
export AWS_SECRET_ACCESS_KEY="evenmoresecret"

Apply

Then you can apply your changes!

kubicorn apply knova

 

Example Output

 

Access

Then you can access your cluster

kubectl get nodes

Delete

Delete your cluster

kubicorn delete knova

Follow @kris-nova