Bare metal Erlang “Hello World” !

Recently I have been messing around with LING VM which is an Erlang VM that runs directly on Xen ! Yes you read it right, LING allows you to run Erlang code in bare metal environment. In this post I will take you through the process of building and deploying your first bare metal Erlang hello world code on Xen.


There are just a few things that you need to install before you can get to creating your hello world vm. First and foremost you need to have Xen installed, you can find an guide here if you need help. Also make sure that you have a copy of LING on your machine, you can download it from here. If you download and extract the tar file from the link you will see a file named railing which is a utility that lets you build Erlang on Xen images. You can put railing in your path variable so that it is easier to access.

Now that we have our environment all setup let's try to build a hello world image which we can run on Xen. You won't have to write any code because we will use hello world server example from cowboy source code,

$ git clone https://github.com/ninenines/cowboy
$ cd cowboy/examples/hello_world
$ make deps app

After executing the above you will have your hello world example compiled. NOTE: don't execute just make as it will make a release too and we don't want that (because that will ERTS). Next we will build a hello image using railing which will bundle our hello world app into LING and create an image which can be run directly on Xen. So in the hello_world folder execute the following,

$ railing image
... console log ...
$ ls
deps domain_config ebin hello_world.img Makefile README.md _rel relx relx.config src
$ railing -l crypto
... console log ...
$ cat domain_config
name = "hello_world"
kernel = "hello_world.img"
extra = "-home /hello_world -pz /hello_world/deps/cowboy/ebin /hello_world/deps/cowlib/ebin /hello_world/deps/ranch/ebin /hello_world/ebin"
vif = []
  • We execute railing image in the hello_world folder which produces two files hello_world.img which is image file that will run on xen and domain_config which is a config that defines various parameters for the image file.
  • Cowboy needs crypto library to run but it is not included by default. So we compile crypto into hello_world.img using railing -l crypto image
  • Lastly you can see the contents of domain_config are just a bunch of variables. Let's discuss them one by one.
  • name : when we run a vm on xen it's called a domain that is the reason we have domain_config and the name defines the name of domain to be created.
  • kernel: defines the name/path of the image to be run i.e. “hello_world.img”
  • extra : these are arguments which are passed to the kernel when it's booted up.
  • vif : this allows the user define interfaces to which the vm will connect to. We will discuss more about it below.

Now that we have generated the hello_world.img and domain_config, let's try to run it,

$ xl create domain_config -c
Parsing config from domain_config
Erlang [ling-0.5.0]
Eshell V6.3 (abort with ^G)
1>
# exit from the shell by pressing   CTRL ]
$ xl list
Name ID Mem VCPUs State Time(s)
Domain-0 0 3596 4 r----- 10119.9
hello_world 44 32 1 -b---- 0.1

xl is a command line utility that comes with xen to manage domains. You can see that we have our hello_world domain started ! But at this moment the vm is not connected to the outer world and our cowboy app is also not running, let's try to get that done. First we kill the hello_world domain,

$ xl destroy 44

notice that we have used the ID to destroy the VM. Now we will modify our domain_config to add some parameters,

name = "hello_world"
kernel = "hello_world.img"
extra = "-dhcp -home /hello_world -pz /hello_world/deps/cowboy/ebin /hello_world/deps/cowlib/ebin /hello_world/deps/ranch/ebin /hello_world/ebin"
vif = ['bridge=xenbr0']

Here he have defined vif i.e. virtual interface to connect to host xenbr0 interface which should be a bridge interface on the host. If you don’t know how to setup bridge interface you can refer here or google it yourself. Once your bridge interface is setup you can specify it in you domain_config. My bridge interface is named xenbr0 so I specify the same here but your could be different depending on whatever you named it. Another thing to notice here is that I specified “-dhcp” , this will cause LING to obtain an ip from the router after it boots up. You can specify static ip by replacing -dhcp with the following,

-ipaddr 192.168.1.8 -netmask 255.255.0.0 -gateway 192.168.1.1

Now lets try to boot the vm again and start our hello world app,

$ xl create domain_config -c
Parsing config from domain_config
eth0: MAC 00:16:3e:51:30:7a
Erlang [ling-0.5.0]
Eshell V6.3 (abort with ^G)
1> l(inet).
{module,inet}
2> inet:getifaddrs().
{ok,[{"lo",
[{flags,[up,loopback,running]},
{addr,{127,0,0,1}},
{netmask,{255,0,0,0}}]},
{"eth0",
[{flags,[up,broadcast,running,multicast]},
{hwaddr,[0,22,62,81,48,122]},
{addr,{192,168,2,39}},
{netmask,{255,255,255,0}}]}]}
3> application:start(crypto).
ok
4> application:start(ranch).
ok
5> application:start(cowlib).
ok
6> application:start(cowboy).
ok
7> application:start(hello_world).
ok

You can see that our vm has an ip allocated by dhcp/router. Then we start all the prerequisite application and finally we start hello_world app. At this point you should head over to your web browser and type the following in your address bar,

192.168.2.39:8080

Click enter and you should see “Hello World!” , volla ! there is our first bare metal hello word application. Now that you have the power of bare metal, you can go ahead and rule the world !