February 27, 2015

Configure WildFly, Apache and websocket connections on Ubuntu 14.04

This tutorial assumes that you have already installed WildFly and you want to configure Apache as a proxy in front of WildFly, and you want to allow websocket connections. For a detailed guide on installing and configuring WildFly, see this post.

In this guide are going to install and configure Apache, mod_proxy and proxy_wstunnel. proxy_wstunnel is required if you want successfully connect to WildFly via websockets (thru Apache). Any attempt to connect via websockets without proxy_wstunnel will fail as the HTTP Upgrade headers will be removed from your request.

Apache install

First install Apache and the required mods:
sudo apt-get install apache2
sudo apt-get install libapache2-mod-proxy-html
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo /etc/init.d/apache2 restart

Apache configuration

Now configure your VirtualHost. For simplicity we are going to update the 000-default.conf file. In this example the context root of the application is app. Update yours as needed.
vim /etc/apache2/sites-available/000-default.conf

These two lines are required to proxy your main http connections
ProxyPass         /app  http://localhost:8080/pss
ProxyPassReverse  /app  http://localhost:8080/pss

These two lines will proxy your websocket connections
ProxyPass         /app/ws/  ws://localhost:8080/app/ws/
ProxyPassReverse  /app/ws/  ws://localhost:8080/app/ws/

Here is the full VirtualHost file, with the mod_proxy and proxy_wstunnel configuration highlighted:
<VirtualHost *:80>
    ServerName www.example.com
    ServerAlias example.com

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/example.com

    ProxyPass         /app  http://localhost:8080/pss
    ProxyPassReverse  /app  http://localhost:8080/pss
    ProxyPass         /app/ws/  ws://localhost:8080/app/ws/
    ProxyPassReverse  /app/ws/  ws://localhost:8080/app/ws/

    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>
Reload Apache for the changes to take effect
sudo /etc/init.d/apache2 reload

Java configuration

Make sure that the value you pass into your @ServerEndPoint annotation matches that in your Apache VirtualHost configuration.
@ServerEndpoint("/ws")
public class WebSocketEndpoint {
 
    private final Logger logger = Logger.getLogger(this.getClass().getName());
 
    @OnOpen
    public void onConnectionOpen(Session session) {
        logger.info("Connection opened");
    }
 
    @OnMessage
    public String onMessage(String message) {
        return "Message received";
    }
 
    @OnClose
    public void onConnectionClose(Session session) {
        logger.info("Connection closed");
    }
}

WildFly configuration

Make sure that you allow connections to your public interface from localhost (127.0.0.1) only. While this is not mandatory, leaving it open will allow connections to circumvent Apache.
<interfaces>
    <interface name="management">
        <inet-address value="0.0.0.0"/>
    </interface>
    <interface name="public">
        <inet-address value="${jboss.bind.address:127.0.0.1}"/>
    </interface>
    <interface name="unsecure">
        <inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
    </interface>
</interfaces>

In WildFly websockets work out of the box, so no other configuration required. Here is the default undertow configuration, with the relevant parts highlighted.
<subsystem xmlns="urn:jboss:domain:undertow:1.2">
    <buffer-cache name="default"/>
    <server name="default-server">
        <http-listener name="default" socket-binding="http"/>
        <host name="default-host" alias="localhost">
            <location name="/" handler="welcome-content"/>
            <filter-ref name="server-header"/>
            <filter-ref name="x-powered-by-header"/>
        </host>
    </server>
    <servlet-container name="default">
        <jsp-config/>
        <websockets/>
    </servlet-container>
</subsystem>
You should now be able to deploy your websocket applications to WildFly and access them via Apache.

February 17, 2015

Installing WildFly on Ubuntu 14.04 cloud server

This post covers the main aspects of installing WildFly on a fresh cloud Ubuntu server (or any clean install). This tutorial shows how WildFly can be configured to be accessed directly. If you want to put WildFly behind Apache using mod_proxy, see this post.

Topics covered: 


Adding swap to a new cloud instance 
  • Checking for swap
  • Creating swap
  • Changing swappiness 
Updating the server using apt-get 

Installing Java
  • Downloading the JDK to the server
  • Installing the JDK
  • Setting the default JDK
Installing WildFly
  • Downloading WildFly
  • Creating the wildfly user
  • Installing the init.d scripts
  • Starting WildFly as a service
Configuring WildFly
  • Open public interface to all IP's
  • Open the management interface to all IP's (optional)
  • Remove the welcome content (optional)

Adding swap to a new cloud instance  

Swap is an area on your hard drive that can store data when your RAM is full. First we need to check to see if a swap area is configured:
sudo swapon -s
If you get the headers back only, you have no swap space:

Now lets create a 4 gig swap:
sudo fallocate -l 4G /swapfile
Verify that is has been created and is the correct size
ls -lh /swapfile 
You should see something like this:

Now change the folder permissions:
sudo chmod 600 /swapfile
Set up swap
sudo mkswap /swapfile
You will should see the output below.


Now enable swap
sudo swapon /swapfile
Lets check to see if we have swap space
sudo swapon -s
We should get the following output:

To make the changes permanent you need to update the fstab file
sudo echo '/swapfile   none    swap    sw    0   0' >> /etc/fstab

Update swappiness

Swappiness can be configured between 0 and 100. The nearer to 0 the more data will be put into the RAM rather than the swap.

To view the current swappiness:
cat /proc/sys/vm/swappiness
To change the swapiness to 10:
sudo echo 'vm.swappiness=10' >> /etc/sysctl.conf
This only takes effect on reboot, so also run this command to effect this change immediately
sudo sysctl vm.swappiness=10

Updating the server using apt-get 

If you have not already updated your new server, do so now:
sudo apt-get update
sudo apt-get upgrade

Installing Java

Personally I like to install the Oracle JDK rather than OpenJDK. As you need to accept the Oracle licence before downloading, you will need to browse to the Java download page using your browser. Agree to the terms, and then click on download. As soon as it starts, pause it, and copy the download link.
Go to your server and use wget to download the file using the download link you just copied:
wget -c http://download.oracle.com/otn-pub/java/jdk/8u31-b13/jdk-8u31-linux-x64.tar.gz?AuthParam=1423681612_d8066e1256e66a7a4895ad467fc7cd07
When is has finished downloading, extract it to the /opt/java folder (or any other folder of your choosing)
mkdir /opt/java
tar -xvzf jdk-8u31-linux-x64.tar.gz -C /opt/java
Now add the following to the end of /etc/environment:
JAVA_HOME="/opt/java/jdk1.8.0_31"
PATH="$JAVA_HOME/bin:$PATH"
Now source the file to load the new $PATH and $JAVA_HOME properties
. /etc/environment

Installing WildFly

First install WildFly by downloading and extracting it to the /opt directory
cd /opt
wget -c http://download.jboss.org/wildfly/8.2.0.Final/wildfly-8.2.0.Final.tar.gz
tar -xzvf wildfly-8.2.0.Final.tar.gz

Create the wildfly user and group

addgroup wildfly
useradd -g wildfly wildfly
Change the ownership of the wildfly folder recursively:
chown -R wildfly:wildfly /opt/wildfly-8.2.0.Final/ 
Create a symbolic link so that if you change WildFly versions, you don't have to update any other configuration:
ln -s wildfly-8.2.0.Final /opt/wildfly

Installing the init.d scripts

To easiest way to start and stop WildFly is to use a startup script. Copy and paste the init.d script within the WildFly install to the /etc/init.d/ folder, change the permissions, and make it executable:
cp /opt/wildfly/bin/init.d/wildfly-init-debian.sh /etc/init.d/wildfly
sudo chown root:root /etc/init.d/wildfly
sudo chmod ug+x /etc/init.d/wildfly
To start/stop WildFly you will simply run the commands
sudo /etc/init.d/wildfly start
sudo /etc/init.d/wildfly stop

Starting WildFly as a service

To enable WildFly to start automatically when the server starts, you need to add it to the linux run-levels:
sudo update-rc.d wildfly defaults 
You should see the following output:

Configuring WildFly - open the public interface to all IP's

To access WildFly from an IP other than 127.0.0.1 (localhost) you will need to update the bind address for the public interface. Update this:
<interface name="public">
    <inet-address value="${jboss.bind.address:127.0.0.1}"/>
</interface>
to this:
<interface name="public">
    <any-address/>
</interface>
You will now be able to access WildFly from any IP using port 8080


Open the management interface to all IP's (optional) 

If you want to access the management console (on port 9990), you will need to update the bind address as you did for the public interface:
<interface name="management">
    <any-address/>
</interface>
You will now be able to access the management interface on port 9990 from any computer.

Remove the welcome content (optional)

If you are deploying your application to the context root, you will need to remove the default welcome content from the WildFly configuration. Remove the lines highlighted in bold from the undertow subsystem in your standalone.xml file
<server name="default-server">
    <http-listener name="default" socket-binding="http"/>
    <host name="default-host" alias="localhost">
        <location name="/" handler="welcome-content"/>
        <filter-ref name="server-header"/>
        <filter-ref name="x-powered-by-header"/>
    </host>
</server>
<handlers>
    <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
</handlers>

You will now be able to deploy your application to WildFly and view it on your_ip:8080. Make sure you configure your jboss-web.xml and set the context root to /.
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
    <context-root>/</context-root>
</jboss-web>
Enjoy :)