This page last changed on Sep 29, 2010 by aatkins.

This page lists instructions for how to build a custom installer for JIRA Standalone.

JIRA Version
The installer was added in JIRA v3.8. It currently only supports Microsoft Windows.

Requirements

The JIRA installer is built using install4j (v4.0.5). In order to make your own custom installer, you will need to buy a license for install4j. If you would like to sign your installer executables you will also need a valid code signing certificate. If you are building the installer on Linux, you may also require mono and mono-mcs for code-signing purposes.

General

The installer is configured using install4j. To edit the installer, open jira-template.install4j in the install4j GUI.

Installed JRE

Install4j will bundle the installer with one of the JREs defined in the <INSTALL4J_HOME>/jres directory.
Prior to version 3.12, the JIRA installer was bundled with a standard jre bundle downloaded from the install4j server called 'windows-x86-1.6.0.tar.gz'.

As of v3.12, we are creating a custom JRE bundle, in order to allow the use of the server JVM (only client JVM is included in the default windows jre bundle).
In order to do this, we create a custom JRE bundle from the JDK. JIRA v3.12 uses JDK 1.6.0_03:

  1. Download and install the latest Windows JDK
  2. Start install4j application.
  3. Select Project > Create a JRE Bundle
  4. On the "Select JRE" page, fill in the following values:
    Java home directory = where you just installed the JDK eg. "C:\Program Files\Java\jdk1.6.0_03\jre"
    Java version = the 3 digit version number of the JDK eg. "1.6.0"
    Custom id = something to name the build number and distinguish it form the standard bundle eg. "03_from_jdk"

Once you have created the custom JRE bundle, make sure that jira-template.install4j refers to the same JRE bundle name.
See the follow property in jira-template.install4j:

includedJRE="windows-x86-1.6.0_03_from_jdk"

or browse to Media > Windows > Bundled JRE in the install4j GUI.

Building the Installer

All source files regarding the installer reside in the main JIRA source tree in /jira/subprojects/installer. Edit project.properties to correctly identify your install4j home directory, as well as your certificate keystore:

subprojects/installer/project.properties
# The location used for code-signing the executable.  This location should contain an SPC (software platfrom certificates)
# and PVK (Private key) file for windows.  Not, you will need mono to run this on unix/linux.
atlassian.keystore.location=/path/to/your/keystore
install4j.home=/path/to/your/install4j

Please note that the directory defined by the 'atlassian.keystore.location' property must contain 2 key files: atlassian.spc and private.pvk. Please see the Code signing section below for how to create these.

Once install4j has been installed, and project.properties has been correctly configured, the following maven command can be executed from the JIRA root directory to build the installer (Note: this will also build JIRA Standalone):

maven jira:installer -Dedition=enterprise

Code signing

Code signing is useful if you would like to ensure that the executable generated cannot be altered by anyone else. A code signed executable will also list the publisher (i.e. Atlassian Software Systems) correctly when opening the installer exe.

Background

To get a code-signing certificate, you firstly generate a public/private key pair using Java's keytool. The public key/certificate is then submitted to a key signing authority (Thawte in our case) who will verify that you really are who you claim to be, sign your public certificate and send it back. Your keystore stores your private key, public certificate as well as the whole certificate chain from your key signing authority.

Implementation

In Windows, you sign executables with a utility called signcode. There's a mono version for this and it's also included in install4j (with a slight modification that will allow you to specify a password for your private key).

Signcode takes a number of arguments:

  1. An SPC file (Software Platform Certificates) which is basically a Windows format of your public certificate.
  2. Your private key, in PVK format (also a Windows format).
  3. Password for the private key.
  4. A location of a timestamp server, such as http://timestamp.verisign.com/scripts/timstamp.dll.
  5. The executable you want to sign.

To get all this information you will need some information from your keystore that Java's keytool can't return. The following Java class should return all required information:

import sun.misc.BASE64Encoder;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.*;
import java.security.cert.Certificate;

class ExportPriv
{
    public static void main(String args[]) throws Exception
    {
        ExportPriv myep = new ExportPriv();
        myep.doit();
    }

    public void doit() throws Exception
    {

        KeyStore ks = KeyStore.getInstance("JKS");
        String fileName = "/path/to/your/keystore";

        char[] passPhrase = "password".toCharArray();
        BASE64Encoder myB64 = new BASE64Encoder();


        File certificateFile = new File(fileName);
        ks.load(new FileInputStream(certificateFile), passPhrase);

        KeyPair kp = getPrivateKey(ks, "password", passPhrase);

        Certificate[] certificateChain = ks.getCertificateChain("atlassian");
        for (int i = 0 ; i < certificateChain.length; i++)
        {
            File output = new File("/path/to/your/output/directory/cert"+i+".crt");
            FileOutputStream out = new FileOutputStream(output);
            out.write(certificateChain[i].getEncoded());
            out.flush();
            out.close();

        }
        PrivateKey privKey = kp.getPrivate();


        String b64 = myB64.encode(privKey.getEncoded());

        File output = new File("/path/to/your/output/directory/private.key");
        FileOutputStream out = new FileOutputStream(output);
        out.write(privKey.getEncoded());

        out.flush();
        out.close();


        System.out.println("-----BEGIN PRIVATE KEY-----");
        System.out.println(b64);
        System.out.println("-----END PRIVATE KEY-----");

    }

    public KeyPair getPrivateKey(KeyStore keystore, String alias, char[] password)
    {
        try
        {
            // Get private key
            Key key = keystore.getKey(alias, password);
            if (key instanceof PrivateKey)
            {
                // Get certificate of public key
                Certificate cert = keystore.getCertificate(alias);

                // Get public key
                PublicKey publicKey = cert.getPublicKey();

                // Return a key pair
                return new KeyPair(publicKey, (PrivateKey) key);
            }
        } catch (UnrecoverableKeyException e)
        {
        } catch (NoSuchAlgorithmException e)
        {
        } catch (KeyStoreException e)
        {
        }
        return null;
    }

}

(Note: This code was copied from here with some modifications)

The get the SPC file you will first have to export your entire certificate chain from the keystore first using the Java class above (keytool does not provide a method to do this).
You can then convert this to a SPC file using:

cert2spc cert0.crt cert1.crt cert2.crt atlassian.spc

The private key returned from the keystore is in the wrong format for the signcode utiltiy. There exists a tool for Windows to convert the private key to the correct Windows PVK format.

Signcode can now be executed:

mono /path/to/your/install4j/resource/signcode.exe -spc atlassian.spc  -v private.pvk -vp password -t http://timestamp.verisign.com/scripts/timstamp.dll JIRA_Enterprise_3_8-DEV_windows.exe

CreateJreBundle.gif (image/gif)
Document generated by Confluence on Mar 27, 2011 18:54