11 min read

(For more resources related to this topic, see here.)

Setting up an Ubuntu box

We are going to set up an Ubuntu virtual machine using the Vagrant tool. This virtual machine will simulate a real production server. If you already have an Ubuntu box (or a similar Linux box) handy, you can skip this step and move on to setting up a user.

Vagrant (http://www.vagrantup.com/) is a tool for managing virtual machines. Many people use it to manage their development environments so that they can easily share them and test their software on different operating systems. For us, it is a perfect tool to practice Vert.x deployment into a Linux environment.

Install Vagrant by heading to the Downloads area at http://vagrantup.com and selecting the latest version. Select a package for your operating system and run the installer. Once it is done you should have a vagrant command available on the command line as follows:

vagrant –v

Navigate to the root directory of our project and run the following command:

vagrant init precise64 http://files.vagrantup.com/precise64.box

This will generate a file called Vagrant file in the project folder. It contains configuration for the virtual machine we’re about to create. We initialized a precise64 box, which is shorthand for the 64-bit version of Ubuntu 12.04 Precise Pangolin. Open the file in an editor and find the following line:

# config.vm.network :private_network, ip: "192.168.33.10"

Uncomment the line by removing the # character. This will enable private networking for the box. We will be able to conveniently access it with the IP address 192.168.33.10 locally.

Run the following command to download, install, and launch the virtual machine:

vagrant up

This command launches the virtual machine configured in the Vagrantfile. On first launch it will also download it. Because of this, running the command may take a while.

Once the command is finished you can check the status of the virtual machine by running vagrant status, suspend it by running vagrant suspend, bring it back up by running vagrant up, and remove it by running vagrant destroy.

Setting up a user

For any application deployment, it’s a good idea have an application-specific user configured. The sole purpose of the user is to run the application. This gives you a nice way to control permissions and make sure the application can only do what it’s supposed to.

Open a shell connection to our Linux box. If you followed the steps to set up a Vagrant box, you can do this by running the following command in the project root directory:

vagrant ssh

Add a new user called mindmaps using the following command:

sudo useradd -d /home/mindmaps -m mindmaps

Also specify a password for the new user using the following command (and make a note of the password you choose; you’ll need it):

sudo passwd mindmaps

Install Java on the server

Install Java for the Linux box, as described in Getting Started with Vert.x. As a quick reminder, Java can be installed on Ubuntu with the following command:

sudo apt-get install openjdk-7-jdk

On fresh Ubuntu installations, it is a good idea to always make sure the package manager index is up-to-date before installing any packages. This is also the case for our Ubuntu virtual machine. Run the following command if the Java installation fails:

sudo apt-get update

Installing MongoDB on the server

We also need MongoDB to be installed on the server, for persisting the mind maps.

Setting up privileged ports

Our application is configured to serve requests on port 8080. When we deploy to the Internet, we don’t want users to have to know anything about ports, which means we should deploy our app to the default HTTP port 80 instead.

On Unix systems (such as Linux) port 80 can only be bound to by the root user. Because it is not a good idea to run applications as the root user, we should set up a special privilege for the mindmaps user to bind to port 80. We can do this with the authbind utility.

authbind is a Linux utility that can be used to bind processes to privileged ports without requiring root access.

Install authbind using the package manager with the following command:

sudo apt-get install authbind

Set up a privilege for the mindmaps user to bind to port 80, by creating a file into the authbind configuration directory with the following command:

cd /etc/authbind/byport/
sudo touch 80
sudo chown mindmaps:mindmaps 80
sudo chmod 700 80

When authbind is run, it checks from this directory, whether there is a file corresponding to the used port and whether the current user has access to it. Here we have created such a file.

Many people prefer to have a web server such as Nginx or Apache as a frontend and not expose backend services to the Internet directly. This can also be done with Vert.x. In that case, you could just deploy Vert.x to port 8080 and skip the authbind configuration. Then, you would need to configure reverse proxying for the Vert.x application in your web server. Note that we are using the event bus bridge in our application, and that uses HTTP WebSockets as the transport mechanism. This means the front-end web server must be able to also proxy WebSocket traffic. Nginx is able to do this starting from version 1.3 and Apache from version 2.4.5.

Installing Vert.x on the server

Switch to the mindmaps user in the shell on the virtual machine using the following command:

sudo su – mindmaps

Install Vert.x for this user, as described in Getting Started with Vert.x. As a quick reminder, it can be done by downloading and unpacking the latest distribution from http://vertx.io.

Making the application port configurable

Let’s move back to our application code for a moment. During development we have been running the application in port 8080, but on the server we will want to run it in port 80. To support both of these scenarios we can make the port configurable through an environment variable.

Vert.x makes environment variables available to verticles through the container API. In JavaScript, the variables can be found in the container.env object. Let’s use it to give our application a port at runtime. Find the following line from the deployment verticle app.js:

port: 8080,

Change it to the following line:

port: parseInt(container.env.get('MINDMAPS_PORT')) || 8080,

This gets the MINDMAPS_PORT environment variable, and parses it from a string to an integer using the standard JavaScript parseInt function. If no port has been given, the default value 8080 is used.

We also need to change the host configuration of the web server. So far, we have been binding to localhost, but now we also want the application to be accessible from outside the server. Find the following line in app.js:

host: "localhost",

Change it to the following line:

host: "0.0.0.0",

Using the host 0.0.0.0 will make the server bind to all IPv4 network interfaces the server has.

Setting up the application on the server

We are going to need some way of transferring the application code itself to the server, as well as delivering incremental updates as new versions of the application are developed. One of the simplest ways to accomplish this is to just transfer the application files over using the rsync tool, which is what we will do.

rsync is a widely used Unix tool for transferring files between machines. It has some useful features over plain file copying, such as only copying the deltas of what has changed, and two-way synchronization of files.

Create a directory for the application, on the home directory of the mindmaps user using the following command:

mkdir ~/app

Go back to the application root directory and transfer the files from it to the new remote directory:

rsync -rtzv . [email protected]:~/app

Testing the setup

At this point, the project working tree should already be in the application directory on the remote server, because we have transferred it over using rsync. You should also be able to run it on the virtual machine, provided that you have the JDK, Vert.x, and MongoDB installed, and that you have authbind installed and configured. You can run the app with the following commands:

cd ~/app
JAVA_OPTS="-Djava.net.preferIPv4Stack=true" MINDMAPS_PORT=80 authbind ~/
vert.x-2.0.1-final/bin/vertx run app.js

Let’s go through the file bit by bit as follows:

  • We pass a Java system parameter called java.net.preferIPv4Stack to Java via the JAVA_OPTS environment variable. This will have Java use IPv4 networking only. We need it because the authbind utility only supports IPv4.
  • We also explicitly set the application to use port 80 using the MINDMAPS_PORT environment variable.
  • We wrap the Vert.x command with the authbind command.
  • Finally, there’s the call to Vert.x. Substitute the path to the Vert.x executable with the path you installed Vert.x to.

After starting the application, you should be able to see it by navigating to //192.168.33.10 in a browser.

Setting up an upstart service

We have our application fully operational, but it isn’t very convenient or reliable to have to start it manually. What we’ll do next is to set up an Ubuntu upstart job that will make sure the application is always running and survives things like server restarts.

Upstart is an Ubuntu utility that handles task supervision and automated starting and stopping of tasks when the machine starts up, shuts down, or when some other events occur. It is similar to the /sbin/init daemon, but is arguably easier to configure, which is the reason we’ll be using it.

The first thing we need to do is set up an upstart configuration file. Open an editor with root access (using sudo) for a new file /etc/init/mindmaps.conf, and set its contents as follows:

start on runlevel [2345]
stop on runlevel [016]

setuid mindmaps
setgid mindmaps

env JAVA_OPTS="-Djava.net.preferIPv4Stack=true"
env MINDMAPS_PORT=80

chdir /home/mindmaps/app
exec authbind /home/mindmaps/vert.x-2.0.1-final/bin/vertx run app.js

Let’s go through the file bit by bit as follows:

  • On the first two lines, we configure when this service will start and stop. This is defined using runlevels, which are numeric identifiers of different states of the operating system (http://en.wikipedia.org/wiki/Runlevel). 2, 3, 4, and 5 designate runlevels where the system is operational; 0, 1, and 6 designate runlevels where the system is stopping or restarting.
  • We set the user and group the service will run as to the mindmaps user and its group.
  • We set the two environment variables we also used earlier when testing the service: JAVA_OPTS for letting Java know it should only use the IPv4 stack, and MINDMAPS_PORT to let our application know that it should use port 80.
  • We change the working directory of the service to where our application resides, using the chdir directive.
  • Finally, we define the command that starts the service. It is the vertx command wrapped in the authbind command. Be sure to change the directory for the vertx binary to match the directory you installed Vert.x to.

Let’s give the mindmaps user the permission to manage this job so that we won’t have to always run it as root. Open up the /etc/sudoers file into an editor with the following command:

sudo /usr/sbin/visudo

At the end of the file, add the following line:

mindmaps ALL = (root) NOPASSWD: /sbin/start mindmaps, /sbin/stop
mindmaps, /sbin/restart mindmaps, /sbin/status mindmaps

The visudo command is used to configure the privileges of different users to use the sudo command. With the line we added, we enabled the mindmaps user to run a few specific commands without having to supply a password.

At this point you should be able to start and stop the application as the mindmaps user:

sudo start mindmaps

You also have the following additional commands available for managing the service:

sudo status mindmaps
sudo restart mindmaps
sudo stop mindmaps

If there is a problem with the commands, there might be some configuration error. The upstart service will log errors to the file: /var/log/upstart/mindmaps.log. You will need to open it using the sudo command.

Deploying new versions

Deploying a new version of the application consists of the following two steps:

  1. Transferring new files over using rsync
  2. Restarting the mind maps service

We can make this even easier by creating a shell script that executes both steps. Create a file called deploy.sh in the root directory of the project and set its contents as:

#!/bin/sh
rsync -rtzv . [email protected]:~/app/
ssh [email protected] sudo restart mindmaps

Make the script executable, using the following command:

chmod +x deploy.sh

After this, just run the following command whenever you want a new version on the server:

./deploy.sh

To make deployment even more streamlined, you can set up SSH public key authentication so that you won’t need to supply the password of the mindmaps user as you deploy. See https://help.ubuntu.com/community/SSH/OpenSSH/Keys for more information.

Summary

In this article, we have learned the following things:

  • How to set up a Linux server for Vert.x production deployment
  • How to set up deployment for a Vert.x application using rsync
  • How to start and supervise a Vert.x process using upstart

Resources for Article :


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here