atlassian tools and nginx

2012-08-28

Atlassian has a wonderful set of tools.

I’ve been using Jira with Fisheye for the last few months, but I recently came across Stash.

Stash is a nice git repository and project manager than provides easy access to creating new Git repo’s with User and Group access controls. I’m considering phasing out FishEye in favor of Stash. I only wanted FishEye as a source code browser, that integrated issues tracking. Stash has that, and allows me to manage many projects and repositories.

Since we (Bay Photo Lab) use FreeBSD as our primary *nix server (and Atlassian only has unofficial documentation on that), I feel I should pool my collective experiences with it and post it here.

In this article, I have documented how I run all three Atlassian applications behind a Nginx server, with HTTPS enabled, and the three available URLs:

Packages

The basic packages required are:

  • java/diablo-jdk16
  • www/nginx
  • databases/postgresql91-client
  • databases/postgresql91-server

We use a separate PostgreSQL database server, so our installation points to that (and that means, we don’t install the postgresql91-server package).

Data Structure

The file system hierarchy I use is pretty simple:

/data
|-- apps
|   |-- jira_home
|   `-- stash
|-- db
|   `-- pgsql
|-- scm
|   |-- git
|   `-- hg
`-- www
    |-- fecru -> fecru-2.8.0
    |-- fecru-2.7.10
    |-- fecru-2.8.0
    |-- jira -> jira-5.1-standalone
    |-- jira-5.1-standalone
    `-- stash -> atlassian-stash-1.2.2

The applications that Nginx proxy go in /data/www. Their application specific data goes in /data/app/

Before running Stash, I was manually creating repositories in /data/scm/{git,hg,svn…}

Now that we’ve pretty much standardized on Git for most projects, I’m letting Stash create those on its own (where is set to /data/apps/stash

User Accounts

At the minimum, you’ll need a user account to run the Atlassian services.

I created one called ‘atlassian’.

The /data/apps and /data/www/ related directories are all owned by the Atlassian user.

Jira configuration

Server.xml

        <Connector port="8080"
                   maxThreads="150"
                   minSpareThreads="25"
                   maxSpareThreads="75"
                   connectionTimeout="20000"
                   scheme="https"
                   proxyName="scm.example.com"
                   proxyPort="443"

                   enableLookups="false"
                   maxHttpHeaderSize="8192"
                   protocol="HTTP/1.1"
                   useBodyEncodingForURI="true"
                   redirectPort="8443"
                   acceptCount="100"
                   disableUploadTimeout="true"

...
        <Engine name="Catalina" defaultHost="localhost">
           ...
                <Context path="/jira" docBase="${catalina.home}/atlassian-jira" reloadable="false" useHttpOnly="true">
                  ...
                </Context>
           ...

###jira-application.properties

WEB-INF/classes/jira-application.properties

# Do not modify this file unless instructed. It is here to store 
# the location of the JIRA home directory only and is typically 
# written to by the installer.
jira.home = /data/apps/jira_home

Stash

Like Jira, Stash needs to have the listening port and Path set to Stash: ###Server.xml

        <Connector port="7990" protocol="HTTP/1.1"
                   connectionTimeout="20000"
                   useBodyEncodingForURI="true"
                   redirectPort="443"
                   compression="on" compressableMimeType="text/html,text/xml,text/plain,text/css,application/json,application/javascript,application/x-javascript"
                   secure="true"
                   scheme="https"
                   proxyName="scm.example.com"
                   proxyPort="443"
         ...
         <Host name="localhost" appBase="webapps"
               ...
               <Context path="/stash" docBase="${catalina.home}/atlassian-stash.war" 
                     reloadable="false" useHttpOnly="true"/>
               ...

Fish Eye (FECRU)

FishEye is slightly different than Jira and Stash, it has a config.xml file that FishEye itself updates.

Still, after you setup FishEye, you can modify the config.xml to include this:

<web-server site-url="https://scm.example.com/fisheye" context="fisheye">
<http bind=":8180" proxy-port="443" proxy-scheme="https" proxy-host="scm.example.com"/></web-server>

rcNG scripts

/usr/local/etc/rc.d/jira:

#!/bin/sh
#
# Startup script for JIRA on FreeBSD
#
# This goes in /usr/local/etc/rc.d and gets run at boot-time.

# PROVIDE: jira
# REQUIRE: postgresql
# KEYWORD: shutdown

#
# Add the following lines to /etc/rc.conf to enable jira:
#
#jira_enable="YES"
#
jira_enable="${jira_enable-NO}"

. /etc/rc.subr

name="jira"
rcvar=`set_rcvar`
start_cmd="${name}_start"
stop_cmd="${name}_stop"

export JAVA_OPTS="-Djavax.net.ssl.keyStore='/usr/local/openjdk/jre/lib/security/cacerts' -Djavax.net.ssl.keyStorePassword=changeit -Djavax.net.ssl.trustStore='/usr/local/openjdk/jre/lib/security/cacerts' -Djavax.net.ssl.trustStorePassword=changeit"

jira_start()
{
    echo -n " Starting JIRA"
    su - atlassian -c '/data/www/jira/bin/startup.sh'
}

jira_stop()
{
    echo -n " Stopping JIRA"
    su - atlassian -c '/data/www/jira/bin/shutdown.sh'
}

load_rc_config $name
run_rc_command "$1"

/usr/local/etc/rc.d/stash

#!/bin/sh
#
# Startup script for Stash on FreeBSD
#
# This goes in /usr/local/etc/rc.d and gets run at boot-time.

# PROVIDE: stash
# REQUIRE: postgresql
# KEYWORD: shutdown

#
# Add the following lines to /etc/rc.conf to enable stash:
#
#stash_enable="YES"
#
stash_enable="${stash_enable-NO}"

. /etc/rc.subr

name="stash"
rcvar=`set_rcvar`
start_cmd="${name}_start"
stop_cmd="${name}_stop"

stash_start()
{
    echo -n " Starting Stash"
    su - atlassian -c '/data/www/stash/bin/startup.sh'
}

stash_stop()
{
    echo -n " Stopping Stash"
    su - atlassian -c '/data/www/stash/bin/shutdown.sh'
}

load_rc_config $name
run_rc_command "$1"

/usr/local/etc/rc.d/fecru:
#!/bin/sh
#
# Startup script for FishEye on FreeBSD
#
# This goes in /usr/local/etc/rc.d and gets run at boot-time.

# PROVIDE: fecru
# REQUIRE: postgresql
# KEYWORD: shutdown

#
# Add the following lines to /etc/rc.conf to enable fecru:
#
#fecru_enable="YES"
#
fecru_enable="${fecru_enable-NO}"

. /etc/rc.subr

name="fecru"
rcvar=`set_rcvar`
start_cmd="${name}_start"
stop_cmd="${name}_stop"

fecru_start()
{
    echo -n " Starting FishEye"
    su - atlassian -c '/data/www/fecru/bin/start.sh'
}

fecru_stop()
{
    echo -n " Stopping FishEye"
    su - atlassian -c '/data/www/fecru/bin/stop.sh'
}

load_rc_config $name
run_rc_command "$1"
Enable RC Scripts

With the scripts in /usr/local/etc/rc.d/ , you still need to enable them.

Most guides will tell you to just add the following to rc.conf:

$ echo 'jira_enable="YES" >> /etc/rc.conf'
$ echo 'fecru_enable="YES" >> /etc/rc.conf'
$ echo 'stash_enable="YES" >> /etc/rc.conf'

I prefer the new rcNG style, which is to use /etc/rc.conf.d/, and create a new file based on the service name:

$ echo 'jira_enable="YES" >> /etc/rc.conf.d/jira'
$ echo 'fecru_enable="YES" >> /etc/rc.conf.d/fecru'
$ echo 'stash_enable="YES" >> /etc/rc.conf.d/stash'

This is cleaner to me, and if I update the scripts to use more options (like “jira_app_dir=/data/www/jira” for example), I can keep it contained in the separate service file, and not have a messy and long rc.conf.

You can now verify that your services will start up the the “rcvar” flag:

mikec@scm /d/w/fecru-2.8.0> /usr/local/etc/rc.d/jira rcvar
# jira
#
jira_enable="YES"
#   (default: "")

mikec@scm /d/w/fecru-2.8.0> /usr/local/etc/rc.d/fecru rcvar
# fecru
#
fecru_enable="YES"
#   (default: "")

mikec@scm /d/w/fecru-2.8.0> /usr/local/etc/rc.d/stash rcvar
# stash
#
stash_enable="YES"
#   (default: "")

mikec@scm /d/w/fecru-2.8.0>

Nginx Proxy Conf

Placing Nginx in front of everything is simple, and honestly, easier than dealing with Java’s keytool for SSL certificates.

    # HTTPS server
    #
    server {
        listen       443;
        server_name  localhost;

        ssl                  on;
        ssl_certificate      /var/puppet/ssl/certs/scm.example.com.pem;
        ssl_certificate_key  /var/puppet/ssl/private_keys/scm.example.com.pem;

        ssl_session_timeout  5m;

        ssl_protocols  SSLv2 SSLv3 TLSv1;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers   on;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;

        }

        location /jira {
              proxy_set_header X-Forwarded-Host $host;
              proxy_set_header X-Forwarded-Server $host;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_pass http://127.0.0.1:8080/jira;
              proxy_redirect off;
        }

        location /fisheye {
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://127.0.0.1:8180;
                proxy_redirect off;
        }

        location /stash {
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://127.0.0.1:7990/stash;
                proxy_redirect off;
        }



    }

}