How To Install Jira on Ubuntu 26.04 LTS

Install Jira on Ubuntu 26.04

Every sysadmin who has been handed a ticket that says “set up Jira by Friday” knows the feeling. It sounds simple on paper, download an installer, click through a wizard, done. Then reality kicks in: database encoding mismatches, a JVM that refuses to start because of memory limits, a reverse proxy that silently breaks Jira’s base URL, and a client wondering why the instance is timing out during a sprint planning session. Jira is not a fragile application, but it is opinionated, and Ubuntu 26.04 LTS, codenamed Resolute Raccoon, brings enough platform changes that a “just copy the old guide” approach will bite you.

This release matters more than most Ubuntu bumps. Canonical shipped Resolute Raccoon on April 23, 2026 with Linux kernel 7.0, GNOME 50, a Wayland-only desktop stack, the early rollout of sudo-rs, and, critically for this guide, PostgreSQL 18 as the default database package in the repositories. Standard security support runs until April 2031, with Ubuntu Pro extending that to a full decade. If you’re standing up Jira on this LTS, you’re likely doing it because you want five-plus years of runway without a forced OS migration mid-project, and that’s a reasonable bet.

This article walks through installing Jira Software (the self-managed Data Center-track release, since Atlassian retired new Server licenses years ago) on a fresh Ubuntu 26.04 LTS server, using PostgreSQL as the backing database, Nginx as a reverse proxy with TLS termination, and a hardened systemd service configuration. It also covers the JVM tuning, firewall rules, backup strategy, and the troubleshooting scenarios that actually show up in production, not the sanitized happy path you get from a five-minute quickstart. Whether you’re running this on a bare-metal box in a Yogyakarta data center or a cloud VM on DigitalOcean or AWS, the fundamentals below apply the same way.

Why Ubuntu 26.04 LTS Changes the Installation Calculus

Before touching a terminal, it’s worth understanding what’s different this time around. Resolute Raccoon isn’t a cosmetic refresh over Noble Numbat (24.04); the underlying package set shifted enough that copy-pasting a 24.04 tutorial verbatim will cause subtle failures.

The two changes that directly affect a Jira deployment:

  • PostgreSQL 18 is now the default in the Ubuntu repos, replacing PostgreSQL 16 from the previous LTS. Jira’s JDBC driver compatibility and pg_hba.conf authentication defaults behave slightly differently, and the data directory path convention (/etc/postgresql/18/main/) trips up anyone who scripts config edits with a hardcoded version number.
  • cgroup v1 is effectively gone in favor of a pure cgroup v2 stack, which matters if you’re containerizing Jira or running it under systemd resource limits, since some older MemoryLimit= style directives behave differently under v2 semantics.

None of this is a dealbreaker. It just means the installation steps below are written specifically against this release rather than assuming backward compatibility.

Prerequisites Before You Start

Get these sorted first, because troubleshooting a half-configured server is far more painful than spending fifteen minutes upfront.

  • A clean Ubuntu 26.04 LTS server (minimum 4 GB RAM for evaluation, 8 GB or more for a real team of 25+ users; Jira’s JVM alone wants a healthy heap).
  • Root or sudo access.
  • A registered domain name if you plan to expose Jira publicly with TLS (recommended over raw IP access).
  • Atlassian account to generate a trial or purchased license key.
  • Basic familiarity with systemd, ufw, and PostgreSQL’s psql shell.

Run a full system update before anything else. Skipping this step is how you end up debugging a library conflict three hours into the install instead of catching it at the source.

sudo apt update && sudo apt upgrade -y
sudo reboot

Reboot if the kernel was patched. It’s a small habit, but running Jira on a half-updated kernel with pending module reloads is asking for weird, hard-to-reproduce bugs later.

Step 1: Install and Configure PostgreSQL 18

Jira supports PostgreSQL, MySQL, Oracle, and SQL Server, but PostgreSQL is the pragmatic default for self-managed instances, it’s open source, well-documented, and Atlassian’s own performance benchmarks favor it for Data Center deployments.

sudo apt install -y postgresql postgresql-contrib
sudo systemctl enable --now postgresql
sudo systemctl status postgresql

Confirm you’re running version 18, since that’s the repository default on Resolute Raccoon:

psql --version

Now create a dedicated database and user. Never reuse the postgres superuser role for application connections; that’s a habit that comes back to haunt you during a security audit.

sudo -u postgres psql

Inside the psql shell:

CREATE ROLE jirauser WITH LOGIN PASSWORD 'ReplaceWithAStrongPassword!';
CREATE DATABASE jiradb WITH ENCODING 'UTF8' LC_COLLATE 'C' LC_CTYPE 'C' TEMPLATE template0 OWNER jirauser;
GRANT ALL PRIVILEGES ON DATABASE jiradb TO jirauser;
\q

The LC_COLLATE 'C' LC_CTYPE 'C' combination isn’t cosmetic. Jira explicitly requires C-locale collation on PostgreSQL databases; using the system default locale (often en_US.UTF-8) causes indexing and sorting inconsistencies that surface later as bizarre search results or JQL ordering bugs. This is one of those requirements that’s easy to overlook and painful to fix retroactively, because changing collation on a live database means a full dump-and-restore.

Next, tell PostgreSQL to accept password-authenticated connections from Jira. Edit the host-based authentication file:

sudo nano /etc/postgresql/18/main/pg_hba.conf

Add or adjust this line so local TCP connections use md5 (or scram-sha-256, which is the more secure modern default) rather than peer:

host    jiradb    jirauser    127.0.0.1/32    scram-sha-256

Restart PostgreSQL to apply changes:

sudo systemctl restart postgresql

Test the connection before moving forward, because catching a credential typo now saves a confusing failure during Jira’s setup wizard later:

psql -h 127.0.0.1 -U jirauser -d jiradb -W

Step 2: Install Java (OpenJDK)

Jira ships with a bundled JRE in its installer, so a system-wide JDK isn’t strictly mandatory, but having one available is useful for diagnostics, heap dump analysis, and running supplementary tooling like Confluence or third-party plugins that expect JAVA_HOME to be set.

sudo apt install -y openjdk-21-jre-headless
java -version

Set JAVA_HOME in your shell profile if other tools need it:

echo 'export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64' | sudo tee -a /etc/environment
source /etc/environment

Step 3: Download and Install Jira Software

At the time of writing, Jira Software 11.3.x is the current self-managed release line. Always check Atlassian’s official download page for the latest patch version before pulling the binary, security fixes ship regularly and running an outdated point release on a public-facing server is an avoidable risk.

cd /tmp
wget https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-11.3.2-x64.bin
chmod a+x atlassian-jira-software-11.3.2-x64.bin
sudo ./atlassian-jira-software-11.3.2-x64.bin

The installer walks through an interactive text wizard. Here’s what to choose at each prompt, based on what actually holds up in production:

  1. Installation type: choose “Custom Install” if you want control over paths, or “Express Install” for a quick evaluation. For anything touching production, go custom.
  2. Installation directory: default is /opt/atlassian/jira, which is fine. Keep application binaries and data separate.
  3. Home directory: default is /var/atlassian/application-data/jira. This is where attachments, indexes, and plugin data live, make sure this path sits on a disk with enough IOPS headroom, because Lucene indexing under Jira’s home directory is disk-intensive during large searches or bulk imports.
  4. Ports: default HTTP port 8080, control port 8005. If you’re running Confluence or Bitbucket on the same host, you’ll need to change these to avoid collisions.
  5. Run as service: yes, always. This registers Jira as a systemd-managed service, which means it survives reboots and integrates with systemctl for monitoring.

Once the installer finishes, start Jira if it hasn’t already:

sudo systemctl start jira
sudo systemctl enable jira
sudo systemctl status jira

Tail the logs while it boots, since first startup takes a few minutes as Jira initializes its internal Lucene index and Tomcat container:

tail -f /opt/atlassian/jira/logs/catalina.out

Step 4: Complete the Setup Wizard

Open a browser and navigate to http://your-server-ip:8080. You’ll see the Jira setup wizard. Choose “I’ll set it up myself”, not the automatic option, since automatic mode provisions an embedded H2 database that is explicitly unsupported for production use and will bite you the moment your dataset grows past a trivial size.

On the database configuration screen:

  • Database Type: PostgreSQL
  • Hostname: 127.0.0.1
  • Port: 5432
  • Database: jiradb
  • Username: jirauser
  • Password: the password set earlier

Click Test Connection. If it fails here, it’s almost always one of three things: pg_hba.conf not reloaded, a typo in the password, or PostgreSQL listening only on a socket rather than TCP. Once it passes, Jira will run its schema migration, enter your license key, create the initial admin account, and you’re through the wizard.

Step 5: Configure Nginx as a Reverse Proxy with TLS

Running Jira directly on port 8080 exposed to the internet is a bad look and a worse security posture. Put it behind Nginx.

sudo apt install -y nginx

Create a server block:

sudo nano /etc/nginx/sites-available/jira.conf
server {
    listen 80;
    server_name jira.yourdomain.com;

    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_read_timeout 120s;
        client_max_body_size 100M;
    }
}

Enable it and reload Nginx:

sudo ln -s /etc/nginx/sites-available/jira.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Now issue a Let’s Encrypt certificate with Certbot:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d jira.yourdomain.com

There’s one step people forget constantly: Jira needs to know it’s sitting behind a proxy, otherwise generated links (email notifications, webhook callbacks, attachment URLs) will point to the internal :8080 address instead of your public domain. Go to Jira Administration → System → General Configuration and set the Base URL to https://jira.yourdomain.com. Then edit Jira’s Tomcat connector config to trust the proxy headers:

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

Add scheme="https" and proxyName/proxyPort attributes to the <Connector> block, or better, enable the RemoteIpValve that ships with Tomcat, which reads the X-Forwarded-* headers Nginx is already sending. This is the fix for the classic “mixed content” and “redirect loop” symptoms people report after adding SSL.

Step 6: Firewall and Network Hardening

With Nginx handling public traffic, lock down direct access to Jira’s Tomcat port.

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw deny 8080
sudo ufw enable
sudo ufw status verbose

If Jira and PostgreSQL live on separate hosts, restrict PostgreSQL’s listener to the private network interface only, and never expose port 5432 to the public internet. On a single-host setup, 127.0.0.1 binding (the default) already handles this.

JVM and Performance Tuning

Jira’s default JVM heap settings are conservative and tuned for small evaluation instances, not real team usage. Edit the startup config:

sudo nano /opt/atlassian/jira/bin/setenv.sh

Adjust the heap sizes based on available RAM. A rough rule of thumb for a mid-sized team (50-150 users): allocate 2-4 GB minimum heap and let it scale up to 6-8 GB max, leaving enough headroom for the OS page cache and PostgreSQL’s own memory footprint.

JVM_MINIMUM_MEMORY="2048m"
JVM_MAXIMUM_MEMORY="6144m"
JVM_SUPPORT_RECOMMENDED_ARGS="-XX:+UseG1GC -XX:+ExitOnOutOfMemoryError"

The G1 garbage collector handles Jira’s mixed allocation patterns (lots of short-lived objects during indexing, longer-lived caches for issue data) better than the older CMS collector, which Atlassian deprecated in newer JVM builds anyway.

A few additional tuning notes worth internalizing:

  • Disk I/O matters more than CPU for Jira’s day-to-day responsiveness. The Lucene search index under <jira-home>/caches/indexes benefits enormously from SSD-backed storage. If you’re on spinning disks in 2026, that’s the first thing to fix before touching JVM flags.
  • PostgreSQL’s shared_buffers and work_mem in /etc/postgresql/18/main/postgresql.conf should scale with your server’s RAM, roughly 25% of total memory for shared_buffers on a dedicated database host.
  • Reindex during low-traffic windows. A full Jira reindex on a large instance can spike CPU and disk I/O noticeably; schedule it outside business hours if you’re running it manually rather than relying on the background reindex.

Backup Strategy

A Jira instance without a tested backup is a production incident waiting for a date. At minimum, back up two things separately: the PostgreSQL database and the Jira home directory (attachments, plugins, configuration).

pg_dump -U jirauser -h 127.0.0.1 jiradb | gzip > /backups/jiradb_$(date +%F).sql.gz
tar -czf /backups/jira_home_$(date +%F).tar.gz /var/atlassian/application-data/jira

Automate this with a cron job, and, this is the part people skip, actually restore from backup on a scratch VM every few months to confirm the backup is usable. A backup you’ve never restored is a hypothesis, not a safety net.

Troubleshooting Common Errors

Jira won’t start, log shows “Port 8080 already in use.”

Something else is bound to that port, likely another Tomcat instance or a leftover process from a failed prior install. Find and kill it:

sudo lsof -i :8080
sudo kill -9 <PID>

Setup wizard fails at database test connection with “FATAL: Peer authentication failed.”

This means pg_hba.conf still has peer or ident authentication for that connection type instead of md5/scram-sha-256. Recheck the file and restart PostgreSQL after editing, a reload sometimes isn’t enough if the connection method itself changed.

Jira runs but attachments fail to upload with a 413 error.

Nginx’s default client_max_body_size is 1 MB, far too small for attachments or import files. Bump it in the server block, as shown earlier, and reload Nginx.

Reindexing gets stuck or times out.

Usually a memory pressure symptom. Check atlassian-jira.log for OutOfMemoryError. Increase JVM_MAXIMUM_MEMORY in setenv.sh, restart Jira, and retry during a quiet period.

“This XML file does not appear to have any style information” or blank page after enabling HTTPS.

Classic symptom of a missing RemoteIpValve configuration or an incorrect Base URL setting. Double-check server.xml and the Base URL field in Jira’s General Configuration.

High CPU usage under normal load with no obvious cause.

Check for a runaway plugin. Jira Marketplace add-ons are a common source of background job loops that spike CPU. Disable recently installed plugins one at a time via Manage Apps to isolate the culprit.

r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.

Related Posts