Saturday, December 27, 2014

Install Skype for Linux ( Fedora 21 )


Skype install for linux


For the life of me, why microsoft would not port skype to x86_64. Perhaps it is because they are going to kill it for future use, boo bah bah ( in a maniacal laughter ). So we have only one choice, install 32bit version. I'm currently experimenting with fedora 21.

 

Download skype 

 

http://www.skype.com/en/download-skype/skype-for-computer/
In my case, fedora 32 bit :
http://www.skype.com/go/getskype-linux-beta-fc10

 

Install rpms packages and run skype


In a terminal 

yum install glibc.i686 libstdc++.i686 libXv.i686 qtwebkit.i686 libXScrnSaver.i686 alsa-plugins-pulseaudio.i686 -y
rpm -Uhv skype-4.3.0.37-fedora.i586.rpm
skype

Background

  • Download skype rpm
  • rpm -Uhv skype-4.3.0.37-fedora.i586.rpm
    error: Failed dependencies:
    ...
    libpthread.so.0(GLIBC_2.3.2) is needed by skype-4.3.0.37-fc16.i586
    librt.so.1 is needed by skype-4.3.0.37-fc16.i586
    librt.so.1(GLIBC_2.2) is needed by skype-4.3.0.37-fc16.i586
    libstdc++.so.6 is needed by skype-4.3.0.37-fc16.i586
    libstdc++.so.6(CXXABI_1.3) is needed by skype-4.3.0.37-fc16.i586
    libstdc++.so.6(GLIBCXX_3.4) is needed by skype-4.3.0.37-fc16.i586
    libstdc++.so.6(GLIBCXX_3.4.9) is needed by skype-4.3.0.37-fc16.i586
    qt >= 4.6 is needed by skype-4.3.0.37-fc16.i586
    qtwebkit is needed by skype-4.3.0.37-fc16.i586

    ...

  • find package the required file comes from:  yum provides */[filename] 
  • yum provides */libpthread.so.0
      glibc-2.20-5.fc21.i686 : The GNU libc libraries
      Repo        : fedora
      Matched from:
      Filename    : /lib/i686/nosegneg/libpthread.so.0
      Filename    : /lib/libpthread.so.0



  • Look for packages such as i686 or noarch
  • yum install glibc.i686 -y
    • specify non version will install the latest same as yum install glibc-2.20-5.fc21.i686 -y
  • Repeat for all the files
  • In the end the 5 rpm packages above requires a total of 147 dependent packages on a clean install of fedora.
 

Wednesday, July 30, 2014

Gitlab Server Installation on Centos 6.4 x88_64

Gitlab Installation

This blog is to document the steps install Gitlab on a Centos 6.4 x88_64 Server. It will discuss some of the issues we encountered and provide some puppet code to automated the build. We used this wiki as a reference for the installation https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md.

Overview
Gitlab using several subsystems
  • Postgres database
  • nginx
  • unicorn
  • ruby / rails
  • redis
  • sidekiq
We opted to install postgres 9.3 instead of the default provided in the rpm. Postgres will be running as a local database account gitlab.
Gitlab will run as local user Centos account git.

Setup

Install and Configure Postgres

Reference for this postgres installation : http://tecadmin.net/install-postgresql-on-centos-rhel-and-fedora/

Install postgres yum repo

rpm -Uhv http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm
 
There was an issue with postgres requiring a new version of openss 10 so we installed a 6.5 package instead. Note this openssl is from updates repo which includes the fix for heartbleed vulnerability.

rpm -Uhv http://mirror.centos.org/centos/6/updates/x86_64/Packages/openssl-1.0.1e-16.el6_5.14.x86_64.rpm 
yum -y install postgresql93-server-9.3.4-1PGDG.rhel6.x86_64 postgresql93-9.3.4-1PGDG.rhel6.x86_64 postgresql93-libs-9.3.4-1PGDG.rhel6.x86_64
 
Edit pg_hba.conf
vi /var/lib/pgsql/9.3/data/pg_hba.conf
#local   all        all                                         peer
local   all         postgres                                    trust
local   all         all                                         trust
 
Initial database and start postgres daemon
service postgresql-9.3 initdb 
service postgresql-9.3 start
 
For some reason the gitlab configuration script is missing some instructions so we pre-config the db. Note postgres has no password to log in locally.

sudo -u postgres psql
CREATE DATABASE gitlab_production;
\c gitlab_production
CREATE USER gitlab WITH PASSWORD 'my_git_passwd1';
GRANT ALL PRIVILEGES ON DATABASE gitlab_production to gitlab;
\list
\q
 
Check gitlab database login
psql -U gitlab -W -d gitlab_production 

Install and Configure Gitlab

The download instruction for Centos can be found here : https://about.gitlab.com/downloads/
Select Centos 6.

Download Gitlab
wget https://downloads-packages.s3.amazonaws.com/centos-6.5/gitlab-7.1.1_omnibus-1.el6.x86_64.rpm
yum install openssh-server
yum install postfix
rpm -i gitlab-7.1.1_omnibus-1.el6.x86_64.rpm
 
Configure gitlab


vi /etc/gitlab/gitlab.rb 
 
# Change the external_url to the address your users will type in their browser
git_data_dir "/home/git"

external_url 'http://[your_hostname]'

#custom postgres install
postgresql['enable'] = false

# Fill in the values for database.yml
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'utf8'
gitlab_rails['db_database'] = 'gitlab_production'
gitlab_rails['db_username'] = 'gitlab'
gitlab_rails['db_password'] = 'dsu-8cq-c5r-poz'
gitlab_rails['db_socket'] = '/tmp/.s.PGSQL.5432'
 
 
Since we where using our own postgres install we need to add addition entries by adding
postgresql['enable'] = false
 


Run gitlab reconfiguration
gitlab-ctl reconfigure 
gitlab-rake gitlab:setup  RAILS_ENV=production 
 
Login to gitlab
In a browser, type http://[your_hostname]
username : admin@local.host
passwd   : 5iveL!fe 
 
 

Debugging

Couldn't create database for {"adapter"=>"postgresql", "encoding"=>"UTF-8", "database"=>"gitlab_production", "pool"=>10, "username"=>"gitlab", "password"=>"dsu-8cq-c5r-poz", "host"=>"127.0.0.1", "port"=>5432, "socket"=>"/tmp/.s.PGSQL.5432"}
-- enable_extension("plpgsql")
rake aborted!
PG::Error: FATAL:  Ident authentication failed for user "gitlab" 

 We had to run numerous time to figure out what was going on.

  • vi /etc/gitlab/gitlab.rb
  • gitlab-ctl reconfigure
  • gitlab-rake gitlab:setup  RAILS_ENV=production

 
Instead we run the following before editing the final gitlab.rb
  • vi /var/opt/gitlab/gitlab-rails/etc/database.yml
  • gitlab:setup  RAILS_ENV=production
     
    
    
  

Bonus Puppet code


Git Node definition

/etc/puppet/manifest/git.pp
node /[your_git_server]/
{
    class
    {
        "postgres":
            version => "9.3",
    }

    class
    {
        "gitlab":
            version => "7.0.0",
            require => Class["postgres"],
    } 
 

Postgres module

/etc/puppet/modules/postgres/manifests/init.pp
class postgres ( $version = "9.3" )
{

    case $version {

        "9.3"     : { $package_version = "93" }

        default   : { $package_version = "93" }
    }

    package
    {
        [ "postgresql${package_version}-server", "postgresql${package_version}" , "postgresql${package_version}-libs" ]:
            ensure => latest,
            require => Package["pgdg-redhat93-9.3-1"];
         
        "pgdg-redhat93-9.3-1":
            ensure => latest, 
 
         #Add this to a local repo : http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-redhat93-9.3-1.noarch.rpm 
         #TODO centos 6.4 requires openssl-1.0.1e-16.el6_5.14.x86_64.rpm for centos 6.5 
    }


    service
    {
         "postgresql-${version}":
             ensure  => "running",
             enable  => "true",
             require => [Package["postgresql${package_version}-server"], Exec["init_postgres"]],

    }

    exec
    {
        "init_postgres":
            command => "service postgresql-${version} initdb",
            path    => "/usr/local/bin/:/bin/:/usr/bin/:/usr/sbin/:/sbin",
            onlyif => "ls /var/lib/pgsql/${version}/data",
            require => Package["postgresql${package_version}-server"],

    }

}
 



Gitlab Module

 
/etc/puppet/modules/gitlab/manifests/init.pp
class gitlab( $version = '7.0.0' )
{


    class
    {
        "gitlab::user":
    }

    file
    {
        "/home/git":
            ensure => directory,
            require => Class["gitlab::user"];


        "/etc/gitlab/gitlab.rb":
            ensure => "present",
            owner  => $::git,
            group  => $::git,
            mode    => 0655,
            notify => Service["gitlab-ctl"],
            content => template("gitlab/gitlab.rb.erb"),
            require => Package["gitlab-${version}_omnibus"];

    }

    package
    {
         "git":
             ensure => latest,
             require => Class["gitlab::user"];

         "gitlab-7.0.0_omnibus":
             ensure => latest,
             require => Package["git"];

    }

    service
    {
        "gitlab-ctl":
            ensure  => "running",
            hasrestart => true,
            restart => "/usr/bin/gitlab-ctl reconfigure && chsh  -s /bin/bash ${::git_user}",
            hasstatus => true,
            status => "/usr/bin/gitlab-ctl status",
            start =>  "/usr/bin/gitlab-ctl start",
            stop =>  "/usr/bin/gitlab-ctl stop",
            require => File["/etc/gitlab/gitlab.rb"],
    }
}


class gitlab::user
{
    # base::generic_user is a custom "define" create user. There are many definitions to create users. We made it into a class so we can "require" it
    # git user account information was define on the top level scope e.g. = $::git
 
    base::generic_user 
    {
        "${git_user}":
            user => "$git_user",
            uid => "${git_user_uid}",
            base_home => "/var/opt",
            home_name => "gitlab",
            password => "${git_user_pass}",
            comment => "${git_user_comment}",
            bash_profile_path => "/opt/gitlab:/opt/gitlab/bin:/opt/gitlab/embedded/bin:/usr/sbin:/sbin:/apps/bin:\$PATH",
            bash_rubylib => "/opt/gitlab/embedded/lib"
    }
}
 


/etc/puppet/modules/gitlab/templates/gitlab.rb.erb
# Autconfigured by Puppet. Do not edit


# Change the external_url to the address your users will type in their browser
git_data_dir "/home/git"

external_url 'http://<%=fqdn%>'

#need to install postgres
postgresql['enable'] = false

# Fill in the values for database.yml
gitlab_rails['db_adapter'] = 'postgresql'
gitlab_rails['db_encoding'] = 'utf8'
gitlab_rails['db_database'] = 'gitlab_production'
gitlab_rails['db_username'] = 'gitlab'
gitlab_rails['db_password'] = 'your_git_user_dbpasswd'
gitlab_rails['db_socket'] = '/tmp/.s.PGSQL.5432'
 

Monday, June 16, 2014

Centos 6.4 GUI installation : Could not allocate requested partitions: not enough space for LVM requests.

Issue:

I'm building a new vm image of Centos 6.4 using the GUI. Upon creating the lvm disk configuration, I receive the following error message despite having a 5G disk :



 

Solution:  Use "Create Custom Layout"

 

Overview of tasks:
  • Create /boot partition
  • Create lvm partition
  • Create / partition using lvm

 

Detail steps

  • Click back button to return to disk installation menu, select "Create Custom Layout".
  • Click Next" 



  • Click "Create"
  • Select "Standard Partition" and click "Create"
  • In the Mount Point list, Select "/boot"
  • Click "OK"


  •  Click "Create"
  •  Select "LVM Physical Volume", and click "Create"
  • If you want use the rest of the partition for the entire lvm type the "Size" as show below then click OK.


  • Click "Create"
  • Select "LVM Volume Group" and click "Create"
  • If you want to Change the name of the Volume Group Name. We use VolGroup00
    • Note : Volume Group Name maps this part of the filesystem name
      • /dev/mapper/VolGroup00-root
  • Click "Add"
  • In the "Mount Point" list, select "/"
  • If you want to change the "Logical Volume Name". We use root
    • Note : Logical Volume Name maps this part of the filesystem name
      • /dev/mapper/VolGroup00-root
  • Click "OK"
  • Click "OK"
  •  Finally, Click "Next"

  •  Enjoy

Wednesday, May 28, 2014

Opennebula context support for Centos 5

Issue

I am a big fan of Opennebula because of some of features such as good support for virtual networking and vmware and documentation. One of the biggest attractions is that is it truly open source. Opennebula has way to pass parameters from the Sunstone interface and pre-defined templates to provision a new virtual machine(vm) via context. We tried to provision some vm's with Centos 6 and it worked great using Opennebula-context rpm package install in the base image. Unfortunately the context package did not work for Centos 5.

Diagnosis

We first installed one-context.rpm on a Centos 5 image. Upon provisioning a new guest, We noticed that the context was not being implement. Such as the hostname not being update to what we typed in the Sunstone interface.

We then looked at Opennebula-context in Github. /etc/init.d/vmcontext is the main service which runs all the context.

Upon closer inspection, the cdrom was not being mounted and that /dev/disk/by-label/CONTEXT symlink was missing. /dev/disk/by-label/CONTEXT was symlink to /dev/sr0 on Centos 6 which was named differently on Centos 5.

Centos 6
/dev/sr0
 
Centos 5
/dev/hdb
 
On the Centos 5 guest vm. We manually symlinked to the cdrom:
cd /dev/disk/by-label
ln -sf ../../hdb CONTEXT
 
Test vmcontext service:
service vmcontext start

We received : "mount: no such partition found" which was tracked down to this line in /etc/init.d/vmcontext
mount -t iso9660 -L CONTEXT -o ro /mnt
 
If we run the following first then the line above would work. Weird.
mount /dev/disk/by-label/CONTEXT -o ro /mnt
umount /mnt
mount -t iso9660 -L CONTEXT -o ro /mnt

 

Solution

Perform these steps on the Centos 5 base image before you import into Opennebula
vi /etc/init.d/vmcontext
change
mount -t iso9660 -L CONTEXT -o ro /mnt
to
mount /dev/disk/by-label/CONTEXT -o ro /mnt
 
To make the symlink correct cdrom device we need to update udev

vi /etc/udev/rules.d/50-udev.rules
change
KERNEL=="hd[a-z]", BUS=="ide", SYSFS{removable}=="1", SYSFS{device/media}=="cdrom", SYMLINK+="cdrom cdrom-%k"
to 
KERNEL=="hd[a-z]", BUS=="ide", SYSFS{removable}=="1", SYSFS{device/media}=="cdrom", SYMLINK+="cdrom cdrom-%k disk/by-label/CONTEXT"
 
comment out 
BUS=="ide", KERNEL=="hd*[0-9]", SYSFS{../removable}=="1", GOTO="persistent_end"
to
#BUS=="ide", KERNEL=="hd*[0-9]", SYSFS{../removable}=="1", GOTO="persistent_end"

Friday, May 23, 2014

Restore Classic Firefox toolbars

Again I have to blog about the stupidity of the firefox version 29.0.1 interface designers. I want to refresh the screen but do not want to press F5. Hunting for that tiny refresh icon on the left of the url bar is quite annoying.



 Let's restore the classic theme




  • Restart Firefox
  • Click View > Toolbars > ...Customize
  • Bottom right Click right of Buttons Toggle to Small
  • Drag Refresh Tool button to where you want.
  • Close Customize Tab

Thursday, May 15, 2014

Iastordatasvc.exe High CPU usage

Iastordatasvc.exe High CPU usage

 

System configurations:
Dell Vostro 220

Intel(R) Core(TM)2 Duo CPU E7500@2.93GHz
4.0 GB
Windows 7 32-Bit

I found that my computer system was very slow and sluggish. 

View processes running
  • Ctrl+Shift+Esc to view the Windows Task Manager
  • Click processes tab
  • Click CPU column to sort by highest percentage
I just install a new video card that changed the Intel Rapid Storage technology driver to use Iastordatasvc instead.

After a bit of research I found the correct driver for this configuration. 


Intel_Intel-Rapid-Storage-Te_A00_R295887.exe 
download here:http://www.dell.com/support/drivers/us/en/19/driverdetails?driverid=RR3H4
 
Run the installation and restart computer and the CPU usage was back to normal.  

Tuesday, May 13, 2014

Annoying default design of Firefox tab location


As of late, Firefox version 29 in its infinite wisdom decided the default location for tabs is above the url toolbar. It's in my opinion and many others agree that having the tabs immediate above the main html section is functionally correct, productive and makes sense.


Here is the solution : https://support.mozilla.org/en-US/questions/991043

But instead of giving a clear answer, you need to read the thread figure it out and decide which course of action.

Here's the skinny.

You should also be able to do this with code in userChrome.css by specifying a value for -moz-box-ordinal-group higher than the default 1, so the Tab bar is moved to a lower position than its current position in the DOM.


Manual steps to update firefox configuration

  1. Find the equivalent directory to the following:
    •  Windows
      • C:\Users\[username]\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxxx.default  
    •  Mac
      • ./Library/Application Support/Firefox/Profiles/xxxxxx.default/chrome/userChrome.css
    • Linux
      • /home/[username]/.mozilla/firefox/xxxxxx.default/chrome/userChrome.css
  1. mkdir chrome 
    • C:\Users\[username]\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxxxx.default\chrome  
  2. cd chrome
  3. Add code to file userChrome.css (case-sensitive )
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* only needed once */
 #TabsToolbar{ -moz-box-ordinal-group: 100 !important; }
  1. Restart Firefox

One liner update for linux

  1. cd /home/[username]
     
  2. chromeprofile=`cat .mozilla/firefox/profiles.ini  | awk '/Path/{split($0,a,"=");print a[2]}'`;userchromepath=.mozilla/firefox/$chromeprofile/chrome;mkdir -p $userchromepath;echo '@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* only needed once */'$'\n#TabsToolbar{ -moz-box-ordinal-group: 100 !important; }' > $userchromepath/userChrome.css
  3. Restart Firefox

Tuesday, March 25, 2014

Load Testing Websockets

Objective

Determine the load the system can handle in websocket connections.


Background

The difficulty is that websockets require a "handshake" to transform a http request to a tcp connection. I initial looked at Gatling ( http://gatling-tool.org/) with the websockets addon( https://github.com/gilt/gatling-websocket ). But I did not want learn scala or performing scripting. I wanted something that displayed output like apache bench. My research led me to Thor (https://www.npmjs.org/package/thor)


Installation

Centos 5.8 x86_64
nodes.js
npm (node package module )
thor

Install nodes.js


We have a user thor which we are going to run thor
cd /home/thor
wget http://nodejs.org/dist/v0.10.26/node-v0.10.26-linux-x64.tar.gz
tar -xvf node-v0.10.26-linux-x64.tar.gz

vi hello_nodes.js
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello Node.js\n');
}).listen(8124, "server");
console.log('Server running at http://server:8124/');

./node-v0.10.26-linux-x64/bin/node hello_node.js
Server running at http://server:8124/

In a browser : http://server:8124/


Install npm


My first attempt to install on Centos 5.8 was to find the rpms. npm and nodes.js was suppose to be in epel repo.

wget http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
rpm -Uvh epel-release-5-4.noarch.rpm
yum search --enablerepo=epel-testing --enablerepo=epel npm
No Matches found

yum provides --enablerepo=epel-testing --enablerepo=epel npm */npm
No Matches found

I decided to build from source

https://github.com/npm/npm
export PATH=$PATH:/home/thor/node-v0.10.26-linux-x64/bin
yum install git -y
git clone https://github.com/npm/npm.git
cd npm
make install
cd ..

which npm
/home/thor/node-v0.10.26-linux-x64/bin/npm


Install Thor

https://www.npmjs.org/package/thor
npm install thor

Example
You can setup an apache tomcat websocket server Here.

ws
 ./npm/node_modules/thor/bin/thor --amount 100 ws://websocket:8080/examples/websocket/chat
 ./npm/node_modules/thor/bin/thor --amount 1000 ws://websocket:8080/examples/websocket/chat
 ./npm/node_modules/thor/bin/thor --amount 100 --concurrent 5 ws://websocket:8080/examples/websocket/chat

apache

ws
 ./npm/node_modules/thor/bin/thor --amount 100 ws://websocket:9090/examples/websocket/chat
 ./npm/node_modules/thor/bin/thor --amount 1000 ws://websocket:9090/examples/websocket/chat
 ./npm/node_modules/thor/bin/thor --amount 100 --concurrent 5 ws://websocket:9090/examples/websocket/chat


Output


Thor:                                                  version: 1.0.0

God of Thunder, son of Odin and smasher of WebSockets!

Thou shall:
- Spawn 1 workers.
- Create 2 concurrent/parallel connections.
- Smash 100 connections with the mighty Mjölnir.

The answers you seek shall be yours, once I claim what is mine.

Connecting to ws://websocket:8080/examples/websocket/chat

  Opened 100 connections


Online               439 milliseconds
Time taken           441 milliseconds
Connected            100
Disconnected         0
Failed               0
Total transferred    132.62kB
Total received       71.85kB

Durations (ms):

                     min     mean     stddev  median max
Handshaking          1       5             3       4 20
Latency              0       0             1       0 3

Percentile (ms):

                      50%     66%     75%     80%     90%     95%     98%     98%    100%
Handshaking          4       5       5       6       7       11      17      20      20
Latency              0       0       1       1       1       1       1       2       3


References: http://howtonode.org/how-to-install-nodejs

Monday, March 24, 2014

Installing different version of python on Fedora / Centos

Objective

We need a specific version of python other that the default version install by the OS. For instance Centos 5.8 comes with python version 2.4.3. Under no circumstance we should replace the python version the OS requires. Bad things will happen.

Current Installation


#python
Python 2.4.3 (#1, Jun 18 2012, 08:55:23)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-52)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.path
['', '/usr/lib/python2.4/site-packages/setuptools-0.6c11-py2.4.egg', '/usr/lib/python2.4/site-packages/chardet-1.0.1-py2.4.egg', '/usr/lib/python2.4/site-packages/autobahntestsuite-0.6.1-py2.4.egg', '/usr/lib/python2.4/site-packages/klein-0.2.3-py2.4.egg', '/usr/lib/python2.4/site-packages/Jinja2-2.7.2-py2.4.egg', '/usr/lib64/python24.zip', '/usr/lib64/python2.4', '/usr/lib64/python2.4/plat-linux2', '/usr/lib64/python2.4/lib-tk', '/usr/lib64/python2.4/lib-dynload', '/usr/lib64/python2.4/site-packages', '/usr/lib64/python2.4/site-packages/Numeric', '/usr/lib64/python2.4/site-packages/gtk-2.0', '/usr/lib/python2.4/site-packages']


Installation in a different location


python2.7
http://www.python.org/ftp/python/2.7.2/Python-2.7.2.tgz
tar -xvf Python-2.7.2.tgz
cd Python-2.7.2
./configure
make
make altinstall


Check path

 
#python2.7
>>> import sys
>>> print sys.path
['', '/usr/local/lib/python27.zip', '/usr/local/lib/python2.7', '/usr/local/lib/python2.7/plat-linux2', '/usr/local/lib/python2.7/lib-tk', '/usr/local/lib/python2.7/lib-old', '/usr/local/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/site-packages']
>>>





Friday, March 21, 2014

Websockets support for Apache httpd 2.2.15 and Tomcat 7.0.27

Objective


We have poor performance using http via apache mod_jk to talk to tomcat. Upon researching different options such as comet, ajp, long polling, websockets appeared to be the most efficient method to communicate with tomcat. The issue we encountered in our production environment is that the software release is set to specific version and we need to have it support websockets.


Websocket Basics


Websocket connection starts out as a ws or wss protocol request from a client such as browser:
    Request URL:ws://server:8080/examples/websocket/chat

Server Responses and makes websocket connection:
    Status Code: 101 Switching Protocols

Client Header:
    connection: upgrade
    Date: Fri, 21 Mar 2014 15:06:58 GMT
    Sec-WebSocket-Accept: XQBn52BiXRMiO0t5qCdQ+v8V9nM=
    Server: Apache-Coyote/1.1
    Transfer-Encoding: hunked
    upgrade: websocket


Environment

Centos 6.3 x86_64
Apache httpd-2.2.15
Java 1.6.0_31 Download
Tomcat 7.0.27 Download

We will install all the software on hostname "server"



Tomcat 7.0.27

As of version 7.0 tomcat has built in support and example application of websocket.


Install Tomcat


tar -xvf apache-tomcat-7.0.27.tar.gz
cd apache-tomcat-7.0.27/bin
sh startup.sh

I recommend using chrome as the test browser. It has tools to debug the connection. Click Customize and Control Google Chrome > Tools > Developer tools




Testing websockets in tomcat

http://server:8080/examples/websocket/chat.html






On the server, you can see the detail package by using tcpdump

tcpdump -X port 8080 and greater 100

14:27:28.134980 IP client.58673 > server.webcache: Flags [P.], seq 3090567567:3090568050, ack 2992001024, win 16458, length 483
        0x0000:  4500 020b 3c31 4000 7f06 9c66 0a00 06fa  E...<1@....f....
        0x0010:  0a00 065c e531 1f90 b836 518f b256 5000  ...\.1...6Q..VP.
        0x0020:  5018 404a 373e 0000 4745 5420 2f65 7861  P.@J7>..GET./exa
        0x0030:  6d70 6c65 732f 7765 6273 6f63 6b65 742f  mples/websocket/
        0x0040:  6368 6174 2e68 746d 6c20 4854 5450 2f31  chat.html.HTTP/1
        0x0050:  2e31 0d0a 486f 7374 3a20 3130 2e30 2e36  .1..Host:.10.10.6
        0x0060:  2e39 323a 3830 3830 0d0a 436f 6e6e 6563  .192:8080..Connec
        0x0070:  7469 6f6e 3a20 6b65 6570 2d61 6c69 7665  tion:.keep-alive
        0x0080:  0d0a 4361 6368 652d 436f 6e74 726f 6c3a  ..Cache-Control:
        0x0090:  206d 6178 2d61 6765 3d30 0d0a 4163 6365  .max-age=0..Acce
        0x00a0:  7074 3a20 7465 7874 2f68 746d 6c2c 6170  pt:.text/html,ap
        0x00b0:  706c 6963 6174 696f 6e2f 7868 746d 6c2b  plication/xhtml+
        0x00c0:  786d 6c2c 6170 706c 6963 6174 696f 6e2f  xml,application/
        0x00d0:  786d 6c3b 713d 302e 392c 696d 6167 652f  xml;q=0.9,image/
        0x00e0:  7765 6270 2c2a 2f2a 3b71 3d30 2e38 0d0a  webp,*/*;q=0.8..
        0x00f0:  5573 6572 2d41 6765 6e74 3a20 4d6f 7a69  User-Agent:.Mozi
        0x0100:  6c6c 612f 352e 3020 2857 696e 646f 7773  lla/5.0.(Windows
        0x0110:  204e 5420 362e 313b 2057 4f57 3634 2920  .NT.6.1;.WOW64).
        0x0120:  4170 706c 6557 6562 4b69 742f 3533 372e  AppleWebKit/537.
        0x0130:  3336 2028 4b48 544d 4c2c 206c 696b 6520  36.(KHTML,.like.
        0x0140:  4765 636b 6f29 2043 6872 6f6d 652f 3333  Gecko).Chrome/33
        0x0150:  2e30 2e31 3735 302e 3135 3420 5361 6661  .0.1750.154.Safa
        0x0160:  7269 2f35 3337 2e33 360d 0a41 6363 6570  ri/537.36..Accep
        0x0170:  742d 456e 636f 6469 6e67 3a20 677a 6970  t-Encoding:.gzip
        0x0180:  2c64 6566 6c61 7465 2c73 6463 680d 0a41  ,deflate,sdch..A
        0x0190:  6363 6570 742d 4c61 6e67 7561 6765 3a20  ccept-Language:.
        0x01a0:  656e 2d55 532c 656e 3b71 3d30 2e38 0d0a  en-US,en;q=0.8..
        0x01b0:  4966 2d4e 6f6e 652d 4d61 7463 683a 2057  If-None-Match:.W
        0x01c0:  2f22 3338 3535 2d31 3333 3332 3035 3131  /"3855-133320511
        0x01d0:  3230 3030 220d 0a49 662d 4d6f 6469 6669  2000"..If-Modifi
        0x01e0:  6564 2d53 696e 6365 3a20 5361 742c 2033  ed-Since:.Sat,.3
        0x01f0:  3120 4d61 7220 3230 3132 2031 343a 3435  1.Mar.2012.14:45
        0x0200:  3a31 3220 474d 540d 0a0d 0a              :12.GMT....
14:27:28.136326 IP server.webcache > client.58673: Flags [P.], seq 1:124, ack 483, win 15544, length 123
        0x0000:  4500 00a3 28a6 4000 4006 f059 0a00 065c  E...(.@.@..Y...\
        0x0010:  0a00 06fa 1f90 e531 b256 5000 b836 5372  .......1.VP..6Sr
        0x0020:  5018 3cb8 21eb 0000 4854 5450 2f31 2e31  P.<.!...HTTP/1.1
        0x0030:  2033 3034 204e 6f74 204d 6f64 6966 6965  .304.Not.Modifie
        0x0040:  640d 0a53 6572 7665 723a 2041 7061 6368  d..Server:.Apach
        0x0050:  652d 436f 796f 7465 2f31 2e31 0d0a 4554  e-Coyote/1.1..ET
        0x0060:  6167 3a20 572f 2233 3835 352d 3133 3333  ag:.W/"3855-1333
        0x0070:  3230 3531 3132 3030 3022 0d0a 4461 7465  205112000"..Date
        0x0080:  3a20 4672 692c 2032 3120 4d61 7220 3230  :.Fri,.21.Mar.20
        0x0090:  3134 2031 383a 3237 3a32 3820 474d 540d  14.18:27:28.GMT.
14:27:28.179957 IP client.58679 > server.webcache: Flags [P.], seq 3023899341:3023899808, ack 2187644622, win 16458, length 467
        0x0000:  4500 01fb 3c34 4000 7f06 9c73 0a00 06fa  E...<4@....s....
        0x0010:  0a00 065c e537 1f90 b43d 0acd 8264 cece  ...\.7...=...d..
        0x0020:  5018 404a cd0e 0000 4745 5420 2f65 7861  P.@J....GET./exa
        0x0030:  6d70 6c65 732f 7765 6273 6f63 6b65 742f  mples/websocket/
        0x0040:  6368 6174 2048 5454 502f 312e 310d 0a55  chat.HTTP/1.1..U
        0x0050:  7067 7261 6465 3a20 7765 6273 6f63 6b65  pgrade:.websocke
        0x0060:  740d 0a43 6f6e 6e65 6374 696f 6e3a 2055  t..Connection:.U
        0x0070:  7067 7261 6465 0d0a 486f 7374 3a20 3130  pgrade..Host:.10
        0x0080:  2e30 2e36 2e39 323a 3830 3830 0d0a 4f72  .0.6.192:8080..Or
        0x0090:  6967 696e 3a20 6874 7470 3a2f 2f31 302e  igin:.http://10.
        0x00a0:  302e 362e 3932 3a38 3038 300d 0a50 7261  10.6.192:8080..Pra
        0x00b0:  676d 613a 206e 6f2d 6361 6368 650d 0a43  gma:.no-cache..C
        0x00c0:  6163 6865 2d43 6f6e 7472 6f6c 3a20 6e6f  ache-Control:.no
        0x00d0:  2d63 6163 6865 0d0a 5365 632d 5765 6253  -cache..Sec-WebS
        0x00e0:  6f63 6b65 742d 4b65 793a 2066 3862 7a62  ocket-Key:.f8bzb
        0x00f0:  532b 2f70 4437 5776 6d66 314b 6c35 6279  S+/pD7Wvmf1Kl5by
        0x0100:  673d 3d0d 0a53 6563 2d57 6562 536f 636b  g==..Sec-WebSock
        0x0110:  6574 2d56 6572 7369 6f6e 3a20 3133 0d0a  et-Version:.13..
        0x0120:  5365 632d 5765 6253 6f63 6b65 742d 4578  Sec-WebSocket-Ex
        0x0130:  7465 6e73 696f 6e73 3a20 7065 726d 6573  tensions:.permes
        0x0140:  7361 6765 2d64 6566 6c61 7465 3b20 636c  sage-deflate;.cl
        0x0150:  6965 6e74 5f6d 6178 5f77 696e 646f 775f  ient_max_window_
        0x0160:  6269 7473 2c20 782d 7765 626b 6974 2d64  bits,.x-webkit-d
        0x0170:  6566 6c61 7465 2d66 7261 6d65 0d0a 5573  eflate-frame..Us
        0x0180:  6572 2d41 6765 6e74 3a20 4d6f 7a69 6c6c  er-Agent:.Mozill
        0x0190:  612f 352e 3020 2857 696e 646f 7773 204e  a/5.0.(Windows.N
        0x01a0:  5420 362e 313b 2057 4f57 3634 2920 4170  T.6.1;.WOW64).Ap
        0x01b0:  706c 6557 6562 4b69 742f 3533 372e 3336  pleWebKit/537.36
        0x01c0:  2028 4b48 544d 4c2c 206c 696b 6520 4765  .(KHTML,.like.Ge
        0x01d0:  636b 6f29 2043 6872 6f6d 652f 3333 2e30  cko).Chrome/33.0
        0x01e0:  2e31 3735 302e 3135 3420 5361 6661 7269  .1750.154.Safari
        0x01f0:  2f35 3337 2e33 360d 0a0d 0a              /537.36....
14:27:28.180593 IP server.webcache > client.58679: Flags [P.], seq 1:222, ack 467, win 15544, length 221
        0x0000:  4500 0105 b61e 4000 4006 627f 0a00 065c  E.....@.@.b....\
        0x0010:  0a00 06fa 1f90 e537 8264 cece b43d 0ca0  .......7.d...=..
        0x0020:  5018 3cb8 224d 0000 4854 5450 2f31 2e31  P.<."M..HTTP/1.1
        0x0030:  2031 3031 2053 7769 7463 6869 6e67 2050  .101.Switching.P
        0x0040:  726f 746f 636f 6c73 0d0a 5365 7276 6572  rotocols..Server
        0x0050:  3a20 4170 6163 6865 2d43 6f79 6f74 652f  :.Apache-Coyote/
        0x0060:  312e 310d 0a75 7067 7261 6465 3a20 7765  1.1..upgrade:.we
        0x0070:  6273 6f63 6b65 740d 0a63 6f6e 6e65 6374  bsocket..connect
        0x0080:  696f 6e3a 2075 7067 7261 6465 0d0a 5365  ion:.upgrade..Se
        0x0090:  632d 5765 6253 6f63 6b65 742d 4163 6365  c-WebSocket-Acce
        0x00a0:  7074 3a20 317a 4973 3474 7a2f 7073 5149  pt:.1zIs4tz/psQI
        0x00b0:  6f57 7035 774d 686d 3237 4a72 4465 343d  oWp5wMhm27JrDe4=
        0x00c0:  0d0a 5472 616e 7366 6572 2d45 6e63 6f64  ..Transfer-Encod
        0x00d0:  696e 673a 2063 6875 6e6b 6564 0d0a 4461  ing:.chunked..Da
        0x00e0:  7465 3a20 4672 692c 2032 3120 4d61 7220  te:.Fri,.21.Mar.
        0x00f0:  3230 3134 2031 383a 3237 3a32 3820 474d  2014.18:27:28.GM
        0x0100:  540d 0a0d 0a

Event summary

client : get /examples/websocket/chat.hmtl
server : 304
client : get /examples/websocket/chat, upgrade:websocket
server : 101 Switching procotol 

Tomcat logs : localhost_access_log
server_ip - - [21/Mar/2014:15:51:02 -0400] "GET /examples/websocket/chat.html HTTP/1.1" 304 -
server_ip - - [21/Mar/2014:15:51:02 -0400] "GET /examples/websocket/chat HTTP/1.1" 101 -

 

Apache httpd server


Now we established that tomcat websockets works, we will add the additional layer of the http server. Websockets was implemented in Apache version 2.4.5 but we only have version 2.2.15. We will need to build httpd apache proxy_wstunnel from source.


Build backport from source

Reference : https://gist.github.com/vitkin/6661683

svn co http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.15 httpd-2.2.15

wget https://gist.github.com/vitkin/6661683/raw/873dd8b4de4ad1ff69757ffe48fc574374aedc57/apache-2.2-wstunnel.patch
cd httpd-2.2.15
patch -p1 -i ../apache-2.2-wstunnel.patch
svn co http://svn.apache.org/repos/asf/apr/apr/branches/1.5.x/ srclib/apr
svn co http://svn.apache.org/repos/asf/apr/apr-util/branches/1.5.x/ srclib/apr-util
  #autoconf not work
./buildconf
./configure --enable-so --enable-proxy --enable-proxy_wstunnel=shared
make

./modules/proxy/.libs/mod_proxy_wstunnel.so

cp ./modules/proxy/.libs/mod_proxy_wstunnel.so /usr/lib64/httpd/modules/


Edit apache configuration to support websockets

vi /etc/httpd/conf/httpd.conf

LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

Listen 9090
    ServerName server

        ProxyPass        /    ws://localhost:8080/
        ProxyPassReverse /    ws://localhost:8080/
        ProxyPass        /    wss://localhost:8080/
        ProxyPassReverse /    wss://localhost:8080/
        ProxyPass        /  http://localhost:8080/
        ProxyPassReverse /  http://localhost:8080/

Note ws, wss need to go before http

service httpd restart

apachectl -t -D DUMP_MODULES | grep proxy
 proxy_module (shared)
 proxy_balancer_module (shared)
 proxy_ftp_module (shared)
 proxy_http_module (shared)
 proxy_connect_module (shared)
 proxy_wstunnel_module (shared)



Testing websockets through apache httpd server


 http://server:9090/examples/websocket/chat.html







TroubleShooting

When implementing the apache server, apache server would not return the websocket connection

tomcat directly
client : get /examples/websocket/chat.hmtl
client : get /examples/websocket/chat, upgrade:websocket
server : 101 Switching procotol

tomcat proxy via apache
client : get /examples/websocket/chat.hmtl
server : 200
client : get /examples/websocket/chat, upgrade:websocket
server : 101 Switching procotol
server : 502 Proxy.Error


Turns out the order of the  proxypass is important

          ProxyPass        /  http://localhost:8080/
          ProxyPassReverse /  http://localhost:8080/
        ProxyPass        /    ws://localhost:8080/
        ProxyPassReverse /    ws://localhost:8080/
        ProxyPass        /    wss://localhost:8080/
        ProxyPassReverse /    wss://localhost:8080/

When I had ProxyPass http first, the request were redirected to http and not ws. Once switch http to the bottom and restart httpd, all worked fine.



References:
http://blog.cafarelli.fr/post/2013/04/26/Backporting-Apache-support-for-websockets-reverse-proxy-%28aka-getting-GateOne-to-work-behind-Apache%29

http://stackoverflow.com/questions/19522635/how-to-get-apache2-reversproxy-with-websockets-mod-proxy-wstunnel-tomcat7-run?rq=1

https://gist.github.com/vitkin/6661683

http://stackoverflow.com/questions/15443550/how-to-deploy-tomcats-example-websocket-applications