Overview
Ubuntu 14.04 (Trusty Tahr) shipped with Jetty 8. You might want to use the latest version of Jetty which is Jetty 9.
Jetty 9 already shipped in Ubuntu 16.04 (Xenial Xerus) but you might still need to use Ubuntu 14.04 on your environment but at the same time you want to use.
Jetty 9 Features
Jetty 9 initial stable version was relased on 2012. Several main features that it shipped with :
- Supports next generation protocol like SPDY, WebSockets, MUX and HTTP/2 are supported equals to HTTP/1.1
- Content push both in client and server
- Improved WebSocket Server and Client
- Java 7 support that take advantage of improved APIs in the JVM regarding concurrrency and nio.
- Ready for Servlet 3.1
- Asynchronous HTTP Client
- Pluggable Modules
- Improved SSL support
- Lightweight in size that enable Jetty to serve tens’s of thousands of connection with very small memory footprints.
- Embeddable in our application so we can just run our application as standalone application.
Jetty 9.3 Features
- HTTP2 support
- Application Layer Protocol Negotiation
- Server Name Indication (SNI) support for TLS/SSL negotiation. This enables jetty to use certificates with one main domain add multiple Subject Alternate Name.
- Targeted for Java 8. This change is due to the SNI extension on Java 8 API and HTTP specification need for TLS ciphers that are only available in Java 8.
In this tutorial we’ll learn how-to install and configure Jetty 9 on Ubuntu 14.04.
Prerequisites
This tutorial assumes that we have clean install of Ubuntu Server 14.04. We will update the OS to the latest version before installing the Jetty 9 prerequisites and Jetty 9 itself.
Update Base OS
The first step that we need to do is updating the system to latest update. We can do that using command below:
$ sudo apt-get update
$ sudo apt-get upgrade
Install Oracle JDK 8
Now, let’s install Java Development Kit 8. We will use Oracle JDK instead of OpenJDK version of JDK 8.
Add the webupd8team
ppa repository :
$ sudo add-apt-repository ppa:webupd8team/java
...
Press [ENTER] to continue or ctrl-c to cancel adding it
gpg: keyring `/tmp/tmpfkhyecrx/secring.gpg' created
gpg: keyring `/tmp/tmpfkhyecrx/pubring.gpg' created
gpg: requesting key EEA14886 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpfkhyecrx/trustdb.gpg: trustdb created
gpg: key EEA14886: public key "Launchpad VLC" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg: imported: 1 (RSA: 1)
OK
We need to press enter
to continue adding the webupd8team PPA repository. The output above is truncated to show only the important part.
Let’s apt-get download and read metadata of the new repository that we just added:
$ sudo apt-get update
Install JDK 8.
$ sudo apt-get -y install oracle-java8-installer
the -y
option above will make you agree automatically with packages to be installed including dependencies.
If you want to check what packages will be installed you can remove the -y
option above.
Package configuration. Choose OK
HP_NO_IMG/data/uploads/users/06ec5e3c-c6e5-4649-b1e7-35579de65459/1815272966.png” alt=”” />
Accepting Oracle Binary Code Lisence Terms. Choose Yes
HP_NO_IMG/data/uploads/users/06ec5e3c-c6e5-4649-b1e7-35579de65459/10630431.png” alt=”” />
After installing Java 8, you can check the current java version by running command below :
$ java -version
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)
We confirmed that we already have JDK 8 installed.
Install Jetty 9
In this tutorial we will install Jetty 9.3, we can get the latest version of jetty from the Jetty download page
Download Jetty 9.3.12 package:
$ wget -c http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.12.v20160915/jetty-distribution-9.3.12.v20160915.tar.gz
Extract the Jetty package:
$ tar xzf jetty-distribution-9.3.12.v20160915.tar.gz
Rename the directory to jetty
and move it to /opt
:
$ mv jetty-distribution-9.3.12.v20160915 jetty9
$ sudo mv jetty9 /opt
We will create a user and group named jetty that will be used to run Jetty. Create the group first:
$ sudo addgroup --quiet --system jetty
Create the jetty
system user.
$ sudo adduser --quiet --system --ingroup jetty --no-create-home --disabled-password jetty
Modify the /etc/passwd
entry to change home and group for jetty
user.
$ sudo usermod -c "Jetty 9" -d /opt/jetty9 -g jetty jetty
Change ownership of /opt/jetty9
directory to user jetty
and group jetty
.
$ sudo chown -R jetty:jetty /opt/jetty9
Change the permission of /opt/jetty9
directory.
$ sudo chmod u=rwx,g=rxs,o= /opt/jetty9
Configure Jetty 9
Create logs directory
We need to create directory for Jetty 9 to store logs:
$ sudo mkdir /var/log/jetty9
And change the ownership of the newly created directory to user jetty
and group jetty
:
$ sudo chown -R jetty:jetty /var/log/jetty
Create a Default Configuration File for Jetty
We will create a default configuration file for jetty. This file will be read by jetty
init script and also the crontab script. Create a new file /etc/default/jetty9
with content below:
# change to 1 to prevent Jetty from starting
NO_START=0
# change to 'no' or uncomment to use the default setting in /etc/default/rcS
VERBOSE=yes
# Run Jetty as this user ID (default: jetty)
# Set this to an empty string to prevent Jetty from starting automatically
JETTY_USER=jetty
# The home directory of the Java Runtime Environment (JRE). You need at least
# Java 6. If JAVA_HOME is not set, some common directories for OpenJDK and
# the Oracle JDK are tried.
#JAVA_HOME=
# Extra options to pass to the JVM
#JAVA_OPTIONS="-Xmx256m -Djava.awt.headless=true"
# Timeout in seconds for the shutdown of all webapps
#JETTY_SHUTDOWN=30
# Additional arguments to pass to Jetty
#JETTY_ARGS=
# Jetty uses a directory to store temporary files like unpacked webapps
#JETTY_TMP=/var/cache/jetty9
JETTY_HOME=/opt/jetty9
JETTY_LOGS=/var/log/jetty9
# Default for number of days to keep old log files in /var/log/jetty9/
#LOGFILE_DAYS=14
# If you run Jetty on port numbers that are all higher than 1023, then you
# do not need authbind. It is used for binding Jetty to lower port numbers.
# (yes/no, default: no)
#AUTHBIND=yes
Log Files Cron
Now, let’s create the crontab configuration file that will rotate log jetty9 log files. Create a new file on /etc/cron.daily/jetty9
with content below:
#!/bin/sh
NAME=jetty9
DEFAULT=/etc/default/$NAME
# The following variables can be overwritten in $DEFAULT
# Default for number of days to keep old log files in /var/log/jetty/
LOGFILE_DAYS=14
# End of variables that can be overwritten in $DEFAULT
# overwrite settings from default file
if [ -f "$DEFAULT" ]; then
. "$DEFAULT"
fi
if [ -d /var/log/$NAME ]; then
find /var/log/$NAME/ -name *.log -mtime +$LOGFILE_DAYS -print0
| xargs --no-run-if-empty -0 rm --
fi
Create an Init Script to Manage Jetty9 Service
The Jetty package comes with an init script. It’s located in the bin directory with the name jetty.sh. We will create the init script to manage Jetty 9 service by creating symlink to that file.
$ sudo ln -sf /opt/jetty9/bin/jetty.sh /etc/init.d/jetty9
Make Jetty 9 Start on Boot
We’ll make sure Jetty 9 running automatically on boot using update-rc.d
.
$ sudo update-rc.d jetty9 defaults
update-rc.d: warning: /etc/init.d/jetty9 missing LSB information
update-rc.d: see
Adding system startup for /etc/init.d/jetty9 ...
/etc/rc0.d/K20jetty9 -> ../init.d/jetty9
/etc/rc1.d/K20jetty9 -> ../init.d/jetty9
/etc/rc6.d/K20jetty9 -> ../init.d/jetty9
/etc/rc2.d/S20jetty9 -> ../init.d/jetty9
/etc/rc3.d/S20jetty9 -> ../init.d/jetty9
/etc/rc4.d/S20jetty9 -> ../init.d/jetty9
/etc/rc5.d/S20jetty9 -> ../init.d/jetty9
Managing the Jetty 9 Service
Now Jetty 9 is ready. Let’s check jetty 9’s service status:
$ sudo service jetty9 status
Jetty NOT running
START_INI = /opt/jetty9/start.ini
START_D = /opt/jetty9/start.d
JETTY_HOME = /opt/jetty9
JETTY_BASE = /opt/jetty9
JETTY_CONF = /opt/jetty9/etc/jetty.conf
JETTY_PID = /var/run/jetty9.pid
JETTY_START = /opt/jetty9/start.jar
JETTY_LOGS = /opt/jetty9/logs
JETTY_STATE = /opt/jetty9/jetty9.state
CLASSPATH =
JAVA = /usr/bin/java
JAVA_OPTIONS = -Djetty.logging.dir=/opt/jetty9/logs -Djetty.home=/opt/jetty9 -Djetty.base=/opt/jetty9 -Djava.io.tmpdir=/tmp
JETTY_ARGS = jetty.state=/opt/jetty9/jetty9.state jetty-logging.xml jetty-started.xml
RUN_CMD = /usr/bin/java -Djetty.logging.dir=/opt/jetty9/logs -Djetty.home=/opt/jetty9 -Djetty.base=/opt/jetty9 -Djava.io.tmpdir=/tmp -jar /opt/jetty9/start.jar jetty.state=/opt/jetty9/jetty9.state jetty-logging.xml jetty-started.xml
The output above showed that the Jetty 9 process is not running, let’s start Jetty 9 using command below:
$ sudo service jetty9 start
Starting Jetty: OK Tue Oct 25 23:56:08 UTC 2016
When we check Jetty 9’s status after starting it shows that Jetty is running. It also show the pid
of Jetty 9
$ sudo service jetty9 status
Jetty running pid=21768
...
We can also check whether the Jetty process is running or not using netstat
by listing all listening ports on the server.
$ sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1365/sshd
tcp6 0 0 :::8080 :::* LISTEN 21768/java
tcp6 0 0 :::22 :::* LISTEN 1365/sshd
The output above shows that there is a java process that is listening on port 8080
, this is Jetty’s default port.
Now point your browser to http://:8080
HP_NO_IMG/data/uploads/users/06ec5e3c-c6e5-4649-b1e7-35579de65459/480901193.png” alt=”” />
Deploying Applications
Deploying applications on Jetty 9 is easy. We only have to copy the .war
file to webapps
directory. This directory is scanned by Jetty and it will run the files available in that directory.
The sample applications is located at /opt/jetty9/demo-base/webapps/
. We will copy async-rest
sample to the webapps directory.
sudo cp /opt/jetty9/demo-base/webapps/async-rest.war /opt/jetty9/webapps/
The Jetty log files are rotated daily. The log file name format is YYYY_MM_DD.stderrout.log
and is located at /var/log/jetty9
. After copying the sample we will see similar output like below that show the async-rest sample is deployed.
2016-11-01 20:51:26.554:WARN::Scanner-0: async-rest webapp is deployed. DO NOT USE IN PRODUCTION!
2016-11-01 20:51:26.730:INFO:oejsh.ContextHandler:Scanner-0: Started o.e.j.w.WebAppContext@5bd204cd{/async-rest,[file:///tmp/jetty-0.0.0.0-8080-async-rest.war-_async-rest-any-4799009764757275722.dir/webapp/, jar:file:///tmp/jetty-0.0.0.0-8080-async-rest.war-_async-rest-any-4799009764757275722.dir/webapp/WEB-INF/lib/example-async-rest-jar-9.3.12.v20160915.jar!/META-INF/resources],AVAILABLE}{/async-rest.war}
When we open Jetty it will show that there is one application deployed. We can click on the link. The app also available on http://server-address:8080/async-rest
, so the file name will be directory name on the url
HP_NO_IMG/data/uploads/users/06ec5e3c-c6e5-4649-b1e7-35579de65459/397508108.png” alt=”” />
When we click the application the async-rest sample will be shown.
HP_NO_IMG/data/uploads/users/06ec5e3c-c6e5-4649-b1e7-35579de65459/1280541191.png” alt=”” />
Removing Applications
Removing applications is also easy, we just have to remove the .war
file from webapps directory. Let’s remove the sample async-rest.war
that we just deploy.
$ sudo rm -f /opt/jetty9/webapps/async-rest.war
On the log file we will see that the application is stopped by Jetty:
2016-11-01 20:49:35.640:INFO:oejsh.ContextHandler:Scanner-0: Stopped o.e.j.w.WebAppContext@3c9d0b9d{/async-rest,null,UNAVAILABLE}{/async-rest.war}
Using Nginx as a Reverse Proxy for Jetty 9
We will install Nginx and use it as reverse proxy for Jetty 9. In this setup we will forward requests that come to Nginx to Jetty 9 on the same machine but we can also use Nginx to forward request to another machines and load balance the request.
We will also use Nginx to serve site on https mode so the SSL connection from client to server will be handled by Nginx.
Install Nginx
We will install Nginx from nginx.org repository instead of from ubuntu repository. The reason is that the nginx.org repository provides a newer version of nginx so we can get the latest and also secure version of Nginx.
First of all let’s add Nginx.org package signing key. We have to add this key so apt can verify that the packages that we download from nginx repository is not tampered on the way to our server.
$ wget -c -O- http://nginx.org/keys/nginx_signing.key | sudo apt-key add -
Add nginx.org Repository:
$ echo "deb http://nginx.org/packages/ubuntu/ trusty nginx" | sudo tee -a /etc/apt/sources.list.d/nginx.list > /dev/null
Update apt metadata so that it know the contents of Nginx.org repository and install Nginx.
$ sudo apt-get update
$ sudo apt-get -y install nginx
Now we have nginx installed, we can check it by checking the status of the service :
$ sudo service nginx status
Configure Nginx Sites For Jetty 9 Nexus
In this section we’ll learn how to configure Nginx to serve as http only proxy and https only proxy.
The configuration directory structure created by nginx package from nginx.org
repository is a little bit different with configuration of Nginx package from Ubuntu repository.
We will reconfigure Nginx configuration directory to make it easier to enable and disable site configuration.
Create two new directories named sites-available
and sites-enabled
with commands below:
$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled
open /etc/nginx/nginx.conf
find line:
include /etc/nginx/conf.d/*.conf;
replace with:
include /etc/nginx/sites-enabled/*.conf;
Remove contents of /etc/nginx/conf.d
$ sudo rm -f /etc/nginx/conf.d/*
Now we are ready to configure Jetty 9 site.
HTTP Only Configuration
Create the file /etc/nginx/sites-available/jetty-http.conf
with the contents below. You need to change the server_name
line below with the domain name that you plan to use for Jetty 9.
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name jetty9.exampleserver.xyz;
root /usr/share/nginx/jetty9;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
proxy_pass http://localhost:8080;
}
}
Enable configuration by creating asymbolic link:
$ sudo ln -sf /etc/nginx/sites-available/jetty-http.conf /etc/nginx/sites-enabled/jetty-http.conf
Now reload Nginx:
$ sudo service nginx reload
Nginx is ready to work as reverse proxy. You can now open http://<server address/
. This time without Jetty port (8080
) since Nginx already listen on port 80 and forward the request to Jetty.
HTTPS Only Configuration
If you already follow the configuration above you can skip this section, but if you want to serve jetty only via https you can follow this section.
The configuration below will make Nginx serve both on http port and https port. When a request comes to http port it will be redirected to https port.
We assume that you already have an ssl certificate and the private key pair. When using this configuration you need to change server_name
, ssl_certificate
and ssl_certificate_key
lines below.
Before creating the configuration file. Let's create a new folder to put ssl certificate.
$ sudo mkdir /etc/nginx/ssl
Create a new configuration file /etc/nginx/sites-available/jetty-ssl.conf
with contents below:
server {
listen 80 default_server;
listen [::]:80 default_server;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name jetty9.exampleserver.xyz;
root /usr/share/nginx/jetty9;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /etc/nginx/ssl/jetty9.exampleserver.xyz.crt;
ssl_certificate_key /etc/nginx/ssl/jetty9.exampleserver.xyz.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
location / {
proxy_pass http://localhost:8080;
}
}
Enable the site by creating symbolic link using command below:
$ sudo ln -sf /etc/nginx/sites-available/jetty-ssl.conf /etc/nginx/sites-enabled/jetty-ssl.conf
If you already follow the http section above you need to disable the site by removing the symbolic link.
$ sudo rm -f /etc/nginx/sites-enabled/jetty-http.conf
Test the Nginx configuration using comand below:
$ sudo service nginx configtest
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
If the output is different to the above, Nginx will show an error message and show which file and line of the configuration is not correct.
Reload Nginx configuration using command below:
$ sudo service nginx reload
Summary
In this tutorial we have learned how to install and configure Jetty 9 on ubuntu 14.04 Trusty Tahr. We also learned how to configure Jetty 9 and also using Nginx as reverse proxy for Jetty 9.