webmail with jetty and jwma

Version 4.5 of JWMA and a version 17 java runtime require a jakarta aware jetty, so download verson 11. Untar the archive as /opt/jetty; this will be the jetty.home ($JETTY_HOME) directory. The jetty philosophy is that nothing is modified in this home directory; I more or less go along with this except that I create /opt/jetty/base for the reasons of keeping things together. This will become jetty.base ($JETTY_BASE), where all configuration changes are made and from where all commands are run. To make this so, add a couple of lines to ~/.bashrc:

export JETTY_HOME=/opt/jetty
export JETTY_BASE=$JETTY_HOME/base
You'll need to log out and back in again for these settings to take effect.

Next job is to create directory $JETTY_BASE/webapps and $JETTY_BASE/webapps/webmail. I then extract the contents of the webmail.war file into this last directory. Reason for this is that left to itself, jetty would decompress the war file into /tmp and run from there. That's not the place where we want jwma to create it's .jwma directory.

Before we start jetty we need to add some modules; as always the command is run from within our jetty.base directory:

david@bulawayo:/opt/jetty/base $ java -jar $JETTY_HOME/start.jar --add-modules=http,requestlog,deploy,jsp
INFO  : mkdir ${jetty.base}/start.d
INFO  : webapp          transitively enabled, ini template available with --add-module=webapp
INFO  : server          transitively enabled, ini template available with --add-module=server
INFO  : requestlog      initialized in ${jetty.base}/start.d/requestlog.ini
INFO  : servlet         transitively enabled
INFO  : jsp             initialized in ${jetty.base}/start.d/jsp.ini
INFO  : resources       transitively enabled
INFO  : annotations     transitively enabled
INFO  : threadpool      transitively enabled, ini template available with --add-module=threadpool
INFO  : plus            transitively enabled
INFO  : deploy          initialized in ${jetty.base}/start.d/deploy.ini
INFO  : logging-jetty   transitively enabled
INFO  : security        transitively enabled
INFO  : apache-jsp      transitively enabled
INFO  : jndi            transitively enabled
INFO  : http            initialized in ${jetty.base}/start.d/http.ini
INFO  : logging/slf4j   transitive provider of logging/slf4j for logging-jetty
INFO  : logging/slf4j   dynamic dependency of logging-jetty
INFO  : bytebufferpool  transitively enabled, ini template available with --add-module=bytebufferpool
INFO  : mkdir ${jetty.base}/logs
INFO  : mkdir ${jetty.base}/resources
INFO  : copy ${jetty.home}/modules/logging/jetty/resources/jetty-logging.properties to ${jetty.base}/resources/jetty-logging.properties
INFO  : Base directory was modified
We can now start jetty with:
david@bulawayo:/opt/jetty/base $ java -jar $JETTY_HOME/start.jar
The jwma login screen will be available at http://localhost:8080/webmail and as you log in /opt/jetty/base/.jwma will be created along with the jwma configs, log files and directories.

adding https

In production use we'll want to have https enabled to avoid the risk of login details being sniffed. A complication to consider is how the certificate will be provided. Documentation here tells how to do it with letsencrypt (the https setup is a bit out of date), but it sounds like a royal pain. For a webmail site, with presumably only a handful of users at most, a self-signed certificate may fit the bill?

At least for initial testing we can use jetty's built in test keystore. Stop the jetty server and add additional modules:

david@bulawayo:/opt/jetty/base $ java -jar $JETTY_HOME/start.jar --add-modules=ssl,https,test-keystore
INFO  : https           initialized in ${jetty.base}/start.d/https.ini
INFO  : ssl             initialized in ${jetty.base}/start.d/ssl.ini
INFO  : test-keystore   initialized in ${jetty.base}/start.d/test-keystore.ini
INFO  : mkdir ${jetty.base}/lib/bouncycastle
INFO  : download https://repo1.maven.org/maven2/org/bouncycastle/bcpkix-jdk15to18/1.76/bcpkix-jdk15to18-1.76.jar to ${jetty.base}/lib/bouncycastle/bcpkix-jdk15to18-1.76.jar
INFO  : download https://repo1.maven.org/maven2/org/bouncycastle/bcprov-jdk15to18/1.76/bcprov-jdk15to18-1.76.jar to ${jetty.base}/lib/bouncycastle/bcprov-jdk15to18-1.76.jar
INFO  : download https://repo1.maven.org/maven2/org/bouncycastle/bcutil-jdk15to18/1.76/bcutil-jdk15to18-1.76.jar to ${jetty.base}/lib/bouncycastle/bcutil-jdk15to18-1.76.jar
INFO  : Base directory was modified
After a restart of jetty, jwma will be additionally available over https at https://localhost:8443/webmail You will of course have to click through a browser warning, but maybe that can just be configured to go away when there are only a few legitimate users of your webmail service.

While still testing locally, but to demonstrate how this would work in a production setting, create $JETTY_BASE/etc and add a file jetty-ssl-context.xml there with following content.

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">

<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory$Server">
    <Set name="KeyStorePath"<etc/keystore</Set>
    <Set name="KeyStorePassword"<changeit</Set>
</Configure>
Also from the $JETTY_BASE/etc directory (thus breaking a rule!), we'll use the keytool command to demonstrate a possible permanent solution:
david@bulawayo:/opt/jetty/base/etc $ keytool -genkeypair -alias jwma -validity 100 -keyalg RSA -keysize 2048 -keystore keystore -storetype pkcs12 -dname "CN=localhost, OU=Unit, O=Company, L=City, S=State, C=Country"
Enter keystore password:  
Re-enter new password: 
Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 100 days
	for: CN=localhost, OU=Unit, O=Company, L=City, ST=State, C=Country
The password must match that specified in jetty-ssl-context.xml and CN=localhost (from the -dname arg, and that one only) is also important. The certificate created in the keystore is for local testing only. In production you would replace it with CN=mydomain.com or whatever domain is hosting jwma.

We can now remove the test-keystore module, by removing $JETTY_BASE/start.d/test-keystore.ini and also remove the bouncycastle directory that was downloaded into $JETTY_BASE/lib (but leave the lib diretory), restart jetty and again check our https access to webmail.

adding derby support

So far all testing has been using serialization to save user preferences and contact lists, but saving them to a derby database, or indeed other databases also, is an option. Here I'm dealing only with steps specfic to jetty to enable derby storage for jwma users. For essential further details, configuring jwma to use derby, see the jwma page at sourceforge or look in jwma's doc/ directory.

Create an additional directory, $JETTY_BASE/lib/ext and copy the derby jar file in jwma's database directory there. We just need to add an additional module before we restart jetty:

david@bulawayo:/opt/jetty/base $ java -jar $JETTY_HOME/start.jar --add-modules=ext
INFO  : ext             initialized in ${jetty.base}/start.d/ext.ini
INFO  : Base directory was modified