Documentation

Self-hosted install guide for Spec2Tickets

ℹ Two names, one product — Spec2Tickets is how the app is published on the Atlassian Marketplace. Spec2JIRA is the project and vendor name you'll see in the backend, in .env variables like SPEC2JIRA_API_KEY, and across this site.
Setup time: ~30–45 minutes of active work, plus up to one business day for backend whitelist approval (Step 7). You'll need a Linux server with an NVIDIA GPU (24 GB+ VRAM).

Overview

The Spec2JIRA backend runs AI models that convert your Confluence specifications into structured Jira work items. It runs on your infrastructure — your data never leaves your network.

The Forge app in Confluence and Jira (installed from the Atlassian Marketplace as Spec2Tickets for Confluence and Jira) connects to your self-hosted backend over HTTPS. All AI inference happens on your hardware using the open-source Qwen 2.5 model.

Requirements

ComponentRequirement
OSUbuntu 24.04 LTS or 22.04 LTS (tested on GCP Deep Learning VM with CUDA)
ImageDeep Learning VM with CUDA (Ubuntu 24.04, CUDA 12.x, Python 3.12)
GPUNVIDIA with ≥24 GB VRAM — tested: L4, A10, A100, RTX 4090
RAM32 GB system RAM (16 GB minimum, 32 GB recommended)
DiskSSD, 100 GB free (10 GB image + 25 GB models + Docker overhead)
DriversNVIDIA driver 550+
SoftwareDocker 24+, Docker Compose v2, NVIDIA Container Toolkit
NetworkStatic IP or domain with HTTPS, reachable from Atlassian Cloud
VRAM note: The pipeline peaks at ~18 GB VRAM during inference. 16 GB GPUs (e.g., T4) are not sufficient. 24 GB minimum is required.

Using a Cloud GPU VM?

If you're using a cloud GPU image (e.g., GCP Deep Learning VM, AWS Deep Learning AMI), NVIDIA drivers, Docker, and the Container Toolkit are typically pre-installed. Verify with:

nvidia-smi          # Should show your GPU
docker --version    # Should show Docker 24+

# If docker is missing, install it:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker

docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu22.04 nvidia-smi

If all three work, skip directly to Step 2. If docker returns "permission denied", run newgrp docker or log out and back in — your user needs to be in the docker group.

Step 0: NVIDIA Drivers

Skip if nvidia-smi already works.

# Check if drivers are already installed
nvidia-smi

# If not found, install:
sudo apt update
sudo apt install -y nvidia-driver-550

# Reboot required after driver install
sudo reboot

# After reboot, verify:
nvidia-smi
# Should show your GPU model and driver version
Recommended on Ubuntu 24.04: pin kernel and NVIDIA packages to prevent automatic upgrades from breaking the NVIDIA driver. Unpaired kernel updates can leave the NVIDIA kernel module unbuilt, causing the backend to fail at next reboot.
# Pin kernel and NVIDIA driver packages against unattended upgrades
sudo apt-mark hold linux-image-generic linux-headers-generic linux-image-gcp
sudo apt-mark hold nvidia-driver-550 nvidia-dkms-550

# When you want to update them deliberately:
#   sudo apt-mark unhold <package>
#   sudo apt update && sudo apt upgrade
#   sudo dkms autoinstall   # rebuild NVIDIA module against new kernel

Step 1: Docker + NVIDIA Container Toolkit

Skip if docker run --rm --gpus all ... already works.

Install Docker

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER

# Apply group change without logging out:
newgrp docker

Install NVIDIA Container Toolkit

curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg

curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

# Verify GPU access in Docker:
docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu22.04 nvidia-smi
# Should show the same GPU as bare-metal nvidia-smi

Step 2: Download Spec2JIRA

curl -fsSL https://spec2jira.com/releases/spec2jira-backend-2.2.0.tar.gz | tar xz
cd spec2jira-backend

This gives you:

FilePurpose
docker-compose.ymlContainer configuration (pulls from Docker Hub)
setup.shDownloads AI models from Hugging Face
.env.exampleConfiguration template
requirements-train.txtDependencies for optional fine-tuning
INSTALL.mdOffline copy of this guide

Step 3: Download AI Models

The backend uses two open-source Qwen 2.5 models (~25 GB total download). This is a one-time step.

chmod +x setup.sh train.sh
./setup.sh

The script will automatically install any missing dependencies (pip, huggingface_hub) before downloading.

What this downloads:

Models are saved to ./models/ and mounted into the Docker container.

Resumable: If the download is interrupted, re-run ./setup.sh — it picks up where it left off.

Step 4: Configure

cp .env.example .env
nano .env  # Ctrl+O, Enter, Ctrl+X to save and exit

Required settings:

VariableDescriptionExample
ATLASSIAN_SITE_URLYour Atlassian site (without protocol)yourcompany.atlassian.net
ATLASSIAN_SERVICE_ACCOUNT_EMAILService account emailspec2jira-svc@yourcompany.com
ATLASSIAN_SERVICE_ACCOUNT_TOKENAPI token for the service accountATATT3xF...
JIRA_PROJECT_KEYDefault Jira project for created issuesPROJ
SPEC2JIRA_API_KEYBackend API key (see Step 4.1)QCRmjrQPm2APyQ6o...

Creating a service account (recommended)

  1. Create a dedicated Atlassian account (e.g., spec2jira-svc@yourcompany.com).
  2. Grant it read access to the Confluence spaces containing your specs.
  3. Grant it write access to the target Jira project.
  4. Generate an API token at id.atlassian.com/manage-profile/security/api-tokens.
  5. Use this email and token in .env.

Using a dedicated service account with minimal permissions is a security best practice — it limits the backend's access to only what it needs.

Step 4.1: Generate Backend API Key

Spec2Tickets requires a shared secret between your self-hosted backend and the Confluence app. This key authenticates the Forge app to your backend.

  1. Generate a random key:
    openssl rand -base64 32
  2. Set it in your backend .env file:
    SPEC2JIRA_API_KEY=<paste-output-here>
  3. In Step 8, you will paste the same key into the Forge app settings. Both values must match exactly.
Required: The backend will refuse to start if SPEC2JIRA_API_KEY is missing or shorter than 16 characters. This is intentional — it prevents accidental production deploys with no authentication.

Step 5: Start

docker compose up -d

# Wait ~60 seconds for models to load into GPU memory, then verify:
curl -H "Authorization: Bearer <your-api-key>" http://localhost:8000/health
First startup pulls the Docker image (~11 GB) and loads AI models into GPU memory. This can take 2–5 minutes. Subsequent starts are faster.
Authentication required: The /health endpoint requires a valid API key. A bare curl http://localhost:8000/health will return 401 Unauthorized — this is expected behavior, not an error.

Watch startup progress:

docker compose logs -f --tail=50

Step 6: Expose via HTTPS

The backend must be reachable from Atlassian Cloud over HTTPS.

6.1 DNS record

Add an A record pointing to your VM's public IP:

Type:      A
Name:      api
Points to: <your VM public IP>
TTL:       3600

6.2 Install nginx and certbot

sudo apt install -y nginx certbot python3-certbot-nginx

# Remove the default site (prevents it from intercepting traffic)
sudo rm -f /etc/nginx/sites-enabled/default

6.3 Initial HTTP config

Create /etc/nginx/sites-enabled/spec2jira:

sudo nano /etc/nginx/sites-enabled/spec2jira

Paste:

server {
    listen 80;
    server_name api.yourcompany.com;
    location / {
        proxy_pass http://127.0.0.1:8000;
    }
}
sudo nginx -t && sudo systemctl reload nginx

6.4 Get the SSL certificate

sudo certbot --nginx -d api.yourcompany.com

Certbot will ask three questions on first run:

  1. Email address — enter your email (used for renewal reminders and security notices).
  2. Terms of Service — type Y to agree (required).
  3. Share email with EFF — type Y or N (your preference, does not affect the certificate).

If certbot fails, make sure your DNS A record from 6.1 has propagated and that port 80 is reachable from the internet.

6.5 Final HTTPS config

Open the config file for editing:

sudo nano /etc/nginx/sites-enabled/spec2jira

Replace the contents with the full HTTPS configuration below. Replace every instance of api.yourcompany.com with your actual domain (certbot writes the SSL paths automatically; adjust to match your domain):

server {
    listen 443 ssl;
    server_name api.yourcompany.com;

    ssl_certificate     /etc/letsencrypt/live/api.yourcompany.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourcompany.com/privkey.pem;
    include             /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 1800s;  # Pipeline runs can take up to 25 minutes
    }
}

server {
    if ($host = api.yourcompany.com) {
        return 301 https://$host$request_uri;
    }
    listen 80;
    server_name api.yourcompany.com;
    return 404;
}
sudo nginx -t && sudo systemctl reload nginx

# Verify HTTPS works:
curl -H "Authorization: Bearer <your-api-key>" https://api.yourcompany.com/health

Step 7: Request Backend Whitelist Approval

During early access, each customer's backend domain is added to the Spec2Tickets Forge app allowlist. This is a one-time, ~5-minute step on our side.

Email support@spec2jira.com with:

We respond within one business day with a confirmation email. Once you receive confirmation, the Forge app installed on your Atlassian site can reach your backend.

Tip: You can send this email as soon as you've chosen your backend domain — no need to wait for HTTPS setup to complete. Running this in parallel with Step 6 reduces total wait time.
If you install the Marketplace app before whitelist approval: "Test Connection" in Step 8 will fail with a 403 error. This is expected. Wait for the confirmation email, then retry — no reinstall required.

Step 8: Connect the Forge App

  1. Install Spec2Tickets for Confluence and Jira from the Atlassian Marketplace.
  2. In Confluence, open any page. In the page toolbar, click the (more) menu.
  3. Select Spec2Tickets for Confluence and Jira. An onboarding screen will appear with configuration instructions.
  4. Follow the onboarding instructions to open Apps → Spec2JIRA → Configure.
  5. In the configuration page, enter:
    • Your backend URL (e.g., https://api.yourcompany.com)
    • Your SPEC2JIRA_API_KEY from your backend .env file
    • Your default Jira Project Key (e.g., PROJ)
  6. Click Save.
  7. Click Test Connection — you should see a green checkmark.

You're ready — open any Confluence specification page and click Generate Breakdown.

Commands Reference

CommandDescription
docker compose up -dStart backend
docker compose downStop backend
docker compose logs -fView live logs
docker compose restartRestart after config change
docker compose pull && docker compose up -dUpdate to latest version

Fine-Tuning (Optional)

Improve breakdown quality by training on your own specification data:

# 1. Install training dependencies (one-time, inside the container)
docker exec -it spec2jira-backend pip install -r /training/requirements-train.txt

# 2. Add training pairs to training/data/ (see training/README.md for format)

# 3. Run training (~10-15 minutes on L4)
docker exec -it spec2jira-backend python -m app.training.train_qwen

# 4. Update config to use fine-tuned model
#    Edit .env: set PIPELINE_MODE=finetuned

# 5. Restart
docker compose restart

Troubleshooting

docker gives "permission denied"

Run newgrp docker or log out and back in. Verify your user is in the docker group: groups.

nvidia-container-toolkit install fails with dependency conflict

Common on cloud GPU VMs with pre-installed NVIDIA packages. Check if the toolkit is already working: docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu22.04 nvidia-smi. If it works, skip the toolkit install step.

nvidia-smi works on host but docker run --gpus all fails

NVIDIA Container Toolkit is not installed or Docker was not restarted. Run: sudo nvidia-ctk runtime configure --runtime=docker && sudo systemctl restart docker.

setup.sh fails with "externally-managed-environment" error (Ubuntu 24.04)

Ubuntu 24.04 ships Python 3.12, which enforces PEP 668 — system Python cannot have packages installed via pip without an explicit override. The setup.sh script's pip install huggingface_hub step is blocked with this error message. The workaround is a one-time --break-system-packages flag, then re-run setup.sh:

pip3 install huggingface_hub --break-system-packages
./setup.sh

This flag is safe in this context — huggingface_hub is used only by setup.sh to download AI models from Hugging Face; the backend itself runs containerized in Docker and does not depend on the host's system Python state. setup.sh will recognize the dependency as already installed and proceed directly to model download.

"No space left on device" during Docker pull

You need at least 100 GB free. Check with df -h /. Clean Docker cache: docker system prune -af.

"Out of memory" during generation

Ensure no other GPU processes are running: nvidia-smi. The pipeline needs ~18 GB VRAM peak during inference — 16 GB GPUs are not sufficient.

Backend refuses to start (ValidationError)

If the container exits immediately with a Pydantic ValidationError mentioning SPEC2JIRA_API_KEY, your API key is either missing from .env or shorter than 16 characters. Generate one with openssl rand -base64 32 and add it to your .env file. See Step 4.1.

Health check returns 401 Unauthorized

This is expected. The /health endpoint requires authentication. Use: curl -H "Authorization: Bearer <your-api-key>" http://localhost:8000/health. If you get 401 with a valid key, verify the key in .env matches exactly (no trailing spaces or newlines).

Backend starts but health check fails

Models may still be loading. Wait 2 minutes and retry. Check logs: docker compose logs -f. Verify models exist: ls -la models/base/.

Backend unreachable from Confluence

Verify HTTPS works from an external machine: curl -H "Authorization: Bearer <your-api-key>" https://api.yourcompany.com/health. Verify firewall allows inbound port 443. If behind a corporate firewall, ensure Atlassian Cloud IPs can reach your server.

"Test Connection" fails with 403 error

Your backend domain may not yet be whitelisted in the Spec2Tickets Forge app. See Step 7. If you've already received whitelist confirmation, verify that the backend URL in your Forge app configuration exactly matches the domain you submitted.

"Test Connection" fails with "Unauthorized"

The API key in Forge app settings does not match the SPEC2JIRA_API_KEY in your backend .env. Copy the exact value from .env and paste into the Backend API Key field in Forge settings. Both must match character-for-character.

Pipeline runs time out (502 Bad Gateway)

Increase proxy_read_timeout in nginx to at least 1800s. Large specifications (5000+ words) can take 20–25 minutes to process.

"Model file not found" on startup

Run ./setup.sh again — the model download may have been interrupted. Verify: ls -la models/base/Qwen2.5-14B-Instruct-GGUF/.

Need help?

Contact support@spec2jira.com.

Data Privacy