This document introduces how to configure SSL/TLS on Jetty in a practical way - from creating key and certificate.
Installation of Jetty
Prerequisites
Jetty is a web server and servlet engine running on JVM.
Therefore, the assumption is that you already installed JDK on your machine.
I tested w/ Oracle JDK 1.8 on Mac and CentOS. (The results are the same.)
$ java -version java version "1.8.0_161" Java(TM) SE Runtime Environment (build 1.8.0_161-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode) | cs |
Download
You can download tarball (or zip file) of every version of Jetty distribution from the following link.
Here is the list of versions I tested.
jetty-distribution-9.2.11.v20150529
jetty-distribution-9.3.15.v20161220
jetty-distribution-9.4.8.v20171121
The installation is untar (or unzip) the file into a certain directory.
I put the 3 different version of Jetty in ~/Work/apps/jetty and make a symlink of "current" as changing the versions.
Simple Test
Before applying SSL/TLS, you can test Jetty up and running as following.
$ cd $JETTY_HOME $ java -jar ./start.jar 2018-03-06 11:52:26.186:INFO::main: Logging initialized @355ms 2018-03-06 11:52:26.242:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended. See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html 2018-03-06 11:52:26.391:INFO:oejs.Server:main: jetty-9.3.15.v20161220 2018-03-06 11:52:26.410:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/webapps/] at interval 1 2018-03-06 11:52:26.431:INFO:oejs.AbstractConnector:main: Started ServerConnector@210c9d62{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} 2018-03-06 11:52:26.650:INFO:oejs.Server:main: Started @820ms | cs |
Then, you can access the Jetty web server on your browser w/ "http://localhost:8080".
Error 404 is not an error actually - You have not deployed any webapps, that's why.

You can run and stop by using a script Jetty provides as following.
This enables Jetty running as a daemon as keeping the logs in a directory.
$ cd $JETTY_HOME $ ./bin/jetty.sh start Starting Jetty: 2018-03-06 11:59:20.067:INFO::main: Logging initialized @636ms 2018-03-06 11:59:20.124:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended. See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html 2018-03-06 11:59:20.332:INFO::main: Redirecting stderr/stdout to /Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/logs/2018_03_06.stderrout.log OK Tue Mar 6 11:59:23 MST 2018 $ ./bin/jetty.sh stop Stopping Jetty: OK | cs |
Creating Certificate
Note that this step introduces how to create a self signed certificate.
If you have an official certificate, you can bypass this section.
There are a few ways to create SSL key and certificates.
In general, OpenSSL and keytool are most popular tools for it.
It does not matter which way you choose. In this document, most procedures are based on openssl, except for creating keystore file.
SSL Key
Note that the pass phrase is "jetty123456".
$ openssl genrsa -des3 -out jetty.key Generating RSA private key, 2048 bit long modulus ....................................................................................................................................................+++ ..................................................................................................+++ e is 65537 (0x10001) Enter pass phrase for jetty.key: Verifying - Enter pass phrase for jetty.key: $ cat jetty.key -----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,15CAAF41EEF60FD3 L9eEDkoogWBXdQ3WPZqfY2vxZHWS5nTY1ow853Hpcf+1mhmyxEzb2uxJAuWhRnCI JHMyyZHjnrtzDBLMUEwVZQ4u63yKFs1hidlPgOP5Xr5Rm118Dzpwbka3VOz0nQ86 Oa+7axV3Zg1qH82+Uda11SYrtRDbizSDW3F3ZQvz3AOyu05AuO9Nibdkc9UQ/zWA lMLe2yjbzBLr1NmOIxrsrb7RCcxwtuIGGKeE8o2KalmehJfvNePcAbjnAn+35+7h 1fh5MuDMeUs5POviGzNUYH8e3U/3rhqWH+0Wj7pFvFvBVV9TjrFecdvmXx7MCtBr GP99SpChF94FBPDAu2Nn/o2jBPlHiVeMLyDsD+KJgSAlb42QDVfJYjHcaBcVsOa4 3vugAkg06AYH2MeOIX0SGKSF4ZYktmV48mtyuC1WcKdAnf8Vp18JaynVY/0wczkz 5KwZUGs2Xa3cQ+XYAR4CY8fY7HPjBXJBNxowdVIVi7UqvVz9nhXeFJeFrld0Tmpx TweitNzEx6Ie8W4PFRGAMx4xhfn5UKhmS/hzqrlPDRxMOXOs2XaPTcmwU8+Asy6E QjGJMQmSWWl1IyXikcavHfmAg5eezFv3ZFl67FpObivzTsS3ABh55DAb1Z1fT8GF iYpaq0dyVmQ16Jzi9FAz40IBrh7AeDRE/mBVnjZtH6XnWgrO7nA8QjXlw9863QDF J136UJaqTcVcjM3GwoclNlTLKpZL7/erUL0UIkeySoQnKU+GF7g4UVnPyp0zkEGU aF5sXSWzxwchGapYHefUkUXhF15pGObZ+cIj9ck/sd2OGhOZwAzcJaBvzN+xGzQX +dO5JMUNQpqjnPgCItslqL84NE/vLVJr6bSfPNBzeNaxl4LBXLQGPF1tGdjroZJo JB8lz+fP/9EQiYzzr2ek/UbYKOoMdm1JmcvBAnOCgsUcMzP1mwV6xdcBO00dojwR dJTCKnez4wYLl6kXbkQ3W8fQNT9yliPUG653hrDZWt5pvA1uDEQ61c7W9IXqV+ZN Sa+VmGiosKW1jvKqdCkmUU272RIy119Un9zxW2yQm5OpC5/bPDVbGYZ1wMJPWqga 3HDe54AwKzS9IU50RhK8HVkQcwUwt5Zx3W2t/eukDfnNWa01jRQe3P+VyXbcRvXC PDXR2p9h5j0iubM+9jqTXAmCA8j2PoqqE1UIHXUXlN3FCZb14QN5/NY9KpdY7Oap k3I2kVf35iq4oo5NjrqbKo3ieN0NBWgKeee/GTYaFXBKSbwf1mqCLZf/xxsx7u+G JjVuDRNbrQFqTOkrY4ihenLMFwsVbbjRaQbXVuLXPPjALdEE17dcROx5wiII271o JXNPZjOfPuGkNZeCgUAte5PDyz9rU0A4bJfaJCbuzy34Ksug2qxhnvoZkQ4wh4jE c9uzumP4zMzyw/MtUKfpbneuaxRp9STL8pyX9D22iepCCk7OjsJhgAZRlYgVr17V z4EDH1W7Kh4i17uhBDNWqVex/caNQJWb5AeWs3X043WwSW3TxD9HZwxnOg9mxhXc u2N9opFZ5xBgj1qe0/h1Z4J72BvnEc0864ryWm00mpyUa5YmrVYysQ== -----END RSA PRIVATE KEY----- | cs |
Certificate
$ openssl req -new -x509 -key jetty.key -out jetty.crt Enter pass phrase for jetty.key: You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) []:US State or Province Name (full name) []:Colorado Locality Name (eg, city) []:Englewood Organization Name (eg, company) []:Comcast Organizational Unit Name (eg, section) []:MELD Common Name (eg, fully qualified host name) []:kafka-gw Email Address []:bumjoon_kim@comcast.com $ cat jetty.crt -----BEGIN CERTIFICATE----- MIIDnjCCAoYCCQDo//zRFi9XizANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMC VVMxETAPBgNVBAgMCENvbG9yYWRvMRIwEAYDVQQHDAlFbmdsZXdvb2QxEDAOBgNV BAoMB0NvbWNhc3QxDTALBgNVBAsMBE1FTEQxETAPBgNVBAMMCGthZmthLWd3MSYw JAYJKoZIhvcNAQkBFhdidW1qb29uX2tpbUBjb21jYXN0LmNvbTAeFw0xODAzMDYx NzI3MzlaFw0xODA0MDUxNzI3MzlaMIGQMQswCQYDVQQGEwJVUzERMA8GA1UECAwI Q29sb3JhZG8xEjAQBgNVBAcMCUVuZ2xld29vZDEQMA4GA1UECgwHQ29tY2FzdDEN MAsGA1UECwwETUVMRDERMA8GA1UEAwwIa2Fma2EtZ3cxJjAkBgkqhkiG9w0BCQEW F2J1bWpvb25fa2ltQGNvbWNhc3QuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAwAxkNLhram/mDSPbd4bOyKItSStM2GB4tG1YF+I1N+bvgCoyY+c5 PP1m9GxvhKPCk8upfeTbvgLl/xN2rd101ABS0pIO8tMLU2MNkZXf8AC+QXZm1uAn ThiILLkk41PyLlYw0wulklrqTmnrrJ+0l0pZ8wJus48rdDJ1lIlT7GFgiT1J2fHr wxkwDdfYy5QrES8SK0bH85i1hc4xLBrDrgah2dMTAyxj20H7KnyTgy5m1V5Xs4VC KtKFV+WBaY1Htwzq5RUjD4Rmrw0N2o0K9mRUxi/s8isbn5TB9Q0mjNoxB9ZwQzh+ NTn6IV8NnmSAStQWkDrGTp4xtcKtIY2Z3wIDAQABMA0GCSqGSIb3DQEBCwUAA4IB AQA3bVYBvo82PgQXX/VenktSCa0TycT8aZTk2un9upJl1Db9zq4ZbZqmS8yadxwM lsMSwexFZJ0OHvXK9CLDUzQ11lOxwJng4ejsreeZua4d5o3suI2S+DZ8u9ySGasj zSBLkjh6Cj7G4D8lOPNZhurSLg4Ysl1J+XKcdUnx8Sf6S+RG009iQ8H0Nq1/x9v0 CI8rHvQD+e5heUR0q/z2MuawCK7zP3KOr1BxwAZPBCqzII5mgYB6AwJ6bRNClsD8 5sd/a3Y/Iap+59lRMjvYYFugcNiNAECdIGo5VX1rsJp4DA+WhToVyOO4FaTBQ4ZD Is4y5bUsZh/Gjr+ONK2YfrjF -----END CERTIFICATE----- | cs |
Convert to PKCS12 Format
Note that the export password is the same - "jetty123456".
$ openssl pkcs12 -inkey jetty.key -in jetty.crt -export -out jetty.p12 Enter pass phrase for jetty.key: Enter Export Password: Verifying - Enter Export Password: | cs |
Then, you will get "jetty.p12".
Create keystore
Note that the destination password is also the same - "jetty123456".
$ keytool -importkeystore -srckeystore jetty.p12 -srcstoretype PKCS12 -destkeystore keystore Importing keystore jetty.p12 to keystore... Enter destination keystore password: Re-enter new password: Enter source keystore password: Entry for alias 1 successfully imported. Import command completed: 1 entries successfully imported, 0 entries failed or cancelled Warning: The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using "keytool -importkeystore -srckeystore keystore -destkeystore keystore -deststoretype pkcs12". | cs |
Then, you will have "keystore" file, which will be used for Jetty configuration.
SSL/TLS Configuration on Jetty
Locate keystore
The keystore file generated in previous step should be located to $JETTY_HOME/etc.
(Actually, it can be placed in other locations but $JETTY_HOME/etc/keystore is the default configuration.)
Password Encryption
As mentioned above, "jetty123456" is the only password I used.
It needs to be encrypted before being applied to the configuration.
Here is the example of encrypting the password. Note that "OBF:" will be used for the configuration later.
$ java -cp $JETTY_HOME/lib/jetty-util-9.2.11.v20150529.jar org.eclipse.jetty.util.security.Password jetty123456 2018-03-06 10:33:03.217:INFO::main: Logging initialized @139ms jetty123456 OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz MD5:09919a53fefcbe804d1cb7b807dc4c19 | cs |
Configuration
First, you need to create a directory "start.d" in $JETTY_HOME.
Then, 2 files should be created as following.
$ cd $JETTY_HOME/start.d $ cat https.ini --module=https $ cat ssl.ini jetty.ssl.host=0.0.0.0 jetty.ssl.port=8443 jetty.sslContext.keyStorePath=etc/keystore jetty.sslContext.keyStorePassword=OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz jetty.sslContext.keyManagerPassword=OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz jetty.sslContext.trustStorePassword=OBF:1ktv1jn31mf31m801n0m18jj1mwo1m4e1mbj1jkf1kqz | cs |
As you see above, the encrypted password is used.
You can change the port number of SSL and keystore location.
Test
If you run Jetty with the same command - "java -jar $JETTY_HOME/start.jar", you will see 2 servers running - plain HTTP and HTTPS.
$ java -jar start.jar 2018-03-06 12:27:10.854:INFO::main: Logging initialized @701ms 2018-03-06 12:27:10.917:WARN:oejs.HomeBaseWarning:main: This instance of Jetty is not running from a separate {jetty.base} directory, this is not recommended. See documentation at http://www.eclipse.org/jetty/documentation/current/startup.html 2018-03-06 12:27:11.104:INFO:oejs.Server:main: jetty-9.3.15.v20161220 2018-03-06 12:27:11.125:INFO:oejdp.ScanningAppProvider:main: Deployment monitor [file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/webapps/] at interval 1 2018-03-06 12:27:11.147:INFO:oejs.AbstractConnector:main: Started ServerConnector@4909b8da{HTTP/1.1,[http/1.1]}{0.0.0.0:8080} 2018-03-06 12:27:11.164:INFO:oejus.SslContextFactory:main: x509=X509@6537cf78(1,h=[],w=[]) for SslContextFactory@67b6d4ae(file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/etc/keystore,file:///Users/bkim203/Work/apps/jetty/jetty-distribution-9.3.15.v20161220/etc/keystore) 2018-03-06 12:27:11.343:INFO:oejs.AbstractConnector:main: Started ServerConnector@55d56113{SSL,[ssl, http/1.1]}{0.0.0.0:8443} 2018-03-06 12:27:11.343:INFO:oejs.Server:main: Started @1190ms | cs |
Let's check it on a web browser.
"http://localhost:8080" will give you the same result as preivous.
"https://localhost:8443" will be the same but it's definitely based on HTTPS now.

References