Glassfish Installation

Introduction

These notes describe installation of Glassfish 3.1 or 3.1.x — the reference implementation of Java EE — on a Debian or Ubuntu system. The upcoming Glassfish 4.0 is not considered. The Java SE Development Kit is assumed to be installed already. Users who prefer to download the bundle containing both JavaSE and Glassfish will need to make adjustments to Steps 2 and 3 below.

It is simple and tempting to install Glassfish in your own directory (for convenience), or to switch to superuser and install it in a more public space. Many other tutorials take one of these easy options. However the aim of this tutorial is to implement a (slightly) higher level of security. For this reason we take the more tricky route of installing Glassfish in the home directory of a pseudo-user 'glassfish' with limited rights. We also touch on certificates and administration matters.

This document is the result of performing several installations of Glassfish. It is more of a recipe than a tutorial. Feel free to write to me if you find errors, or if you notice serious omissions.

Table of contents:

  1. Setting up users
  2. Setting up environment variables
  3. Downloading and installing Glassfish
  4. Setting up an init script
  5. Autostart: adding init script
  6. Security configuration
  7. Maintaining Glassfish
  8. Programming for Glassfish
  9. Appendix: Private Glassfish installation

1. Setting up users

It is possible to install Glassfish under your own username: the advantage is personal convenience, but the disadvantage occurs when trying to make it accessible to the public. Conversely, it is possible to install Glassfish as root; however the advantages and disadvantages are then reversed. And both approaches are ugly from the perspective of security. Far better to create a user with restricted rights, and use that for running Glassfish. Once you have added such a user (let's say 'glassfish'), you might also want to add a new group (let's called it 'glassfish' too). This group can then be used to facilitate access for all users who will be allowed to administer Glassfish.

Below are the required user- and group-related commands. Customize them to suit your environment. In particular, choose whether to give the pseudo-user 'glassfish' a shell. Doing so facilitates administration — the .bashrc file can contain handy environment variables and aliases — however this is a security concern. To allay these concerns, it is possible deny Glassfish automatic access to any shell; and instead to invoke a shell and environment variables only if and when necessary. The present instructions have been tested both ways. Generally, these instructions assume that Glassfish has no default shell.

Add a new user called 'glassfish' with group 'glassfish'
sudo adduser --system --group --home /home/glassfish [--shell /bin/bash] glassfish

Enable an existing user to be a Glassfish administrator.  Repeat for additional users.
sudo usermod -a -G glassfish existingUser

##### NOTE! ######
# The user will need to login afresh, before this modification takes effect
# The user can check their group membership with:
groups       # List should include 'glassfish'

#        Undo:
# If we want to delete the user and group 'glassfish' (and optionally remove Glassfish too):
sudo deluser [--remove-home] glassfish
sudo delgroup glassfish

We now have a limited user, who will be the owner of Glassfish. Note that user 'glassfish' has no login ability. But don't worry. As will be seen below, Glassfish maintains its own administration passwords and security realms, so the configuration and content of the server will still be password protected.

2. Setting up environment variables

See instructions elsewhere for installation of Java SE. (Glassfish 3.1 requires Oracle's JDK 1.6.0_22 or later; Glassfish 3.1.1 requires JDK 1.6.0_26 or later, including 1.7.0, Glassfish 3.1.2 requires JDK 1.6.0_31+ or 1.7.0_03+.) One of the consequences of installation should be addition of an environment variable pointing to its location, e.g. JAVA_HOME=/usr/java/jdk1.6.0_26, or similar.

Ant is Glassfish's other dependency. There is said to be a version of Ant built-in to Glassfish, but I expect everyone will want to install the latest version themselves.

Once these two dependencies are satisfied we must ensure that Glassfish administrators and developers can access Java SE+EE and Ant. This will enable them to complete the installation of Glassfish, and subsequently to perform compilations and administration tasks. Here is an example of the required additions to their .bashrc — although those users will certainly need to make adjustments to the following, to suit their own environment.

Java SE
export JAVA_HOME=/usr/java/jdk1.7.0_15
export JAVA_BINDIR=${JAVA_HOME}/bin
echo $PATH | /bin/grep -q -v $JAVA_BINDIR
if [ $? -eq 0 ]; then export PATH="${PATH}:$JAVA_BINDIR"; fi

Ant
export ANT_HOME=/usr/java/apache-ant-1.8.4
echo $PATH | /bin/grep -q -v $ANT_HOME/bin
if [ $? -eq 0 ]; then export PATH="${PATH}:$ANT_HOME/bin"; fi

Glassfish
export GLASSFISH_PARENT=/home/glassfish
export GLASSFISH_HOME=/home/glassfish/glassfish
echo $PATH | /bin/grep -q -v $GLASSFISH_HOME/bin
if [ $? -eq 0 ]; then export PATH="${PATH}:$GLASSFISH_HOME/bin"; fi

We shall configure Glassfish to be managable by certain favoured users, logged in as themselves, and so it should never be necessary for anyone to log in as user 'glassfish'. For this reason the home directory of the pseudo-user glassfish does not need any .profile or .bashrc file.

In particular, appending $GLASSFISH_HOME/bin to their $PATH (as suggested above) will give administrators access to asadmin and other management and development tools. [There is just one other location that administrators might want to add to their $PATH, namely $GLASSFISH_PARENT/bin. This contains the two update tools, plus an alternative version of asadmin.]

3. Downloading and installing Glassfish

Choosing amongst the many available versions of Glassfish is very confusing, as the differences are not explained properly. Also, the naming and numbering of Java products is annoyingly volatile. However the alternatives are, roughly, as follows:

What are the distinctions?

It is actually not terribly critical which version you choose: all are free, and will quickly get you up and running. But I find the Glassfish zip from dlc.sun.com.edgesuite.net to be more to my taste, as I can manage installation and operation more directly. The zip version is required for this set of instructions.

Accordingly we shall download the Glassfish zip installation file. We shall opt for the 'full' version, rather than the Web Profile. In the following set of commands we shall download it to /home/glassfish/downloads/, unzip it there, and finally re-home everything to /home/glassfish/.

Switch to the user 'glassfish' and to /home/glassfish, but retain the superuser's environment
sudo su --shell /bin/bash glassfish
# 'sudo -H -u glassfish -s' has a similar effect, but preserves env variables

Create new download directory, '/home/glassfish/downloads'
cd ~
whoami       # should say 'glassfish'
pwd          # should say '/home/glassfish'
mkdir downloads
cd downloads

Download Glassfish and unzip.
# [You may or may not need to set the environment variable http_proxy first.]
wget http://dlc.sun.com.edgesuite.net/glassfish/3.1.2/release/glassfish-3.1.2.zip
unzip glassfish-3.1.2.zip
# This creates /home/glassfish/downloads/glassfish3/*

Move the relevant content up two levels to home directory
mv glassfish3/* /home/glassfish/
# One strangely named directory needs to be moved explicitly
mv glassfish3/.org.opensolaris,pkg /home/glassfish/
# Delete the now-empty directory created by unzip
rmdir glassfish3

Exit from glassfish user.  We didn't login, so 'logout' is not appropriate.
exit

Ensure owner:group for glassfish is glassfish:glassfish
sudo chown -R glassfish:glassfish /home/glassfish

Ensure the owner and group can execute/modify/read bin files, and autodeploy
sudo chmod -R ug+rwx /home/glassfish/bin/
sudo chmod -R ug+rwx /home/glassfish/glassfish/bin/
sudo chmod -R ug+rwx /home/glassfish/glassfish/domains/domain1/autodeploy/

Ensure others are not allowed to execute/modify/read bin files, nor autodeploy
sudo chmod -R o-rwx /home/glassfish/bin/
sudo chmod -R o-rwx /home/glassfish/glassfish/bin/
sudo chmod -R o-w /home/glassfish/glassfish/domains/domain1/autodeploy/

#        Undo:
# In case we want to delete Glassfish:
sudo rm -rf /home/glassfish

At this point you can already start your 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 --shell /bin/bash glassfish

Start Glassfish
export AS_JAVA=/usr/java/jdk1.7.0_15
/home/glassfish/bin/asadmin start-domain domain1
/home/glassfish/bin/asadmin start-database
#check the output, /home/glassfish/glassfish/domains/domain1/logs/server.log

05/06/2011 5:56:22 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: JVM invocation command line:
/usr/java/jdk1.6.0_26/bin/java
-cp /home/glassfish/glassfish/modules/glassfish.jar
-XX:+UnlockDiagnosticVMOptions
-XX:MaxPermSize=192m
-XX:NewRatio=2
-Xmx512m
-javaagent:/home/glassfish/glassfish/lib/monitor/btrace-agent.jar=unsafe=true,noServer=true
-client
-Dosgi.shell.telnet.maxconn=1
-Dfelix.fileinstall.disableConfigSave=false
-Djdbc.drivers=org.apache.derby.jdbc.ClientDriver
-Dfelix.fileinstall.dir=/home/glassfish/glassfish/modules/autostart/
-Djavax.net.ssl.keyStore=/home/glassfish/glassfish/domains/domain1/config/keystore.jks
-Dosgi.shell.telnet.port=6666
-Djava.security.policy=/home/glassfish/glassfish/domains/domain1/config/server.policy
-Dfelix.fileinstall.log.level=2
-Dfelix.fileinstall.poll=5000
-Dcom.sun.aas.instanceRoot=/home/glassfish/glassfish/domains/domain1
-Dosgi.shell.telnet.ip=127.0.0.1
-Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory
-Djava.endorsed.dirs=/home/glassfish/glassfish/modules/endorsed:/home/glassfish/glassfish/lib/endorsed
-Dcom.sun.aas.installRoot=/home/glassfish/glassfish
-Dfelix.fileinstall.bundles.startTransient=true
-Djava.ext.dirs=/usr/java/jdk1.6.0_26/lib/ext:/usr/java/jdk1.6.0_26/jre/lib/ext:/home/glassfish/glassfish/domains/domain1/lib/ext
-Dfelix.fileinstall.bundles.new.start=true
-Djavax.net.ssl.trustStore=/home/glassfish/glassfish/domains/domain1/config/cacerts.jks
-Dorg.glassfish.additionalOSGiBundlesToStart=org.apache.felix.shell,org.apache.felix.gogo.runtime,org.apache.felix.gogo.shell,org.apache.felix.gogo.command
-Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as
-Djava.security.auth.login.config=/home/glassfish/glassfish/domains/domain1/config/login.conf
-DANTLR_USE_DIRECT_CLASS_LOADING=true
-Dgosh.args=--nointeractive
-Djava.library.path=/home/glassfish/glassfish/lib:/usr/java/jdk1.6.0_26/jre/lib/i386/server:/usr/java/jdk1.6.0_26/jre/lib/i386:/usr/java/jdk1.6.0_26/lib/i386:/usr/java/packages/lib/i386:/lib:/usr/libcom.sun.enterprise.glassfish.bootstrap.ASMain
-domainname domain1
-asadmin-args --host,,,localhost,,,--port,,,4848,,,--secure=false,,,--terse=false,,,--echo=false,,,--interactive=true,,,start-domain,,,--verbose=false,,,--debug=false,,,--domaindir,,,/home/glassfish/glassfish/domains,,,domain1
-instancename server
-verbose false
-debug false
-asadmin-classpath /home/glassfish/glassfish/modules/admin-cli.jar
-asadmin-classname com.sun.enterprise.admin.cli.AsadminMain
-upgrade false
-type DAS
-domaindir /home/glassfish/glassfish/domains/domain1
-read-stdin true
05/06/2011 5:56:22 PM com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: Successfully launched in 6 msec.
05/06/2011 5:56:24 PM null
INFO: Running GlassFish Version: GlassFish Server Open Source Edition 3.1 (build 43)
[#|2011-06-05T17:56:24.090+0930|INFO|glassfish3.1|org.glassfish.ha.store.spi.BackingStoreFactoryRegistry|_ThreadID=10;_ThreadName=Thread-1;|Registered org.glassfish.ha.store.adapter.cache.ShoalBackingStoreProxy for persistence-type = replicated in BackingStoreFactoryRegistry|#]

[#|2011-06-05T17:56:24.354+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=28;_ThreadName=Thread-1;|Grizzly Framework 1.9.31 started in: 136ms - bound to [0.0.0.0:8080]|#]

[#|2011-06-05T17:56:24.354+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=32;_ThreadName=Thread-1;|Grizzly Framework 1.9.31 started in: 107ms - bound to [0.0.0.0:4848]|#]

[#|2011-06-05T17:56:24.354+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=29;_ThreadName=Thread-1;|Grizzly Framework 1.9.31 started in: 98ms - bound to [0.0.0.0:3700]|#]

[#|2011-06-05T17:56:24.354+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=31;_ThreadName=Thread-1;|Grizzly Framework 1.9.31 started in: 92ms - bound to [0.0.0.0:7676]|#]

[#|2011-06-05T17:56:24.354+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=30;_ThreadName=Thread-1;|Grizzly Framework 1.9.31 started in: 113ms - bound to [0.0.0.0:8181]|#]

[#|2011-06-05T17:56:24.426+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=1;_ThreadName=Thread-1;|GlassFish Server Open Source Edition 3.1 (43) startup time : Felix (1,579ms), startup services(556ms), total(2,135ms)|#]

[#|2011-06-05T17:56:24.651+0930|INFO|glassfish3.1|javax.enterprise.system.tools.admin.org.glassfish.server|_ThreadID=40;_ThreadName=Thread-1;|JMXStartupService: Started JMXConnector, JMXService URL = service:jmx:rmi://dogmatix:8686/jndi/rmi://dogmatix:8686/jmxrmi|#]


Stop glassfish
/home/glassfish/bin/asadmin stop-domain domain1
/home/glassfish/bin/asadmin stop-database
#check the output, /home/glassfish/glassfish/domains/domain1/logs/server.log

[#|2011-06-05T18:04:39.659+0930|INFO|glassfish3.1|javax.enterprise.system.tools.admin.com.sun.enterprise.v3.admin|_ThreadID=60;_ThreadName=Thread-1;|Server shutdown initiated|#]

[#|2011-06-05T18:04:42.376+0930|INFO|glassfish3.1|javax.enterprise.system.tools.admin.org.glassfish.server|_ThreadID=60;_ThreadName=Thread-1;|JMXStartupService: Stopped JMXConnectorServer: null|#]

[#|2011-06-05T18:04:42.376+0930|INFO|glassfish3.1|javax.enterprise.system.tools.admin.org.glassfish.server|_ThreadID=60;_ThreadName=Thread-1;|JMXStartupService and JMXConnectors have been shut down.|#]

[#|2011-06-05T18:04:42.376+0930|INFO|glassfish3.1|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=60;_ThreadName=Thread-1;|Shutdown procedure finished|#]


Exit from glassfish user
exit

4. Setting up an init script

Let's create an init script, to help start, stop and restart Glassfish easily. (I know that init is a bit old-fashioned, but upstart is still unfamiliar to me.) This script may be called manually, or else automatically during reboots and shutdowns. The file we need to create is /etc/init.d/glassfish. We will take this opportunity to start Derby too, and will use the asadmin tool for both jobs.

# Create init script
sudo vi /etc/init.d/glassfish

Then insert the following:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          glassfish
# Required-Start:    $remote_fs $network $syslog
# Required-Stop:     $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts Glassfish
# Description:       Starts Glassfish application server
### END INIT INFO
 
# We need this, since NetworkServerControl uses $JAVA_HOME to find java
export JAVA_HOME=/usr/java/jdk1.7.0_15 # Check!
# We need this, since asadmin contains the line 'JAVA=${AS_JAVA}/bin/java'
export AS_JAVA=$JAVA_HOME

GLASSFISH=/home/glassfish
DERBY_BIN=/home/glassfish/javadb/bin

case "$1" in
start)
  echo "Starting Glassfish from ${GLASSFISH}"
  sudo -u glassfish -E $GLASSFISH/bin/asadmin start-database
  sudo -u glassfish -E $GLASSFISH/bin/asadmin start-domain domain1
  ;;
stop)
  echo "Stopping Glassfish from ${GLASSFISH}"
  sudo -u glassfish -E $GLASSFISH/bin/asadmin stop-domain domain1
  sudo -u glassfish -E $GLASSFISH/bin/asadmin stop-database
  ;;
restart)
  $0 stop
  $0 start
  ;;
status)
  echo "# Glassfish at ${GLASSFISH}:"
  sudo -u glassfish -E $GLASSFISH/bin/asadmin list-domains | grep -v Command
  sudo -u glassfish -E $GLASSFISH/bin/asadmin list-domains | grep -q "domain1 running"
  if [ $? -eq 0 ]; then
    sudo -u glassfish -E $GLASSFISH/bin/asadmin uptime | grep -v Command
    echo "\n# Deployed applications:"
    sudo -u glassfish -E $GLASSFISH/bin/asadmin list-applications --long=true --resources | grep -v Command
    echo "\n# JDBC resources:"
    sudo -u glassfish -E $GLASSFISH/bin/asadmin list-jdbc-resources | grep "jdbc/"
  fi
  echo "\n# Derby:"
  sudo -u glassfish -E $DERBY_BIN/NetworkServerControl ping | sed "s/^.* : //"
  ;;
*)
  echo "Usage: $0 {start|stop|restart|status}"
  exit 1
  ;;
esac

exit 0

Make the script executable. You can now start, stop or restart Glassfish manually via the init.d script:

Make the init script executable by root
sudo chmod ug+x /etc/init.d/glassfish

Start
sudo /etc/init.d/glassfish start

Status
sudo /etc/init.d/glassfish status

Do some tests (here, 'EXAMPLEDB' is some pre-existing database)
firefox http://localhost:8080/
firefox file:///home/glassfish/javadb/index.html
java -jar $GLASSFISH_PARENT/javadb/lib/derbyrun.jar ij    # 'quit;'  to exit
java -jar $GLASSFISH_PARENT/javadb/lib/derbyrun.jar sysinfo
java -jar $GLASSFISH_PARENT/javadb/lib/derbyrun.jar dblook -d  jdbc:derby://localhost:1527/EXAMPLEDB

Restart
sudo /etc/init.d/glassfish restart
 
Stop
sudo /etc/init.d/glassfish stop

When Glassfish is started with this init.d script, the process will be owned by the user 'glassfish'. This is a major goal of our installation procedure, as this user has very limited authorization. (Indeed, user 'glassfish' is not even able to run the init.d script!)

5. Autostart: adding init script

Now ensure that Glassfish (and Derby) are run whenever the server is restarted.

Configure Glassfish for autostart on Ubuntu boot
sudo update-rc.d glassfish defaults

This is a good time to reboot, and to check that http://localhost:8080/ is showing up in your browser. You will also see from ps aux that the processes Glassfish and Derby are both owned by the pseudo-user 'glassfish'. This user is very limited: it has no login shell (see /etc/passwd), and even when you become that user via sudo su --shell /bin/bash glassfish you will find that you belong to no groups, other than 'glassfish'. This is as it should be.

However, we are not done yet. The server is currently running with a widely-known default administration password … Hopefully your firewall is blocking attackers! Fixing this vulnerability is the subject of the next section.

If we want to remove this init script:

#        Undo:
sudo /etc/init.d/glassfish stop
sudo update-rc.d -f glassfish remove
sudo rm /etc/init.d/glassfish

6. Security configuration

We shall now begin the configuration of Glassfish itself. For security, you should always run these steps: change the default passwords, enable https, change the default SSL certificate used for https etc. We shall also give attention to Glassfish obfuscation.

The first step is to switch to user 'glassfish' and set environment variables. This is a pre-requisite for all three of the following subsections.

Switch user to glassfish (and remain as this user throughout Step 6!)
sudo su --shell /bin/bash glassfish
# Or 'sudo -H -u glassfish -s'

Set up environment for user 'glassfish'
export AS_JAVA=/usr/java/jdk1.7.0_15    [essential for running asadmin]
export PATH=$PATH:$AS_JAVA/bin          [essential for running keytool]
#export PATH=$PATH:/home/glassfish/bin  [optional: facilitates running asadmin]

Passwords

Our first step is to change the master password with change-master-password. Glassfish uses the master password 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 — and for this reason Glassfish needs to be provided with the master password, either in an intertactive way or in a non-interactive way. We shall choose the non-interactive way: we want our Glassfish to start up on Ubuntu reboot as a daemon, and prefer not to have to enter a password each time. To accomplish this we need to set the --savemasterpassword option to true. This option causes the master password to be stored in the file master-password in the parent of the domain's configuration directory, namely in $GLASSFISH_HOME/domains/domain1/.

Tip: Changing the master password will cause several changes. It will create a file $GLASSFISH_HOME/domains/domain1/master-password, as well as update three files in $GLASSFISH_HOME/domains/domain1/config/, namely domain-passwords, keystore.jks and cacerts.jks. If I do this carelessly, I often get a hard-to-recover-from error, "Keystore was tampered with, or password was incorrect", so I suggest backing-up these files before updating the master password. It may save you from a re-installation. [Another tip: If you are in deep trouble, then setting export AS_DEBUG=true may help.]
# Ensure you are running as user 'glassfish'!!

Stop Glassfish
/home/glassfish/bin/asadmin stop-domain domain1

Backup default passwords.
# In addition to the three shown:
# - add domains/domain1/master-password, if this exists
# - add domains/domain1/local-password, just for completeness
cd /home/glassfish/glassfish
tar cf passwords.orig.tar domains/domain1/config/domain-passwords domains/domain1/config/keystore.jks domains/domain1/config/cacerts.jks

Change master password
/home/glassfish/bin/asadmin change-master-password --savemasterpassword=true domain1
#     Enter the current master password>     [By default this is 'changeit']
#     Enter the new master password>         [e.g. 'myMasterPwd']
#     Enter the new master password again>
# After entering the new master password twice, there is a pause of several 
# seconds.  Then you will find new versions of 'master-password'
# 'domain-passwords' 'keystore.jks' and 'cacerts.jks'.  [All initially have
# 600 permissions, but after change-master-password the
# file 'domain-passwords' has 664 permissions: this is surely a bug.]

Test:
# Your chosen master password should unlock both keystores, and reveal
# two certificates in keystore.jks, and many additional ones in cacerts.jks.
keytool -list -v -keystore /home/glassfish/glassfish/domains/domain1/config/keystore.jks [-storepass myMasterPwd]
keytool -list -v -keystore /home/glassfish/glassfish/domains/domain1/config/cacerts.jks [-storepass 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. Also, we probably want to grant password-less logins to some users; and so we shall also generate an admin password file (named .asadminpass).

Ensure you are running as user 'glassfish'!!

Start Glassfish
/home/glassfish/bin/asadmin start-domain domain1

Change admin password
/home/glassfish/bin/asadmin change-admin-password
#     Enter admin user name [default: admin]>     [Just press Enter]
#     Enter admin password>         [By default this is blank, so just press Enter]
#     Enter new admin password>     [Must contain at least 8 chars (e.g. 'myAdminPwd')]
#     Enter new admin password again>
# There will now be a new version of '$GLASSFISH_HOME/domains/domain1/config/admin-keyfile'

Store admin password, to enable automatic login to localhost:4848
/home/glassfish/bin/asadmin [--host localhost --port 4848] login
#     Enter admin user name [default: admin]>      [Just press Enter]
#     Enter admin password>                        [e.g. 'myAdminPwd']
#     Login information relevant to admin user name [admin]
#     for host [localhost] and admin port [4848] stored at
#     [/home/glassfish/.asadminpass] successfully.

Stop Glassfish
/home/glassfish/bin/asadmin stop-domain domain1

The file /home/glassfish/.asadminpass is handy: it may be copied to the home directory of the GF administrator, who will then be able to run asadmin without entering the password. After copying the file to the home directory of some GF administrator, ensure it is owned that user: chown gf_admin:glassfish ~gf_admin/.asadminpass. The group ownership for this file is irrelevant, and its permissions should obviously be limited to rw-------.

Certificates

Glassfish comes with two pre-configured server certificates that can be used for SSL (i.e. for the https: protocol). They are contained in keystore.jks, and have the aliases s1as and glassfish-instance. However this means that everybody knows these two certificates: the public keys, private keys, etc., so anyone can capture and read data sent to Glassfish even via https. Accordingly, be sure to replace the pre-configured s1as and glassfish-instance entries in your keystore.

The following code box shows you the commands needed for modifying our Glassfish keystores. We first update and extend keystore.jks. We then generate new certificates for s1as and glassfish-instance and import them into cacerts.jks — the 'truststore' used by SSL. The latter keystore contains a large number of trusted certificates, as well as our two newly-minted certificates. See elsewhere for how to obtain certificates from trusted sources, and add them to cacerts.jks.

# Ensure you are running as user 'glassfish'!!

Inspect keystore.jks
cd /home/glassfish/glassfish/domains/domain1/config/
$AS_JAVA/bin/keytool -list -keystore keystore.jks -storepass myMasterPwd

Update keystore.jks
$AS_JAVA/bin/keytool -delete -alias s1as               -keystore keystore.jks -storepass myMasterPwd
$AS_JAVA/bin/keytool -delete -alias glassfish-instance -keystore keystore.jks -storepass myMasterPwd
$AS_JAVA/bin/keytool -genkeypair -alias s1as               -dname "CN=someOne,OU=someUnit,O=someOrg,L=someCity,S=someState,C=XX" -keyalg RSA -keysize 2048 -validity 3650 -keystore keystore.jks -keypass myMasterPwd -storepass myMasterPwd
$AS_JAVA/bin/keytool -genkeypair -alias glassfish-instance -dname "CN=someOne,OU=someUnit,O=someOrg,L=someCity,S=someState,C=XX" -keyalg RSA -keysize 2048 -validity 3650 -keystore keystore.jks -keypass myMasterPwd -storepass myMasterPwd

Check keystore.jks
$AS_JAVA/bin/keytool -list -keystore keystore.jks -storepass myMasterPwd

Export certificates from keystore.jks
$AS_JAVA/bin/keytool -export -alias s1as               -file s1as.cert               -keystore keystore.jks -storepass myMasterPwd
$AS_JAVA/bin/keytool -export -alias glassfish-instance -file glassfish-instance.cert -keystore keystore.jks -storepass myMasterPwd

Update cacerts.jks
$AS_JAVA/bin/keytool -delete -alias s1as                                             -keystore cacerts.jks -storepass myMasterPwd
$AS_JAVA/bin/keytool -delete -alias glassfish-instance                               -keystore cacerts.jks -storepass myMasterPwd
$AS_JAVA/bin/keytool -import -alias s1as               -file s1as.cert               -keystore cacerts.jks -storepass myMasterPwd
$AS_JAVA/bin/keytool -import -alias glassfish-instance -file glassfish-instance.cert -keystore cacerts.jks -storepass myMasterPwd

Check and tidy up
$AS_JAVA/bin/keytool -list -keystore cacerts.jks -storepass myMasterPwd
rm s1as.cert glassfish-instance.cert

What do these two similar-sounding keystores do? They are indeed similar, but are used in a complementary way:

JVM Options and Obfuscations

Now we want to enable https for the admin console. Once we have done that we can be sure that nobody can decrypt data sent via https, since nobody else has our certificate. But this is not all we want to do here: we also want to change some of the default JVM Options, and we want to make our Glassfish not reveal too much about itself ('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 configuration changes so far are optional. But adding -Dproduct.name= is a good idea for everyone. If you don't, then each http/https response will contain a revealing header like: Server: GlassFish Server Open Source Edition 3.1

Similarly, 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). We can disable sending 'x-powered-by' in the http/https headers with the last three asadmin commands in the code box below. Now our Glassfish is working in silent mode. Glassfish obfuscation accomplished.

Ensure you are running as user 'glassfish'!!

# 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

List current JVM options
/home/glassfish/bin/asadmin list-jvm-options

Change JVM Options
# Glassfish 3.1.1 and earlier....
# Now update some important JVM settings.   (Adding '--' is a workaround for
# bugs #16037 and #16770, which cause certain options to be misinterpreted.
# The bug is largely fixed in GlassFish 3.1.1.)
/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

# Glassfish 3.1.2 and later....
# Now update some important JVM settings.  (Inclusion of '--secure=false'
# is due to lingering issues when interpreting the string '-server'.)
/home/glassfish/bin/asadmin delete-jvm-options -client
/home/glassfish/bin/asadmin --secure=false 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?  (Confirm trust, when prompted.)
/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

# Show something other than default error pages (which tend to
# be rather too revealing....).  In the case of wrong URLs:
# 1 It is possible to create 404 error pages that are application-specific
#   by editing that application's web.xml file, and adding a
#   element like
#   <error-page>
#       <error-code>404</error-code>
#       <location>/404.html</location>
#   </error-page>
#
# 2a It is possible to create 404 error pages that are global to the server
#    by editing the server's domain.xml file, and adding a property having
#    name="send-error_1" 
#    value="code=404 path=/tmp/404.html reason=Resource_not_found"
# 2b Or by executing a command like
#       asadmin set server.http-service.virtual-server.server.property.send-error_1="code=404 path=/tmp/404.html reason=Resource_not_found"
# 2c Or by using the admin console to add a new property 'send-error_1'
#    with a value "code=404 path=/tmp/404.html reason=Resource_not_found"

We are done with user 'glassfish'.
exit

Here is a telnet session that shows that the line "Server: GlassFish Server 3.1.1" has been successfully eliminated from the HTTP response header

$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
HEAD /index.html HTTP/1.1
Host: localhost
Connection: close

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 4759
Date: Fri, 01 Jun 2012 13:44:05 GMT
Connection: close

Connection closed by foreign host.
$ 

The Release Notes for Glassfish 3.1 say that debugging JPA is aided by adding the line
   org.eclipse.persistence.session.level=INFO
to /home/glassfish/glassfish/domains/domain1/config/logging.properties. This line is included by default in 3.1.1+.

If we want to remove these security measures, start Glassfish, become user 'glassfish' (although this is unnecessary if you have the .asadminpass file), and enter:

#        Undo:
# Disable https for remote access to admin console
/home/glassfish/bin/asadmin set server-config.network-config.protocols.protocol.admin-listener.security-enabled=false
/home/glassfish/bin/asadmin disable-secure-admin

# Restore default JVM Options
/home/glassfish/bin/asadmin delete-jvm-options -- -server
/home/glassfish/bin/asadmin create-jvm-options -- -client
/home/glassfish/bin/asadmin delete-jvm-options -- -Xmx2048m
/home/glassfish/bin/asadmin create-jvm-options -- -Xmx512m
/home/glassfish/bin/asadmin delete-jvm-options -- -Xms1024m
/home/glassfish/bin/asadmin delete-jvm-options -Dproduct.name=

# Restore 'x-powered-by' in http header
/home/glassfish/bin/asadmin get server.network-config.protocols.protocol.*.xpowered-by
/home/glassfish/bin/asadmin set server.network-config.protocols.protocol.http-listener-1.http.xpowered-by=true
/home/glassfish/bin/asadmin set server.network-config.protocols.protocol.http-listener-2.http.xpowered-by=true
/home/glassfish/bin/asadmin set server.network-config.protocols.protocol.admin-listener.http.xpowered-by=true

7. Maintaining Glassfish

Finally: we have installed, secured and configured our Glassfish installation. Now it has to be managed …

Starting and stopping Glassfish and Derby
# Any sudoer can do this, and the services will be owned by user 'glassfish'
sudo /etc/init.d/glassfish [start | stop | restart | status]

Monitor logs.  Any user can view the logs.
less +F /home/glassfish/glassfish/domains/domain1/logs/server.log
less +F /home/glassfish/glassfish/databases/derby.log

Explore asadmin, doing so here as user 'glassfish'
sudo su --shell /bin/bash glassfish
export AS_JAVA=/usr/java/jdk1.7.0_15
/home/glassfish/bin/asadmin list-commands
exit

Test of the administrator's group membership, $PATH and copy of .asadminpass
asadmin list-commands
asadmin list-applications
asadmin list-jvm-options  To see all system properties: sudo jinfo PID_of_GF

Updates (preliminary notes only).
# If Glassfish was installed from a zip, then updatetool and pkg exist only
# as stubs initially -- however the missing bits will be downloaded and 
# installed when the stubs are first run.  If Glassfish was installed
# from a self-extracting executable, then updatetool and pkg will already
# be fully installed.
# See also the Glassfish Runtime Administration Guide at 
# http://www.oracle.com/technetwork/middleware/glassfish/documentation/index.html

# Notes regarding 'pkg'
# The man page is accessible via:
man -M $GLASSFISH_PARENT/pkg/man/ pkg
# With Glassfish 3.1 I was unable to run pkg when behind a proxy.
# This problem went away with Glassfish 3.1.1

# Note regarding 'updatetool'
# It is hard to manage permissions when we need to be the user 'glassfish' 
# to create files; yet we must be a regular user to be able to access the 
# X11 server.  A solution is to grant 'glassfish' access to X11 before 
# running updatetool.  This is done with the 'xhost' command.  See below
# for an example.

Before updating, we must halt GlassFish and Derby
sudo /etc/init.d/glassfish stop

# 20110808, running 'pkg', the text-based updater
sudo su --shell /bin/bash glassfish
export AS_JAVA=/usr/java/jdk1.7.0_15
export PATH=$PATH:$AS_JAVA/bin
/home/glassfish/bin/pkg -R /home/glassfish [list | info | history]
/home/glassfish/bin/pkg -R /home/glassfish image-update -v
exit

# 20110808, running 'updatetool', the GUI-based updater
xhost +SI:localuser:glassfish   # Run this first, as yourself, not as user 'glassfish'
sudo su --shell /bin/bash glassfish
export AS_JAVA=/usr/java/jdk1.7.0_15
export PATH=$PATH:$AS_JAVA/bin
/home/glassfish/bin/updatetool
exit
xhost -SI:localuser:glassfish   # Run this last, as yourself, not as user 'glassfish'

Restart Glassfish and Derby
sudo /etc/init.d/glassfish start

Backing-up can be done crudely by saving everything under /home/glassfish/ (including raw database files) — or it could be done more selectively. In the latter case, the crucial backups are:

Click here How to access a Derby DB with ij or DBVis

Brief instructions for fronting Glassfish with an Apache server are available at http://weblogs.java.net/blog/amyroh/archive/2012/02/15/running-glassfish-312-apache-http-server

Your installation contains more information, such as $GLASSFISH_HOME/docs/quickstart.html, and there is more at http://download.oracle.com/javaee/.

8. Programming for Glassfish

There are several options for progamming environments: Eclipse, NetBeans, and Emacs (of course). Users of Eclipse might like to check this introductory tutorial: http://glassfishplugins.java.net/eclipse36/, which describes how to deploy and debug a servlet from within version 3.6 (aka 'helios') of Eclipse.

Fancy environments have their appeal, however programming web apps is not so very different from desktop apps. Indeed there are only two configuration-related things that a programmer needs to know in order to build and deploy Java EE web apps:

  1. /home/glassfish/glassfish/modules/ This is where all the Java EE jar files are located.
  2. /home/glassfish/glassfish/domains/domain1/autodeploy/ This is the place to drop your .war file.

Appendix: Private Glassfish installation

Here is a sketch of what to do for a private installation. This may be preferable for program developers, as it simplifies some testing mechanisms. You don't want authenication problems when Maven is managing integration tests.

The general plan is to unpack the Glassfish distro in your personal directory space, and to start and stop the server manually. In this example we choose to place Glassfish in $HOME/glassfish, and to advertise this by setting environment variables appropriately.

Glassfish
export GLASSFISH_PARENT=$HOME/glassfish3
export GLASSFISH_HOME=$HOME/glassfish3/glassfish
echo $PATH | /bin/grep -q -v $GLASSFISH_HOME/bin
if [ $? -eq 0 ]; then export PATH="${PATH}:$GLASSFISH_HOME/bin"; fi

To download and install Glassfish, follow the instructions above in 3. Downloading and installing Glassfish. The difference is the base directory, and everything to do with user names.

cd ~/Downloads
wget http://dlc.sun.com.edgesuite.net/glassfish/3.1.2.2/release/glassfish-3.1.2.2.zip
unzip glassfish-3.1.2.2.zip
mv glassfish3 ~

Now you can start and stop the server by

asadmin start-domain domain1
asadmin stop-domain domain1
Acknowledgement: Some parts, particularly within Section 6, are borrowed from the tutorial www.nabisoft.com, that appeared in April 2011. This is a clear and frequently-updated installation guide, and is highly recommended.