





















































(For more resources related to this topic, see here.)
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.
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 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
We also need MongoDB to be installed on the server, for persisting the mind maps.
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.
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.
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.
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
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:
After starting the application, you should be able to see it by navigating to //192.168.33.10 in a browser.
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 mindmapsenv JAVA_OPTS="-Djava.net.preferIPv4Stack=true"
env MINDMAPS_PORT=80chdir /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:
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 a new version of the application consists of the following two steps:
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.
In this article, we have learned the following things:
Further resources on this subject: