Naming Nodes

Learn how to use and implement naming nodes in Elixir.

There’s nothing mysterious about a node. It is simply a running Erlang VM. Throughout this course, we’ve been running our code on a node.

The Erlang VM, called Beam, is more than a simple interpreter. It’s like its own little operating system running on top of our host operating system. It handles its own events, process scheduling, memory, naming services, and interprocess communication. In addition to all that, a node can connect to other nodes in the same computer, across a LAN, or across the Internet, and provide many of the same services across these connections that it provides to the processes it hosts locally.

Implementation

So far, we didn’t name our node because we’ve had only one. If we ask Elixir what the current node is called, it’ll give us a made-up name:

iex> Node.self 
:nonode@nohost

We can set the name of a node when we start it. With IEx, we use the --name or --sname option. The former sets a fully qualified name. To run the command below, we exit from the iex session using “Ctrl+C” twice.

$ iex --name wibble@educative.local 
iex(wibble@educative.local)> Node.self 
:"wibble@educative.local"

The --sname option sets a short name:

$ iex --sname wobble 
iex(wobble@educative)> Node.self 
:"wobble@educative"

The name that’s returned is an atom. It’s in quotes because it contains characters not allowed in a literal atom.

Note: In both cases, the IEx prompt contains the node’s name along with the machine’s name (educative).

Now, let’s create an anonymous function that outputs the current node name.

iex(node_one@educative)> func = fn -> IO.inspect Node.self end
#Function<erl_eval.20.82930912>

We can run this with the spawn function.

iex(node_one@educative)> spawn(func)
#PID<0.59.0>
node_one@educative

But spawn also lets us specify a node name. The process will be spawned on that node.

iex(node_one@educative)> Node.spawn(:"node_one@educative", func)
#PID<0.57.0>
node_one@educative

We’re running on node one. When we tell spawn to run on node_one@educative, we see two lines of output. The first is the PID spawn returns, and the second is the value of Node.self that the function writes.

Nodes, cookies, and security

Although this is cool, it might also ring some alarm bells. If we can run arbitrary code on any node, then anyone with a publicly accessible node has just handed over their machine to any random hacker. But that’s not the case.

Before a node lets another connect, it checks that the remote node has permission. It does that by comparing that node’s cookie with its own cookie. A cookie is just an arbitrary string, ideally fairly long and very random. As an administrator of a distributed Elixir system, we need to create a cookie and then make sure all nodes use it.

If we’re running the iex or elixir commands, we can pass in the cookie using the --cookie option.

$ iex --sname one --cookie chocolate-chip 
iex(one@educative)> Node.get_cookie 
:"chocolate-chip"
$ iex --sname node_one --cookie cookie-one
iex(node_one@educative)> Node.connect :"node_two@educative"
false

The node that attempts to connect receives false, indicating the connection wasn’t made.

Run the above commands in the terminal below:

Get hands-on with 1400+ tech skills courses.