Skip to main content

Quick Start

This local evaluation stores data in PostgreSQL, generates unique credentials, and listens only on your machine. Read Production Deployment before shared or remote use.

You need Docker with Compose v2, and network access from the machine you run this on to your Jira Data Center instance.

1. Save the compose file​

Save this as docker-compose.yml in an empty directory.

services:
postgres:
image: postgres:17-alpine
environment:
- POSTGRES_DB=riskscanner
- POSTGRES_USER=riskscanner
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?Create the one-time .env file first}
volumes:
- scanner-postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U riskscanner -d riskscanner"]
interval: 5s
timeout: 3s
retries: 20
networks:
- scanner-network

scanner:
image: arcsoftklg/sensitive-data-scanner:latest
depends_on:
postgres:
condition: service_healthy
ports:
# 8080 is the scanner. 8082 is Keycloak, published here because Keycloak
# shares this container's network namespace - see the note below.
- "127.0.0.1:8080:8080"
- "127.0.0.1:8082:8082"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/riskscanner
- SPRING_DATASOURCE_USERNAME=riskscanner
- SPRING_DATASOURCE_PASSWORD=${POSTGRES_PASSWORD:?Create the one-time .env file first}
- OIDC_ISSUER_URI=http://localhost:8082/realms/sensitive-data-scanner
- APP_BASE_URL=http://localhost:8080
- JIRA_CREDENTIAL_ENCRYPTION_KEY=${JIRA_CREDENTIAL_ENCRYPTION_KEY:?Create the one-time .env file first}
- FINDING_FINGERPRINT_HMAC_SECRET=${FINDING_FINGERPRINT_HMAC_SECRET:?Create the one-time .env file first}
restart: unless-stopped
networks:
- scanner-network

keycloak:
image: quay.io/keycloak/keycloak:26.1
# Keycloak runs inside the scanner's network namespace on purpose, so that
# http://localhost:8082 means the same thing to your browser and to the
# scanner. This service therefore declares no ports or networks of its own.
network_mode: "service:scanner"
depends_on:
- scanner
command: start-dev --import-realm --http-port=8082
environment:
- KC_BOOTSTRAP_ADMIN_USERNAME=keycloak
- KC_BOOTSTRAP_ADMIN_PASSWORD=${KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD:?Create the one-time .env file first}
- KC_HOSTNAME=http://localhost:8082
- KC_HOSTNAME_STRICT=false
- KC_HEALTH_ENABLED=true
configs:
- source: scanner-realm
target: /opt/keycloak/data/import/sensitive-data-scanner-realm.json
restart: unless-stopped

configs:
scanner-realm:
content: |
{
"realm": "sensitive-data-scanner",
"enabled": true,
"roles": {
"realm": [
{ "name": "ADMIN", "description": "Application administrator" },
{ "name": "USER", "description": "Authenticated application user" }
]
},
"clients": [
{
"clientId": "sensitive-data-scanner-frontend",
"name": "Sensitive Data Scanner Frontend",
"enabled": true,
"publicClient": true,
"protocol": "openid-connect",
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"redirectUris": ["http://localhost:8080/*"],
"webOrigins": ["http://localhost:8080"]
}
],
"users": [
{
"username": "admin",
"enabled": true,
"email": "admin@example.test",
"firstName": "Admin",
"lastName": "User",
"credentials": [{ "type": "password", "value": "${EVALUATION_ADMIN_PASSWORD:?Create the one-time .env file first}", "temporary": false }],
"realmRoles": ["ADMIN", "USER"]
},
{
"username": "user",
"enabled": true,
"email": "user@example.test",
"firstName": "Regular",
"lastName": "User",
"credentials": [{ "type": "password", "value": "${EVALUATION_USER_PASSWORD:?Create the one-time .env file first}", "temporary": false }],
"realmRoles": ["USER"]
}
]
}

networks:
scanner-network:
driver: bridge

volumes:
scanner-postgres-data:

2. Create the one-time local secrets​

Run this once in the same directory. Re-running it keeps the existing values, so stored credentials and finding identities remain readable after a restart.

umask 077
if [ ! -f .env ]; then
cat > .env <<EOF
POSTGRES_PASSWORD=$(openssl rand -hex 24)
JIRA_CREDENTIAL_ENCRYPTION_KEY=$(openssl rand -base64 32 | tr -d '\n')
FINDING_FINGERPRINT_HMAC_SECRET=$(openssl rand -hex 48)
KEYCLOAK_BOOTSTRAP_ADMIN_PASSWORD=$(openssl rand -hex 24)
EVALUATION_ADMIN_PASSWORD=$(openssl rand -hex 16)
EVALUATION_USER_PASSWORD=$(openssl rand -hex 16)
EOF
fi
chmod 600 .env

Keep .env with your database backup. Losing either scanner secret makes stored Jira credentials or finding identities unusable.

3. Start it​

docker compose up

The first start pulls three images and runs the database migrations, so give it a couple of minutes. It is ready when http://localhost:8080/actuator/health answers.

4. Sign in​

Open http://localhost:8080/ui/ and sign in as admin with the password shown by grep EVALUATION_ADMIN_PASSWORD .env.

The bundled Keycloak also has a non-admin user named user; its password is in EVALUATION_USER_PASSWORD if you want to see the read-only USER view.

Local evaluation only

The ports bind to loopback, but the bundled Keycloak still issues tokens over plain HTTP. For shared or remote access, use HTTPS and your real identity provider as described in Production Deployment.

5. Connect your Jira​

Go to Administration → Jira Connection and enter your Jira Data Center base URL and a service account. The account needs Browse Projects on the projects you want to scan and nothing more; the scanner only reads, through the REST API. See Jira Connection.

6. Run a scan​

Go to Scans and start one. The evaluation covers the first 1000 issues on a single worker. See Your First Scan.

What you get without a license​

With no license file installed, the scanner runs a five-day evaluation:

EvaluationLicensed
Issues per scan1000Unlimited
Scan workers1Configurable
Attachment contentsNot readWith the SCAN_ATTACHMENTS feature
Duration5 days from first usePer the license file

The License page shows the days remaining. When the evaluation ends, everything already scanned stays readable - findings, the audit log, CSV export - but no new scans start until a license is installed. The clock is anchored to the oldest data in the database rather than to a licence record, so clearing the licence table does not restart it.

See License and Pricing.

Next steps​

  1. Connect Jira
  2. Run your first scan
  3. Deploy it properly