Introduction

This guide explains Install Jira 9 on Ubuntu 24.04 with PostgreSQL — Step by Step in a production-aware way, including the design choices, implementation checks, and operational safeguards that matter for Linux environments.

1. Before you start

This guide installs one Jira node and its database on a fresh Ubuntu Server 24.04 LTS amd64 host. A practical starting point for a small installation is 4 vCPU, 8 GB RAM and 40 GB free disk. You need a sudo account, internet access and a valid Jira Data Center license or an available evaluation license. Sizing depends on users and attachments.

Checked on 14 October 2026: 9.12.40 is the latest maintenance release listed in the official 9.12 release notes, released on 5 October 2026. The 9.17 feature branch exists, but its 9.17.5 patch is older. This guide uses the more recently patched 9.12 LTS branch. Jira Server support ended in February 2024. This is a version-specific installation guide, not a promise of current vendor support for Jira 9.

Use Java 17 and PostgreSQL 15. Ubuntu 24.04 normally installs PostgreSQL 16 through the unversioned postgresql package; Jira 9.12 does not support that database major. We therefore install postgresql-15 explicitly from PGDG. Atlassian documents Linux support generally; this guide does not claim certification of Ubuntu 24.04 for this older Jira release. Commands below have been reviewed against documentation, not executed on a live Jira server.

Run the commands in order in Bash on Ubuntu, not in Windows PowerShell. This is a new installation, not an upgrade of an existing Jira. The database stays local; do not open TCP 5432 to the network.

Architecture and Core Concepts

Understand the data flow, trust boundaries, dependencies, and the expected state before changing a live environment. Separate control-plane configuration from data-plane traffic and document every external dependency.

Security Considerations

Production safety

  • Do not expose management interfaces or databases to the public Internet.
  • Store passwords, tokens, and private keys outside the article and source repository.
  • Patch dependencies, restrict administrative access, and retain audit logs.

2. Prepare Ubuntu and Java

BASH
cat /etc/os-release
uname -m
free -h
df -h /
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl ca-certificates gnupg openjdk-17-jdk-headless fontconfig
java -version
timedatectl status
sudo timedatectl set-ntp true

The OS must be Ubuntu 24.04, the architecture x86_64 and Java must report 17. If Ubuntu asks for a reboot, run sudo reboot, reconnect over SSH and continue. The service below pins Java 17 explicitly, even if another Java version is also installed.

3. Install PostgreSQL 15

Add the official PostgreSQL repository with a dedicated signing key, then install version 15 only.

BASH
sudo install -d -m 0755 /usr/share/postgresql-common/pgdg
sudo curl --fail --show-error --location   https://www.postgresql.org/media/keys/ACCC4CF8.asc   -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc
echo 'deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt noble-pgdg main' | sudo tee /etc/apt/sources.list.d/pgdg.list
sudo apt update
sudo apt install -y postgresql-15 postgresql-client-15
sudo systemctl enable --now postgresql
pg_lsclusters
sudo -u postgres psql -p 5432 -c 'SELECT version();'

On this fresh host, pg_lsclusters should show 15/main, port 5432 and online. If another cluster already occupies 5432, stop here and resolve the port deliberately; do not remove an existing database. All remaining commands assume 15/main uses 5432.

4. Create the Jira database and password

Open psql as the postgres administrator. Paste the following SQL inside psql. The password command prompts twice without putting the password into shell history. Keep that password for the browser wizard. The application account is not a superuser.

BASH
sudo -u postgres psql -p 5432
SQL
CREATE ROLE jira LOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE;
SET password_encryption = 'scram-sha-256';
\password jira
CREATE DATABASE jiradb OWNER jira ENCODING 'UTF8' LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0;
\connect jiradb
GRANT USAGE, CREATE ON SCHEMA public TO jira;
\q

Restrict PostgreSQL to loopback. Add the two Jira authentication rules at the top of pg_hba.conf so they take precedence; leave the other packaged rules intact.

BASH
sudo -u postgres psql -p 5432 -c "ALTER SYSTEM SET listen_addresses = 'localhost';"
sudo cp -a /etc/postgresql/15/main/pg_hba.conf /etc/postgresql/15/main/pg_hba.conf.before-jira
sudo sed -i '1i host jiradb jira 127.0.0.1/32 scram-sha-256\nhost jiradb jira ::1/128 scram-sha-256' /etc/postgresql/15/main/pg_hba.conf
sudo systemctl restart postgresql@15-main
psql -h 127.0.0.1 -p 5432 -U jira -d jiradb -W -c "SELECT current_user, current_database();"
sudo -u postgres psql -p 5432 -c "SELECT datname, pg_encoding_to_char(encoding), datcollate, datctype FROM pg_database WHERE datname = 'jiradb';"

Enter the password when asked. The first test must return jira and jiradb. The second must show UTF8 / C / C. Fix connection or password errors before installing Jira.

5. Download and extract Jira

We use the official tar.gz archive, with separate installation and data directories. Verify the archive checksum against Atlassian’s download archive if provided before extracting. A locally calculated hash alone does not verify authenticity.

BASH
sudo useradd --system --create-home --home-dir /var/lib/jira --shell /usr/sbin/nologin jira
sudo install -d -o jira -g jira -m 0750 /var/atlassian/application-data/jira
sudo install -d -m 0755 /opt/atlassian
mkdir -p ~/jira-install
cd ~/jira-install
JIRA_VERSION=9.12.40
curl --fail --location --show-error   "https://www.atlassian.com/software/jira/downloads/binary/atlassian-jira-software-${JIRA_VERSION}.tar.gz"   -o "atlassian-jira-software-${JIRA_VERSION}.tar.gz"
sha256sum "atlassian-jira-software-${JIRA_VERSION}.tar.gz"
tar -tzf "atlassian-jira-software-${JIRA_VERSION}.tar.gz" | head
sudo tar -xzf "atlassian-jira-software-${JIRA_VERSION}.tar.gz" -C /opt/atlassian
sudo ln -s "/opt/atlassian/atlassian-jira-software-${JIRA_VERSION}-standalone" /opt/atlassian/jira
sudo chown -R jira:jira "/opt/atlassian/atlassian-jira-software-${JIRA_VERSION}-standalone"
echo 'jira.home=/var/atlassian/application-data/jira' | sudo tee /opt/atlassian/jira/atlassian-jira/WEB-INF/classes/jira-application.properties
sudo chown jira:jira /opt/atlassian/jira/atlassian-jira/WEB-INF/classes/jira-application.properties

The application path is /opt/atlassian/jira and Jira Home is /var/atlassian/application-data/jira. The archive includes Tomcat and the PostgreSQL JDBC driver; no separate Tomcat or SQL Server installation is needed. Never continue if the download or extraction failed.

6. Create and start the service

Bind the HTTP connector to loopback for safe initial setup through an SSH tunnel. This edit must match the connector line shown by grep. If the address is not present after the edit, use sudo nano /opt/atlassian/jira/conf/server.xml and add address="127.0.0.1" to the Connector with port="8080" manually.

BASH
sudo cp -a /opt/atlassian/jira/conf/server.xml /opt/atlassian/jira/conf/server.xml.before-jira
sudo sed -i 's/<Connector port="8080"/<Connector address="127.0.0.1" port="8080"/' /opt/atlassian/jira/conf/server.xml
grep -n -A 5 '<Connector' /opt/atlassian/jira/conf/server.xml
sudo tee /etc/systemd/system/jira.service > /dev/null <<'EOF'
[Unit]
Description=Jira Software
After=network.target postgresql@15-main.service
Requires=postgresql@15-main.service

[Service]
Type=simple
User=jira
Group=jira
Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
Environment=JRE_HOME=/usr/lib/jvm/java-17-openjdk-amd64
WorkingDirectory=/opt/atlassian/jira
ExecStart=/opt/atlassian/jira/bin/start-jira.sh -fg
Restart=on-failure
RestartSec=10
TimeoutStopSec=180
KillSignal=SIGTERM
UMask=0027
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now jira
sudo systemctl status jira --no-pager
sudo journalctl -u jira -n 80 --no-pager
sudo ss -ltnp | grep ':8080'
curl -I http://127.0.0.1:8080/

Startup can take several minutes. Port 8080 must listen on 127.0.0.1. HTTP 200 or a redirect indicates that the web application is responding. A running systemd process alone does not prove Jira finished starting; inspect logs and the browser too.

7. Complete setup in your browser

On your own computer, open a terminal and establish the SSH tunnel below. Replace YOUR_SSH_USER and YOUR_SERVER_IP with real values. Keep the session open, then visit http://localhost:8080 in your browser.

BASH
ssh -L 8080:127.0.0.1:8080 YOUR_SSH_USER@YOUR_SERVER_IP

Choose “I will set it up myself” / manual setup, then “My own database”, and select PostgreSQL. Enter Hostname: 127.0.0.1; Port: 5432; Database: jiradb; Username: jira; Password: the password from step 4; Schema: public. Click Test Connection, and only continue when it succeeds. Do not choose the built-in evaluation database.

Set the application title. For this tunneled initial setup, use http://localhost:8080 as the temporary Base URL. Activate your Data Center license, create the administrator with a unique strong password, and finish the wizard. SMTP can be skipped initially. Once you configure a real HTTPS address, update Base URL to that address.

Create a Scrum or Kanban project, create one issue, refresh the page and verify it remains saved. Restart Jira and repeat the check. This confirms the initial application/database path works.

BASH
sudo systemctl restart jira
sudo journalctl -u jira -n 50 --no-pager

8. Optional: give users an HTTPS address

For access by other users, use Nginx in front of Jira. You need a real domain pointing to the server, public TCP 80/443 reachability for HTTP-01 issuance, and a permitted SSH connection. Replace jira.example.com and admin@example.com everywhere below. This example assumes a dedicated host without an existing Nginx site; an internal-only deployment needs an internal CA or DNS-01 instead.

BASH
sudo apt install -y nginx certbot python3-certbot-nginx
sudo tee /etc/nginx/sites-available/jira > /dev/null <<'EOF'
server {
    listen 80;
    server_name jira.example.com;
    client_max_body_size 100m;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 30s;
        proxy_read_timeout 300s;
    }
}
EOF
sudo ln -s /etc/nginx/sites-available/jira /etc/nginx/sites-enabled/jira
sudo nginx -t
sudo systemctl enable --now nginx
sudo systemctl reload nginx
sudo certbot --nginx -d jira.example.com --email admin@example.com --agree-tos --redirect
sudo certbot renew --dry-run

If a firewall is active, allow TCP 80/443 in that firewall and the upstream firewall. Keep SSH access working. Do not expose 8080 or 5432. After the certificate succeeds, edit the Jira connector:

BASH
sudo nano /opt/atlassian/jira/conf/server.xml

On the Connector with port="8080", add the attributes below, keeping its existing attributes and address="127.0.0.1". Replace the domain. Do not create a second connector.

XML
scheme="https"
secure="true"
proxyName="jira.example.com"
proxyPort="443"
BASH
sudo systemctl restart jira
sudo nginx -t
curl -I https://jira.example.com/

Open https://jira.example.com, then Administration → System → General configuration → Edit settings, and set Base URL to https://jira.example.com. Verify login, issue creation and attachment upload. The 100 MB Nginx limit is an example; Jira’s attachment limit is configured separately.

9. Do we need SQL Server?

No. Jira uses one database backend. PostgreSQL 15 completes this installation, so installing SQL Server alongside it adds nothing. If your organization requires Microsoft SQL Server, use it instead of PostgreSQL and follow the Jira 9 database matrix and the version-specific SQL Server setup guide; do not connect one Jira instance to both databases.

10. Common installation errors

Connection refused: check pg_lsclusters and the configured port. Password authentication failed: retest with psql -h 127.0.0.1 -U jira -d jiradb -W; reset using \password jira as postgres if needed. No pg_hba.conf entry: verify the two host rules and restart postgresql@15-main. Do not use trust authentication to hide the error.

Jira does not start: inspect journalctl and catalina.out for Java or permissions errors. Nginx 502: ensure Jira responds locally on 8080. Incorrect redirects after HTTPS: check proxyName, proxyPort, scheme and Base URL. Never paste dbconfig.xml or full logs containing credentials into a public ticket.

BASH
sudo journalctl -u jira -n 100 --no-pager
sudo tail -n 100 /opt/atlassian/jira/logs/catalina.out
sudo tail -n 100 /var/atlassian/application-data/jira/log/atlassian-jira.log
sudo systemctl status postgresql@15-main --no-pager
curl -I http://127.0.0.1:8080/

11. Take an initial backup

Back up PostgreSQL and Jira Home together while Jira is stopped so attachments match the database. The backup commands run in a root shell, use a private timestamped folder and restart Jira afterward. They do not delete or overwrite older backups. Copy the backup securely to another host; a copy on the same disk is not sufficient.

BASH
sudo bash <<'EOF'
set -euo pipefail
umask 077
backup_dir="/var/backups/jira/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$backup_dir"
systemctl stop jira
trap 'systemctl start jira' EXIT
runuser -u postgres -- pg_dump -p 5432 -Fc jiradb > "$backup_dir/jiradb.dump"
tar -czf "$backup_dir/jira-home.tar.gz" -C /var/atlassian/application-data jira
tar -czf "$backup_dir/jira-install.tar.gz" -C /opt/atlassian atlassian-jira-software-9.12.40-standalone
cp /etc/systemd/system/jira.service "$backup_dir/"
if [ -f /etc/nginx/sites-available/jira ]; then cp /etc/nginx/sites-available/jira "$backup_dir/nginx-jira.conf"; fi
pg_restore --list "$backup_dir/jiradb.dump" > "$backup_dir/dump-list.txt"
tar -tzf "$backup_dir/jira-home.tar.gz" > "$backup_dir/home-list.txt"
echo "Backup saved: $backup_dir"
EOF
sudo systemctl status jira --no-pager

The archive contains database credentials and private attachments; encrypt off-host copies. Listing archives checks readability, not full recoverability. Before relying on backups, restore them to a separate test host with the same Jira version. Certificate/private-key backup for the optional HTTPS setup must follow your organization’s secure backup process.

Best Practices

  • Version-control configuration and review changes.
  • Use least privilege and explicit allow-lists.
  • Automate repeatable checks and monitor the expected state.
  • Test upgrades and restores before production rollout.

Conclusion

A reliable implementation of Install Jira 9 on Ubuntu 24.04 with PostgreSQL — Step by Step is more than a successful first run. Keep the configuration documented, observable, recoverable, and aligned with the team's change-management process.

Frequently Asked Questions

Can this procedure be used in production without a maintenance window?

Only when the platform documents a safe reload or the change is isolated and rollback-tested; otherwise schedule a maintenance window.

What should be backed up before making the change?

Back up configuration, credentials held by the service, application data, and the current version of the deployment. Test the restore path.

How do I verify that the change really took effect?

Check the service health endpoint or status, inspect logs and metrics, and run a representative client-side test from the intended network zone.

What is the first check for a timeout or connection refusal?

Check listening ports, routing, firewall policy, DNS resolution, and whether the service is bound to the expected interface.

How should secrets and tokens be handled?

Use a secret manager or protected environment configuration, rotate them after exposure, and never commit them to Git or paste them into tickets.

How can this be automated safely?

Automate idempotent checks first, add dry-run support, require review for destructive operations, and emit logs and exit codes suitable for monitoring.

What should be monitored after deployment?

Monitor availability, error rate, latency, resource saturation, certificate expiry, failed jobs, and configuration drift.

When should I roll back instead of troubleshooting in place?

Rollback when the service is unavailable, data integrity is at risk, or the blast radius is growing faster than you can isolate it. Preserve logs first.

Official References

Jira 9.12.40 release, 5 October 2026

Official download archives

Version-specific database matrix

Official PostgreSQL Ubuntu repository

Jira 9 PostgreSQL database settings

Linux archive installation

Official command-line download pattern

Share

Meet AJInfrastructure & DevOps
Loading…