Installing Glassfish 3.1.1 on Ubuntu 10.04 LTS

This tutorial is outdated. The latest version is available here: Installing Glassfish 4.1 on Ubuntu 14.04 LTS.

This tutorial will explain how to install a Glassfish 3.1.1 Server on an Ubuntu 10.04 LTS Server (you can also use it for installing Glassfish 3.1.2.2). It will also cover some but not all security concerns. The steps have been executed successfully on Ubuntu 10.04 LTS Server edition (64-bit). I have tested everything by using Parallels Virtual Machines - you might want to use Virtual Machines as well. You can use this tutorial for setting up a Glassfish server which is reachable via internet for everybody. Both Ubuntu root servers and Ubuntu virtual servers should be fine for this tutorial, so you can choose any hosting package offered by the provider of your choice. In all cases you need to make sure to have root access to your server. You should also be familiar with the Unix/Linux command line because you will have to execute lots of commands on the shell. After having this tutorial completed you can use your new Glassfish installation to host your own Java EE 6 compliant applications.

In my previous tutorial I described how to install Glassfish 3.0.1/3.1 on Ubuntu 8.04/10.04. I have received plenty of feedback directly posted on the page and even much more feedback from people who directly contacted me. It seems that my tutorials are quite helpful for many of my readers. Unfortunately I did not receive any donations yet - hopefully this will change soon as this is the third version of the tutorial.

I would like to take this chance to thank everybody who left comments and hints on my previous tutorials. Some of the hints have been incorporated into this tutorial. Keep posting your information and ideas here to improve this tutorial for others! Share your knowledge here!


Table of contents:


Creating this tutorial meant a lot of effort - although I could reuse a lot of the work I invested into my previous tutorial. I hope it will help others. If you have any questions do not hesitate to contact me. Any feedback is welcome! Also feel free to leave a comment (see below). For helping me to maintain my tutorials any donation is welcome. But now enough words - enjoy the tutorial.


1. Setting up the OS environment

Before you start doing anything you should think about a security concept. A detailed security concept is out of scope for this tutorial. Very important from security point of view is not to run your Glassfish server as root. This means you need to create a user with restricted rights which you can use for running Glassfish. Once you have added a new user, let's say 'glassfish', you might also want to add a new group called 'glassfishadm'. You can use this group for all users that shall be allowed to "administer" your Glassfish in full depth. In full depth means also modifying different files in the Glassfish home directory. Below you find user and group related commands that you might want to use.

#Add a new user called glassfish
sudo adduser --home /home/glassfish --system --shell /bin/bash glassfish

#add a new group for glassfish administration
sudo groupadd glassfishadm

#add your users that shall be Glassfish adminstrators
sudo usermod -a -G glassfishadm $myAdminUser

#in case you want to delete a group some time later (ignore warnings):
#delgroup glassfishadm

Glassfish allows some of the configuration tasks to be managed via a web based Administration GUI. We will simply call it AdminGUI from now on. You can reach the AdminGUI by visiting http://www.yourserver.com:4848/ in your browser (please replace www.yourserver.com with localhost or where ever your Glassfish server is). As you can see port 4848 is used. Of course, we don't want anyone to access our AdminGUI. Therefore we have to restrict access to the AdimnGUI. A way do this is to block port 4848 via the firewall. Anything you can do via AdminGUI is also available via the asadmin tool that ships with Glassfish. So you don't have to worry about not being able to configure Glassfish if you block the AdminGUI.

Usually you want to run Glassfish on port 80. But since we don't suggest to run Glassfish as root we cannot run Glassfish on port 80. But there are still ways to run Glassfish as a non-root user and still receive http requests on port 80. One option could be mod_jk, but this would only be another component that needs to be managed. An easy way is to use a simple iptables redirection rule, that redirects requests on port 80 to port 8080 (http) and requests on port 443 to port 8181 (https).

You should make sure that you do not block other important ports, for example your ssh port which usually runs on port 22 (else you will be locked out). Changing the ssh port to some other is actually a good idea, but for now we will simply suggest your ssh port is 22. Another helpfull iptables rule related to your ssh port 22 is to slow down connection tries from an ip if they fail 3 times. I found a rule for that on the web and added it below. Although I will not mention it here you should also use other techniques and tools to secure your ssh port. Unfortunately, I did not get the time to post a tutorial about that.

Now we have created a lot of rules. You could enter them always one by one, but we don't want this kind of effort. I suggest to enter the following iptables rules in a separate file which contains all of our iptables related ideas we discussed so far:

#!/bin/bash

# ATTENTION: flush/delete all existing rules
iptables -F

################################################################
# set the default policy for each of the pre-defined chains
################################################################
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

# allow establishment of connections initialised by my outgoing packets
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

# accept anything on localhost
iptables -A INPUT -i lo -j ACCEPT

################################################################
#individual ports tcp
################################################################
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
iptables -A INPUT -p tcp --dport 8181 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
#uncomment next line to enable AdminGUI on port 4848:
#iptables -A INPUT -p tcp --dport 4848 -j ACCEPT

################################################################
#slow down the amount of ssh connections by the same ip address:
#wait 60 seconds if 3 times failed to connect
################################################################
iptables -I INPUT -p tcp -i eth0 --dport 22 -m state --state NEW -m recent --name sshprobe --set -j ACCEPT
iptables -I INPUT -p tcp -i eth0 --dport 22 -m state --state NEW -m recent --name sshprobe --update --seconds 60 --hitcount 3 --rttl -j DROP

#drop everything else
iptables -A INPUT -j DROP

################################################################
#Redirection Rules
################################################################
#1. redirection rules (allowing forwarding from localhost)
iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A OUTPUT -o lo -p tcp --dport 443 -j REDIRECT --to-port 8181

#2. redirection http
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080

#3. redirection https
iptables -t nat -A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 8181


################################################################
#save the rules somewhere and make sure
#our rules get loaded if the ubuntu server is restarted
################################################################
iptables-save > /etc/my-iptables.rules
iptables-restore < /etc/my-iptables.rules

#List Rules to see what we have now
iptables -L

I suggest to create a file called iptables.DISABLE_4848.rules which contains exactly everything from the code box above. Then you could also create a file called iptables.ENABLE_4848.rules which has line 28 uncommented (everything else is just the same). Of course, you have to make both files executable with the command chmod +x $filename (please replace $filename). Then you can simply run one of the scripts when ever you want to disable or enable the AdminGUI on port 4848, i.e. sudo ./iptables.DISABLE_4848.rules

Please also do not forget that all your iptables rules should also be activated if your Ubuntu server is restarted. Otherwise you would have to remember to run your iptables rules manually after each restart. If you forget to run them all manually, or if you have simply forgotten that your server has been restarted, then your firewall is open for everyone. If you are lucky nothing will happen, if not you might get some successful instrusion attacks. Lines 58 and 59 will help you to make sure your rules are automatically loaded after each restart. But this is not everything for iptables configuration on startup. You also need to create a file at /etc/network/if-pre-up.d/iptablesload and one at /etc/network/if-post-down.d/iptablessave. For more information please have a look at the official Ubuntu help sites for iptables. The following two code boxes show the content of our two files. As you can see in both code boxes line 2 is refering to the file /etc/my-iptables.rules, which we have defined in line 58 and 59 of our files iptables.DISABLE_4848.rules and iptables.ENABLE_4848.rules respectively. I have added /sbin/ in front of the iptables commands (see below) because i was facing the problem that iptables commands without /sbin/ could not be found at the time when the files iptablesload or iptablessave were executed during the Ubuntu server startup process.

#!/bin/sh
/sbin/iptables-restore < /etc/my-iptables.rules
exit 0
#!/bin/sh
/sbin/iptables-save -c > /etc/my-iptables.rules
if [ -f /etc/iptables.downrules ]; then
   /sbin/iptables-restore < /etc/iptables.downrules
fi
exit 0

Finally you have to make sure that both files are executable. For that you only need to execute the following commands once.

sudo chmod +x /etc/network/if-post-down.d/iptablessave
sudo chmod +x /etc/network/if-pre-up.d/iptablesload

At this point you can try what happens if you reboot your Ubuntu server (sudo reboot). After Ubuntu has restarted just try sudo iptables -L on the shell. It should show you the rules we have defined. You should see something like this if you hit sudo ./iptables.DISABLE_4848.rules before rebooting:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: UPDATE seconds: 60 hit_count: 3 TTL-Match name: sshprobe side: source
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh state NEW recent: SET name: sshprobe side: source
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:www
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:http-alt
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:8181
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https
DROP       all  --  anywhere             anywhere

Chain FORWARD (policy DROP)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Your firewall settings are loaded automatically whenever Ubuntu is starting up. We can continue with the next steps. Please do not forget that these are only some minimum firewall settings. For maximum security you might need to add your own iptables rules.


2. Setting up Java

The next step is to set up Java. As you can see at the official Oracle Glassfish 3.1.1 download site Glassfish 3.1.1 is certified with Oracle's JDK 1.6.0_26 and JDK 1.7.0. On the other hand you can see on the official Oracle Glassfish 3.1.2.2 download site that the minimum and certified versions are Oracle's JDK 1.6.0_31 and JDK 7 Update 3. That means these are the minimum versions you want to use! I suggest to remove the ObenJDK first if you have it installed and install the Oracle JDK and JRE. I also suggest to remove any previous Sun/Oracle JDK and JRE already installed on your system. On a production system I don't suggest to use the ObenJDK because it is not certified (but that's another story...).

So what we want now is to install the latest JDK 7 from Oracle. Unfortunately Oracle's JDK 7 is not available via Ubuntu's aptitude. So if you want to install Oracles's JDK 7 you will have to download the Linux distribution from Oracle's JDK 7 Download site and install it manually. Installing Oracle's JDK 7 manually means downloading it manually, uploading it manually to your Ubuntu server and the executing the actual installation process. See How do I install Oracle Java JDK 7 on askubuntu.com for more information. The following commands expect that you have already downloaded Oracle's JDK 7 Download (i.e. jdk-7u7-linux-x64.tar.gz) manually to your local machine (i.e. by the browser of your choice) and that the same file has been uploaded to ~/downloads on your Ubuntu server (i.e. via scp).

#remove OpenJDK if installed - this is how you would remove OpenJDK 6:
sudo apt-get remove openjdk-6-jre openjdk-6-jdk

#remove sun's jdk if you have it:
sudo apt-get remove sun-java6-jdk  sun-java6-jre

#get rid of several automatically-installed packages that are not needed anymore...
sudo apt-get autoremove
sudo apt-get autoclean

#extract oracle's jdk
cd ~/downloads
tar -xvf jdk-7u7-linux-x64.tar.gz

#remove previous installations if available
sudo rm -rf /usr/lib/jvm/jdk1.7.0

#make sure our destination folder exists
sudo mkdir /usr/lib/jvm

#move extracted files
sudo mv ./jdk1.7.0_07 /usr/lib/jvm/jdk1.7.0
sudo chgrp -R root /usr/lib/jvm/jdk1.7.0
sudo chown -R root /usr/lib/jvm/jdk1.7.0

#update alternatives - make sure environment points to a valid install if you are replacing...
sudo update-alternatives --install "/usr/bin/java" "java" "/usr/lib/jvm/jdk1.7.0/bin/java" 1
sudo update-alternatives --install "/usr/bin/javac" "javac" "/usr/lib/jvm/jdk1.7.0/bin/javac" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.7.0/bin/javaws" 1
sudo update-alternatives --config java

#check JDK by looking in the /etc/alternatives/ directory
cd /etc/alternatives
ls -lrt java*

#this is optionally since we will add everything to the PATH variable (i usually don't use this):
sudo update-alternatives --install "/usr/bin/apt" "apt" "/usr/lib/jvm/jdk1.7.0/bin/apt" 1
sudo update-alternatives --install "/usr/bin/idlj" "idlj" "/usr/lib/jvm/jdk1.7.0/bin/idlj" 1
sudo update-alternatives --install "/usr/bin/jarsigner" "jarsigner" "/usr/lib/jvm/jdk1.7.0/bin/jarsigner" 1
sudo update-alternatives --install "/usr/bin/java-rmi.cgi" "java-rmi.cgi" "/usr/lib/jvm/jdk1.7.0/bin/java-rmi.cgi" 1
sudo update-alternatives --install "/usr/bin/javadoc" "javadoc" "/usr/lib/jvm/jdk1.7.0/bin/javadoc" 1
sudo update-alternatives --install "/usr/bin/javah" "javah" "/usr/lib/jvm/jdk1.7.0/bin/javah" 1
sudo update-alternatives --install "/usr/bin/javaws" "javaws" "/usr/lib/jvm/jdk1.7.0/bin/javaws" 1
sudo update-alternatives --install "/usr/bin/jconsole" "jconsole" "/usr/lib/jvm/jdk1.7.0/bin/jconsole" 1
sudo update-alternatives --install "/usr/bin/jdb" "jdb" "/usr/lib/jvm/jdk1.7.0/bin/jdb" 1
sudo update-alternatives --install "/usr/bin/jinfo" "jinfo" "/usr/lib/jvm/jdk1.7.0/bin/jinfo" 1
sudo update-alternatives --install "/usr/bin/jps" "jps" "/usr/lib/jvm/jdk1.7.0/bin/jps" 1
sudo update-alternatives --install "/usr/bin/jsadebugd" "jsadebugd" "/usr/lib/jvm/jdk1.7.0/bin/jsadebugd" 1
sudo update-alternatives --install "/usr/bin/jstat" "jstat" "/usr/lib/jvm/jdk1.7.0/bin/jstat" 1
sudo update-alternatives --install "/usr/bin/jvisualvm" "jvisualvm" "/usr/lib/jvm/jdk1.7.0/bin/jvisualvm" 1
sudo update-alternatives --install "/usr/bin/native2ascii" "native2ascii" "/usr/lib/jvm/jdk1.7.0/bin/native2ascii" 1
sudo update-alternatives --install "/usr/bin/pack200" "pack200" "/usr/lib/jvm/jdk1.7.0/bin/pack200" 1
sudo update-alternatives --install "/usr/bin/rmic" "rmic" "/usr/lib/jvm/jdk1.7.0/bin/rmic" 1
sudo update-alternatives --install "/usr/bin/rmiregistry" "rmiregistry" "/usr/lib/jvm/jdk1.7.0/bin/rmiregistry" 1
sudo update-alternatives --install "/usr/bin/serialver" "serialver" "/usr/lib/jvm/jdk1.7.0/bin/serialver" 1
sudo update-alternatives --install "/usr/bin/tnameserv" "tnameserv" "/usr/lib/jvm/jdk1.7.0/bin/tnameserv" 1
sudo update-alternatives --install "/usr/bin/wsgen" "wsgen" "/usr/lib/jvm/jdk1.7.0/bin/wsgen" 1
sudo update-alternatives --install "/usr/bin/xjc" "xjc" "/usr/lib/jvm/jdk1.7.0/bin/xjc" 1
sudo update-alternatives --install "/usr/bin/appletviewer" "appletviewer" "/usr/lib/jvm/jdk1.7.0/bin/appletviewer" 1
sudo update-alternatives --install "/usr/bin/extcheck" "extcheck" "/usr/lib/jvm/jdk1.7.0/bin/extcheck" 1
sudo update-alternatives --install "/usr/bin/jar" "jar" "/usr/lib/jvm/jdk1.7.0/bin/jar" 1
sudo update-alternatives --install "/usr/bin/javafxpackager" "javafxpackager" "/usr/lib/jvm/jdk1.7.0/bin/javafxpackager" 1
sudo update-alternatives --install "/usr/bin/javap" "javap" "/usr/lib/jvm/jdk1.7.0/bin/javap" 1
sudo update-alternatives --install "/usr/bin/jcmd" "jcmd" "/usr/lib/jvm/jdk1.7.0/bin/jcmd" 1
sudo update-alternatives --install "/usr/bin/jcontrol" "jcontrol" "/usr/lib/jvm/jdk1.7.0/bin/jcontrol" 1
sudo update-alternatives --install "/usr/bin/jhat" "jhat" "/usr/lib/jvm/jdk1.7.0/bin/jhat" 1
sudo update-alternatives --install "/usr/bin/jmap" "jmap" "/usr/lib/jvm/jdk1.7.0/bin/jmap" 1
sudo update-alternatives --install "/usr/bin/jrunscript" "jrunscript" "/usr/lib/jvm/jdk1.7.0/bin/jrunscript" 1
sudo update-alternatives --install "/usr/bin/jstack" "jstack" "/usr/lib/jvm/jdk1.7.0/bin/jstack" 1
sudo update-alternatives --install "/usr/bin/jstatd" "jstatd" "/usr/lib/jvm/jdk1.7.0/bin/jstatd" 1
sudo update-alternatives --install "/usr/bin/keytool" "keytool" "/usr/lib/jvm/jdk1.7.0/bin/keytool" 1
sudo update-alternatives --install "/usr/bin/orbd" "orbd" "/usr/lib/jvm/jdk1.7.0/bin/orbd" 1
sudo update-alternatives --install "/usr/bin/policytool" "policytool" "/usr/lib/jvm/jdk1.7.0/bin/policytool" 1
sudo update-alternatives --install "/usr/bin/rmid" "rmid" "/usr/lib/jvm/jdk1.7.0/bin/rmid" 1
sudo update-alternatives --install "/usr/bin/schemagen" "schemagen" "/usr/lib/jvm/jdk1.7.0/bin/schemagen" 1
sudo update-alternatives --install "/usr/bin/servertool" "servertool" "/usr/lib/jvm/jdk1.7.0/bin/servertool" 1
sudo update-alternatives --install "/usr/bin/unpack200" "unpack200" "/usr/lib/jvm/jdk1.7.0/bin/unpack200" 1
sudo update-alternatives --install "/usr/bin/wsimport" "wsimport" "/usr/lib/jvm/jdk1.7.0/bin/wsimport" 1
sudo update-alternatives --config java

#setting JAVA_HOME and AS_JAVA globally for all users (only for bash)
sudo vim /etc/bash.bashrc
#append the following lines:
export GLASSFISH_HOME=/home/glassfish
export JAVA_HOME=/usr/lib/jvm/jdk1.7.0
export PATH=$PATH:$JAVA_HOME/bin:$GLASSFISH_HOME/bin

#setting JAVA_HOME ans AS_JAVA for everyone (best place for setting env vars globally)
#see https://help.ubuntu.com/community/EnvironmentVariables for details
sudo vim /etc/environment
#append the following lines:
JAVA_HOME=/usr/lib/jvm/jdk1.7.0
#we will set this here because it might prevent problems later
AS_JAVA=/usr/lib/jvm/jdk1.7.0

#check JDK by looking in the /etc/alternatives/ directory...
cd /etc/alternatives
ls -lrt java*


3. Downloading and Installing Glassfish

Now we can download Glassfish. I suggest to switch the user now to glassfish, which we have created in the first step. We want to download the Glassfish zip installation file to /home/glassfish/downloads/. Afterwards the zip file has to be extracted and the content can be moved to /home/glassfish/ - this is everything needed for installing Glassfish. Usually the zip file is extracted to a directory called ./glassfish3/. Make sure to move the content of ./glassfish3/ and not ./glassfish3 itself to /home/glassfish/.
#if you dont't have "unzip" installed run this here first
sudo apt-get install unzip

#now switch user to the glassfish user we created (see step 1)
sudo su glassfish

#change to home dir of glassfish
cd /home/glassfish/

#create new directory if not already available
mkdir downloads

#go to the directory we created
cd /home/glassfish/downloads/

#download Glassfish and unzip
wget http://download.java.net/glassfish/3.1.1/release/glassfish-3.1.1.zip
unzip glassfish-3.1.1.zip

#move the relevant content to home directory
mv /home/glassfish/downloads/glassfish3/* /home/glassfish/
#if something has not been moved, then move it manually, i.e.:
mv /home/glassfish/downloads/glassfish3/.org.opensolaris,pkg /home/glassfish/.org.opensolaris,pkg

#exit from glassfish user
exit

#change group of glassfish home directory to glassfishadm
sudo chgrp -R glassfishadm /home/glassfish

#just to make sure: change owner of glassfish home directory to glassfish
sudo chown -R glassfish /home/glassfish

#make sure the relevant files are executable/modifyable/readable for owner and group
sudo chmod -R ug+rwx /home/glassfish/bin/
sudo chmod -R ug+rwx /home/glassfish/glassfish/bin/

#others are not allowed to execute/modify/read them
sudo chmod -R o-rwx /home/glassfish/bin/
sudo chmod -R o-rwx /home/glassfish/glassfish/bin/


At this point you can give it a try and start you Glassfish server. But do not forget to stop it again before you continue with the next steps. Here are the commands for starting and stopping Glassfish:

#now switch user to the glassfish user
sudo su glassfish

#start glassfish
/home/glassfish/bin/asadmin start-domain domain1
#check the output...

#stop glassfish
/home/glassfish/bin/asadmin stop-domain domain1
#check the output...

#exit from glassfish user
exit


4. Setting up an init script

Let's create an init script for now. It helps you to start, stop and restart your Glassfish easily. We also need this to make Glassfish start up automatically whenever Ubuntu is rebooting. The file we need to create is /etc/init.d/glassfish. For starting and stopping Glassfish we will use the asadmin tool that ships with Glassfish (we used it a little in the previous step).
#create and edit file
sudo vi /etc/init.d/glassfish

#(paste the lines below into the file and save it...):

#! /bin/sh

#to prevent some possible problems
export AS_JAVA=/usr/lib/jvm/java-6-sun

GLASSFISHPATH=/home/glassfish/bin

case "$1" in
start)
echo "starting glassfish from $GLASSFISHPATH"
sudo -u glassfish $GLASSFISHPATH/asadmin start-domain domain1
;;
restart)
$0 stop
$0 start
;;
stop)
echo "stopping glassfish from $GLASSFISHPATH"
sudo -u glassfish $GLASSFISHPATH/asadmin stop-domain domain1
;;
*)
echo $"usage: $0 {start|stop|restart}"
exit 3
;;
esac
:

As you can see Glassfish is started with the user glassfish. It's always a bad idea to run a webserver with root. You should always use a restricted user - in our case this will be the user glassfish. You will learn how to use the script we just created in the next steps.


5. Glassfish autostart: adding init script to default runlevels

The init script is set up. Now we can add it to the default run levels. This way our Glassfish will startup whenever Ubuntu is restarted.
#make the init script file executable
sudo chmod a+x /etc/init.d/glassfish

#configure Glassfish for autostart on ubuntu boot
sudo update-rc.d glassfish defaults

#if apache2 is installed:
#stopping apache2
sudo /etc/init.d/apache2 stop
#removing apache2 from autostart
update-rc.d -f apache2 remove

From now on you can start, stop or restart your Glassfish like this (Ubuntu will also do it this way):

#start
/etc/init.d/glassfish start

#stop
/etc/init.d/glassfish stop

#restart
/etc/init.d/glassfish restart

6. Security configuration before first startup

Even now we should not really use Glassfish in production. We will now begin the configuration of Glassfish itself. You should always run these steps, for example changing the default passwords, enabling https, changing the default ssl certificate to be used for https etc. We will also put our attention on Glassfish obfuscation.

Our first step is to change the master password. Glassfish uses it to protect the domain-encrypted files from unauthorized access, i.e. the certificate store which contains the certificates for https communication. When Glassfish is starting up it tries to read such "secured" files - for exactly this purpose Glassfish needs to be provided with the master password either in an intertactive way or in a non-interactive way. I will choose the non-interactive way because we want our Glassfish to start up on Ubuntu reboot as a deamon (in the Windows world this would be called a service). This is necessary so that the start-domain command can start the server without having to prompt the user. To accomplish this we need to set the savemasterpassword option to true. This option indicates whether the master password should be written to the file system. The file is called master-password and can be found at <DOMAIN-DIR>/config/. To change the master password you have to ensure that Glassfish is not running - only then you can call the command change-master-password which will interactivly ask you for the new password.

#switch user to glassfish (stay with this user for complete Step 6!)
sudo su glassfish

#change master password, default=changeit
/home/glassfish/bin/asadmin change-master-password --savemasterpassword=true
#prompt: choose your new master password ==> myMasterPwd

The next step is to change the administration password with change-admin-password. Because this command is a remote command we need to ensure that Glassfish is running before we can execute the command. Since we want "automatic login" we will create an admin password file allowing us to login without being asked for credetials.

#now we have to start Glassfish
/home/glassfish/bin/asadmin start-domain domain1

#change admin password
/home/glassfish/bin/asadmin change-admin-password
#1. enter "admin" for user (default)
#2. hit enter because default pwd is empty
#3. choose you new pwd ==> myAdminPwd

#login for automatic login...
/home/glassfish/bin/asadmin login
#prompt:
#user = admin
#password = myAdminPwd
#==> stores file to /home/glassfish/.asadminpass

#now stop Glassfish
/home/glassfish/bin/asadmin stop-domain domain1


Glassfish is coming with two pre-configured certificate which is used for ssl (https). You can see it in the keystore.jks file if you check for the alias s1as. In Glassfish 3.1 there is even another preconfigured certificate available: glassfish-instance. But that also means that everybody else can get these two certificates, the public keys, private keys, etc. With that information you could never be safe because "others" could "read" your data sent to Glassfish via https. That means you should always make sure to replace the pre-configured s1as and glassfish-instance entries in your keystore. But you should not delete them as long as the alias "s1as" and "glassfish-instance" are still in use (and it is by default in use for https...). I faced some strange behaviour as I did not think of that at the beginning when I simply deleted s1as - learn from my mistake and do not delete it for now... But we can help us with generating a new alias first (myAlias) and when ever needed or wanted we could change each occurrence of s1as to myAlias (i.e. via admin console) and then we could finally delete that s1as. The same has to be done also for glassfish-instance.

The following code box shows you the commands we need for modifying our Glassfish keystore. As you can see we first delete our pre-configured s1as entry (Glassfish mustn't be running!). Later a new s1as entry is generated - it is now unique for us! Similar steps have to be executed also for our second certificate (glassfish-instance).

#create new certs
cd /home/glassfish/glassfish/domains/domain1/config/
keytool -list -keystore keystore.jks -storepass myMasterPwd
keytool -delete -alias s1as -keystore keystore.jks -storepass myMasterPwd
keytool -delete -alias glassfish-instance -keystore keystore.jks -storepass myMasterPwd
keytool -keysize 2048 -genkey -alias myAlias -keyalg RSA -dname "CN=nabisoft,O=nabisoft,L=Mannheim,S=Baden-Wuerttemberg,C=Germany" -validity 3650 -keypass myMasterPwd -storepass myMasterPwd -keystore keystore.jks
keytool -keysize 2048 -genkey -alias s1as -keyalg RSA -dname "CN=nabisoft,O=nabisoft,L=Mannheim,S=Baden-Wuerttemberg,C=Germany" -validity 3650 -keypass myMasterPwd -storepass myMasterPwd -keystore keystore.jks
keytool -keysize 2048 -genkey -alias glassfish-instance -keyalg RSA -dname "CN=nabisoft,O=nabisoft,L=Mannheim,S=Baden-Wuerttemberg,C=Germany" -validity 3650 -keypass myMasterPwd -storepass myMasterPwd -keystore keystore.jks
keytool -list -keystore keystore.jks -storepass myMasterPwd

#update cacerts.jks (hint comes from a comment of previous tutorial - thanks!)
keytool -export -alias glassfish-instance -file glassfish-instance.cert -keystore keystore.jks -storepass myMasterPwd
keytool -export -alias s1as -file s1as.cert -keystore keystore.jks -storepass myMasterPwd

keytool -delete -alias glassfish-instance -keystore cacerts.jks -storepass myMasterPwd
keytool -delete -alias s1as -keystore cacerts.jks -storepass myMasterPwd

keytool -import -alias s1as -file s1as.cert -keystore cacerts.jks -storepass myMasterPwd
keytool -import -alias glassfish-instance -file glassfish-instance.cert -keystore cacerts.jks -storepass myMasterPwd


Now we want to enable https for the admin console. Once we have done that we can be sure that nobody can listen to our data sent via https because nobody else has our certificate, i.e. nobody can decrypt our password used for entering the admin console via browser (in case someone cought our data packages). But this is not all we want to do here. We want to change some of the default JVM Options and we want to make our Glassfish not telling too much ("obfuscation").

The first JVM Option we will change is replacing the -client option with the -server option. I expect the java option -server to be the better choice when it comes to performance. I have also decided to change -Xmx512m (Glassfish default) to a higher value: -Xmx2048m. Furthermore I have added -Xms1024m. For more information about these options please check the documentation for the java launcher options.
All JVM Options so far are optional. But at least adding -Dproduct.name="" is a good idea for everyone. If you would not add this then each http/https response will contain a header field like this: Server: GlassFish Server Open Source Edition 3.1
This is some great piece of information for hackers - that's why you should disable it. We do not want Glassfish to talk too much for security reasons!

We also don't want Glassfish to send a header similar to X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1 Java/Apple Inc./1.6) because this is telling everyone we are using a Servlet 3.0 container and that we are (of course) using Java etc. So we have to disable sending x-powered-by in the http/https headers - this is accomplished with the last three asadmin commands in the code box below. Now our Glassfish is working in silent mode - it is not telling too much any more. Glassfish obfuscation accomplished.

# the commands here change the file at
# /home/glassfish/glassfish/domains/domain1/config/domain.xml

#first we have to start Glassfish
/home/glassfish/bin/asadmin start-domain domain1

# enable https for remote access to admin console
# requests to http://xxx:4848 are redirected to https://xxx:4848
/home/glassfish/bin/asadmin set server-config.network-config.protocols.protocol.admin-listener.security-enabled=true
/home/glassfish/bin/asadmin enable-secure-admin

#change JVM Options
#list current jvm options
/home/glassfish/bin/asadmin list-jvm-options
#now start setting some important jvm settings
/home/glassfish/bin/asadmin delete-jvm-options -- -client
/home/glassfish/bin/asadmin create-jvm-options -- -server
/home/glassfish/bin/asadmin delete-jvm-options -- -Xmx512m
/home/glassfish/bin/asadmin create-jvm-options -- -Xmx2048m
/home/glassfish/bin/asadmin create-jvm-options -- -Xms1024m
#get rid of http header field value "server" (Glassfish obfuscation)
/home/glassfish/bin/asadmin create-jvm-options -Dproduct.name=""
#restart to take effect
/home/glassfish/bin/asadmin stop-domain domain1
/home/glassfish/bin/asadmin start-domain domain1
#what jvm options are configured now?
/home/glassfish/bin/asadmin list-jvm-options

#disable sending x-powered-by in http header (Glassfish obfuscation)
/home/glassfish/bin/asadmin set server.network-config.protocols.protocol.http-listener-1.http.xpowered-by=false
/home/glassfish/bin/asadmin set server.network-config.protocols.protocol.http-listener-2.http.xpowered-by=false
/home/glassfish/bin/asadmin set server.network-config.protocols.protocol.admin-listener.http.xpowered-by=false

#we are done with user glassfish
exit

7. Run Glassfish

Finally we have come to where we wanted. We have installed, secured and configured our Glassfish installation.
#starting glassfish
sudo /etc/init.d/glassfish start

#remove glassfish from autostart
#update-rc.d -f glassfish remove

Comments
Additional configuration detail for this excelent tutorial
posted by Roberto
Sun Jul 21 16:26:24 UTC 2013
This tutorial is an excelent piece of work. It has saved me a lot of time and effort to get all the information it gives.
I only miss two things:
On one hand, once you install your SSL certificate you must change the configuration of your Glassfish domain so that it uses it instead of s1as. This can be done from the admin console under Configurations -> Server Config -> Network Config -> Protocols -> httpsListener-2. I am sure there is a line subcommand of stadmin to do it too, but I don't know the details.
On the other hand, I miss one line at the end of the list of commands to modify the Glassfish Keystore saying that in case you want to use a certificate signed by a Certification Authority instead of a self-signed certificate you should use the new key pair you have generated (the one with alias "myAlias") to get a signed certificate following the instructions from the Certification Authority you choose.
Thank you for your tutorial.
Automated Login not working
posted by Vincenz
Fri Jun 21 21:34:41 UTC 2013
Hello, I created all the files as you did and pretty much everything worked fine. But it will not login automatically when i reboot. It always asks me for the password. Do you know why this could be?
Solved: Cannot Start Glassfish
posted by Spyros
Thu May 02 11:08:15 UTC 2013
Answer found to question below!
I had to make sure hostname is in /etc/ hostname

Cannot Start Glassfish
posted by Spyros
Tue Apr 30 12:47:34 UTC 2013
Thank you for your tutorial.
I execute these steps in Ubuntu 12.04 jeos, when I start for the first time:
Executing{
#start glassfish
/home/glassfish/bin/asadmin start-domain domain1
#check the output...
 }
I get the following output:
"/usr/lib/jvm/jdk1.7.0/bin/java: 1: /usr/lib/jvm/jdk1.7.0/bin/java: Syntax error: end of file unexpected (expecting ")")"

Could you please provide any suggestions?
I am trying to solve that for a week.
Cannot access Web Admin Console
posted by Elmar
Fri Feb 08 13:13:48 UTC 2013
I followed tutorial with few changes to install GlassFish on a remote host.

Debian 6.0.5 instead of Ubuntu 10.04
GlassFish version 3.1.2.2 instead of 3.1.1
sun-java6-jdk (1.6.0_26) also tested with openjdk-6-jdk (1.6.0_18)

Everything works fine, except the web admin console. I can deploy apps (e.g. Jenkins) via CLI and asadmin and they work. But i can not access the web admin console via http(s)://my-domain:4848

My Browser (Safari) notifies me about my self signed certificate and after a while it reports that it can't establish a secure connection to my server.

The log (glassfish/domains/domain1/log/server.log) is clean. I turned off the firewall but the problem still exists.

Can you help me to fix this Problem or have you suggestions what i can try.

--

Thanks a lot,

Elmar
Very thorough and useful tutorial
posted by marshal
Wed Jan 30 05:13:49 UTC 2013
Great work. Thank you so much!
Thanks
posted by Mohammad Mahdi Shahabi
Thu Jan 24 21:29:27 UTC 2013
Superb
Nice tutorial!
posted by Piero
Mon Dec 10 02:48:11 UTC 2012
Hi Nabi, 
great tutorial! It's very complete and has a very nice presentation :)

I was going through it with almost no inconvenient, until I tried to update cacerts.jks. When I reach line 15 :

     keytool -delete -alias glassfish-instance -keystore cacerts.jks -storepass mypass

and I get this error:
     
     keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect

If I try to execute the rest of the commands I get the same error. I have checked twice the log of my session, and I haven't committed any spell mistake with the password that I have given.
Do you know what can be the problem? I would be greatly thankful if you give me a hand.

Best regards.
RE: RE: Wonderful howto !
posted by Brice DELATTRE
Wed Nov 14 14:25:44 UTC 2012
I'm confused... sorry ;-D
I didn't see the scroll bars !

Thanks again.
RE: Wonderful howto !
posted by Nabi
Tue Nov 13 15:51:36 UTC 2012
hi brice,
thank you for your comment and the flowers!
please check the commands once again => "-keystore keystore.jks" is already there, just scroll to the end of each line ;-)
Nabi
Wonderful howto !
posted by Brice DELATTRE
Tue Nov 13 11:03:44 UTC 2012
Hi,

Thanks for this tutorial.
As described by Christopher, it works fine in Ubuntu Server 12.04 TLS.

It seems to be an error in keytool commands at lines 6, 7 and 8.
I must add "-keystore keystore.jks" to prevent use of "~/.keystore.jks" by keytool.

Best regards.
Great article - works on Ubuntu 12.04 LTS :)
posted by Christopher Thorjussen
Wed Oct 31 16:39:00 UTC 2012
Great tutorial and information. Used it to create my own private how-to. I tend to keep 3rd party applications in /opt/ and not /home/ but it was easy peasy to change scripts etc. Example:

/opt/glassfish/glassfish-3.1.2.2
/opt/glassfish/glassfish3              <--- symlink to the above one. Easy to change
                                               versions without changing scripts and variables :)

I can add that to change stuff like  XX:PermSize=64m you need escape the colon with backslash and put all in quotes, like this:

asadmin delete-jvm-options -- "-XX\:PermSize=64m"
asadmin delete-jvm-options -- "-XX\:MaxPermSize=192m"
asadmin create-jvm-options -- "-XX\:PermSize=128m"
asadmin create-jvm-options -- "-XX\:MaxPermSize=256m"
Many thanks
posted by kalyst
Sat Sep 08 16:14:21 UTC 2012
Wonderful tutorial, and up-to-date !
I'm french student and it was very useful and not only for GlassFish.

Don't forget ... donate !
Very helpful tutorial
posted by Joaquim Miralles
Thu Aug 30 12:40:11 UTC 2012
Thanks a lot!
SMTP and FTP
posted by Bill
Sat Jun 30 04:25:42 UTC 2012
This is an amazing tutorial!

How can I enable FTP and SMTP ports?

I tried:

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

but still cant connect with my ftp

Thank you!
Great post
posted by Alex
Fri Jun 15 18:26:28 UTC 2012
Your post saved my day. Very, very helpful.
running apache2 side by side
posted by ian
Wed May 30 14:41:07 UTC 2012
I think I found the answer to my previous question.

In the iptables rules setup if I comment out the two lines redirecting port 80 to 8080 that should be all there is to it unless there are other conflicts between the two servers. This is a home dev server but on a production server I wouldn't want to run them both side by side anyway.

Thanks
possible to run this along side apache2 instead of removing it?
posted by Ian
Wed May 30 05:53:26 UTC 2012
Hi, thanks for this awesome tutorial. I'm almost finished but need a break. I did it on Ubuntu12.10 and manually installed jdk 7 so some slight mods from the tutorial but all seems to be working well so far.

I was wondering though, if apache2 can be ran side by side with this somehow?

Thanks
Glassfish Running Issue
posted by Haseeb
Thu May 03 08:00:51 UTC 2012
You did the great job, this tutorial is helped me a lot throughout this activity. Im having a little problem. when i go to start domain it prompts me an error like '' There is a process already using the admin port 4848 -- it probably is another instance of a GlassFish server.
Command start-domain failed.''

Im working on Amazon EC2 Ubuntu 10.04. there were nothing installed earlier, i just install java, mysql server and glassfish server to deploy my application. I faced this problem. I check all open ports by using 'netstat' command, given port was not listed there. Its mean no application using that port it could be another hidden problem which im enable to figure out.

And if i try to create another domain (new domain). it prompts me another error that "You do not have permission to use port 5050 for newdomain. Try a different port number or login to a more privileged account.
CLI130 Could not create domain, newdomain
Command create-domain failed."

What's wrong here, i would be grateful to you for your time and help.
it works
posted by Kortas
Tue Mar 13 18:50:37 UTC 2012
thank you!
Thanks for guiding us in installing and securing Glassfish
posted by Julius Gamanyi
Sun Mar 04 11:34:25 UTC 2012
Hi,

Just wanted to say thanks for this tutorial, which was easy to follow while addressing security concerns. I especially liked how you took care of the user and group of Glassfish, and also how you guided us in securing Glassfish via SSL and firewall. Many of the installation tutorials that I've come across neglect these important aspects. Having followed it, except the firewall section, I didn't run into any problems.

Julius
Glassfish User and JPA - update
posted by Prashanth
Mon Oct 10 16:35:34 UTC 2011
Hi,

It works now. It was my mistake. May be i did not log out of the telnet (Ssh) session after adding myself to glassfishadm group or some other changes. Now that I am trying this on a different day ( new session) glassfish is running as glassfish user and works in harmony with JPA. 
Glassfish User and JPA
posted by Prashanth
Thu Oct 06 20:16:16 UTC 2011
Hi,

Thanks for the great tutorial.Neatly done great... I ran into some problems with JPA while trying to run glassfish server as glassfish user.

Background:
I had Glassfishv3 running on Ubuntu 10.04LTS. I had added it as a service and everything was great. Then I came across your tutorial and read some great tips like not  running as "root" and securing the admin console so decided to upgrade my server.

change:
I downloaded glassfish 3.1.1 to /opt/glassfish3.1.1 folder , changed the softlink for /opt/glassfish  from  /opt/glassfishv3  to /opt/glassfish3.1.1. created glassfish user and everything you mentioned in your tutorial (except for the ip routing table), worked like a gem.

Problem:
Now when i deploy my application , there is an error . The system does not seem to be able to talk to JPA. the error is "java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManagerFactory"

well after some head scratching, i decided to try stopping glassfish from /etc/init.d/glassfish stop (which starts and stops glassfish as user glassfish)

Then i started glassfish server as root using sudo /opt/glassfish/bin/asadmin start-domain domain1

well everything is normal . The application is able to talk to the database and everything is great.

Confirmation:
to confirm this I stopped glassfish and restarted it as glassfish user and the problem came back. So i am back to running glassfish as "root" 

Any idea what might be wrong or what i am missing. It looks like i am not able to connect to the database, even though the ping for DB connection pool (from admin console) is successful. I am using JTA to connect to DB.  DB user id/ password/address is correct as the same settings work when restarted as root.  There is no change to any settings on the application or glassfish. Just the user that is used to run glassfish server.

My database is postgress 8.4 and runs on the same machine as glassfish.

Thanks,


Change admin-listener certificate alias through CLI
posted by Muhammad El-Sergani
Fri Aug 19 02:09:03 UTC 2011
Never mind, found the command:

asadmin enable-secure-admin --adminalias=XYZ
Thanks a lot!!
posted by Muhammad El-Sergani
Fri Aug 19 01:46:09 UTC 2011
Ok, so this time I got everything the way I need (thanks to you!) .. but how do I change the admin-listener certificate to myAlias, since the SSL, HTTP and CACHE tabs are hidden once secure-admin is enabled?

Appreciate the effort...

//M
Great tutorial ... one question
posted by MuhammadEl-Sergani
Mon Aug 15 18:10:58 UTC 2011
Hello,

Thanks for the great tutorial, I've followed the earlier 3.1 one and it worked great, only thing missing, is how exactly do I get to secure my admin listener and http-listener 1 or 2?

I'm able to do the http-listener, but I'm not yet able to correctly secure the admin listener, it always ends up with HTTP ERROR 500, and I'll have to kill the process and restart domain1 again.

Appreciate if you could help shed some light over this, as I'm planning a full re-installation to our glassfish instances.

Thanks again.

//M