Skip to main content
Version: v2 (current)

Install PanDev Metrics on-prem

TL;DR. This guide walks an admin through a fresh on-prem install of PanDev Metrics with Docker Compose in about 60 minutes. By the end you have a running backend on port 8080, a frontend behind your reverse proxy, PostgreSQL 17 on a separate host, and a verified health check. Audience: admin.

Before you begin

  • Two Linux hosts that meet the system requirements: one for backend + frontend, one for PostgreSQL (Redis is optional — needed only when you want to share sessions horizontally)
  • Docker Engine ≥ 20.10 and Docker Compose ≥ v2.0 (v2.20+ recommended) installed on the application host
  • PostgreSQL 17 available — either installed on the database host or running as a managed instance reachable from the application host
  • A reachable hostname and TLS certificate for the public endpoint (PanDev Metrics can also work with a self-signed certificate plus client-side validation disabled)
  • Outbound HTTPS access to your Git provider and task tracker — egress is minimal but cannot be disabled
  • The PanDev Metrics distribution archive from your account manager
warning

PanDev Metrics on-prem is a single-organization deployment. Do not plan around multi-tenant separation — that capability is Cloud-only. Air-gapped deployments are not supported.

Step 1 — Prepare the database host

Install PostgreSQL 17 on the dedicated database host. Create a database, a role, and grant ownership:

psql on the database host
CREATE ROLE pandev WITH LOGIN PASSWORD '<STRONG_DB_PASSWORD>';
CREATE DATABASE pandev_metrics OWNER pandev;
GRANT ALL PRIVILEGES ON DATABASE pandev_metrics TO pandev;

Allow connections from the application host in pg_hba.conf and reload PostgreSQL. PanDev Metrics applies its schema and Flyway migrations automatically on first start — you do not need to seed tables manually.

Step 2 — Prepare the application host

Create a working directory and place the distribution archive into it:

terminal
sudo mkdir -p /opt/pandev
sudo chown "$USER":"$USER" /opt/pandev
cd /opt/pandev
unzip /tmp/pandev_metrics_latest.zip -d .

The archive contains docker-compose.yml, an .env.example file, and supporting configuration. Copy the example into a real .env file you will edit in the next step:

terminal
cp .env.example .env

Step 3 — Configure environment variables

Open .env and set the values for your environment. The minimum set you need to change for a fresh install:

VariablePurposeExample
DB_URLJDBC URL of your PostgreSQL 17 databasejdbc:postgresql://db.internal:5432/pandev_metrics
DB_USERNAMEDatabase user created in Step 1pandev
DB_PASSWORDDatabase user password<STRONG_DB_PASSWORD>
DB_SCHEMASchema for PanDev tablespublic
SPRING_DATA_REDIS_HOSTRedis hostname (optional — only set when Redis is deployed)redis
SPRING_DATA_REDIS_PORTRedis port (optional)6379
SERVER_PORTBackend HTTP port8080
AI_AGENT_DB_PASSWORDPassword for the read-only AI database role (reserved for future use; set a strong value anyway)<STRONG_AI_DB_PASSWORD>
APPLICATION_IS_CLOUDHard-coded marker for on-premfalse
GOOGLE_AUTH_ENABLEGoogle sign-in is Cloud-only — keep disabledfalse
LOG_LEVELLog verbosityINFO
warning

Treat .env as a secret. Restrict it to chmod 600 and keep it out of version control. Do not reuse passwords between DB_PASSWORD and AI_AGENT_DB_PASSWORD.

LDAP variables are not required for the initial start — you can configure LDAP from the UI after first login. See LDAP integration for the full variable list and behavior.

Step 4 — Pull images and start the stack

Pull the images referenced in docker-compose.yml from your registry, then start the stack:

terminal
docker compose pull
docker compose up -d

On first start, the backend runs Flyway migrations against the empty database. Expect 1–3 minutes before the application is ready. Tail the logs to watch progress:

terminal
docker compose logs -f pandev-metrics

You should see lines from org.flywaydb.core.internal.command.DbMigrate followed by Spring startup messages ending with Started PandevApplication.

Step 5 — Verify the install

Run the actuator health check from the application host. Expect a 200 OK with "status":"UP":

terminal
curl -fsS http://localhost:9090/actuator/health | jq '.status'
# → "UP"

Check that the frontend is reachable through your reverse proxy on its public hostname. You should see the PanDev Metrics login screen. The first admin is created during initial setup — follow First login.

Step 6 — Configure the reverse proxy and TLS

Terminate TLS at your reverse proxy. A minimal Nginx server block looks like this:

/etc/nginx/conf.d/pandev.conf
server {
listen 443 ssl http2;
server_name metrics.example.com;

ssl_certificate /etc/ssl/certs/pandev.crt;
ssl_certificate_key /etc/ssl/private/pandev.key;

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;
}
}

PanDev Metrics can also work directly with a self-signed certificate by disabling client-side SSL validation. See Network and ports.

Troubleshooting

Backend exits with `FATAL: password authentication failed for user "pandev"`

The DB_PASSWORD in .env does not match the role you created in Step 1. Recreate the role with the correct password, or update .env and run docker compose up -d --force-recreate pandev-metrics.

Flyway fails with `ERROR: permission denied for schema public`

The role from Step 1 is not the owner of the database. Run ALTER DATABASE pandev_metrics OWNER TO pandev; from a superuser session, then restart the backend.

`/actuator/health` returns `DOWN` with `redis` as the failing component

The backend cannot reach Redis. Check that the Redis container is up (docker compose ps redis) and that SPRING_DATA_REDIS_HOST matches the service name in docker-compose.yml.

Login screen loads but API requests fail with mixed-content or CORS errors

The reverse proxy is not forwarding X-Forwarded-Proto correctly. Make sure the Nginx block in Step 6 includes proxy_set_header X-Forwarded-Proto $scheme; and restart Nginx.

Container restarts in a loop with `OutOfMemoryError`

The application host has less RAM than recommended. Increase the host to at least 16 GB RAM as specified in the system requirements, or set a Docker memory limit and Java heap accordingly via JAVA_OPTS=-Xmx12g.

FAQ

Can I run the database on the same host as the backend?

You can for a small evaluation, but for production we recommend a dedicated database host with the sizing in system requirements. The application host and the database host benefit from independent CPU, memory, and disk profiles, and updates are simpler when they are separate.

Do I need to pre-create database tables?

No. The backend runs Flyway migrations automatically on first start and on every upgrade. You only need to create the empty database and the owning role described in Step 1.

How do I upgrade to a newer version?

Replace the image tags in docker-compose.yml (or in your Helm chart) and run docker compose pull && docker compose up -d. Flyway applies any pending schema changes on startup. Take a pg_dump backup first — see backups below.

Can I disable outbound network access?

No. PanDev Metrics needs minimal outbound HTTPS to talk to your Git provider, task tracker, and other configured integrations. Egress is minimal but cannot be disabled. Air-gapped deployments are not supported.

Which Kubernetes versions are supported?

PanDev Metrics runs on Kubernetes >= 1.28. The Helm chart is shipped alongside the Docker Compose distribution. The configuration shape is identical — the same env vars from Step 3 apply.

Backups and disaster recovery

For backups, a regular pg_dump of the PanDev Metrics database is sufficient — continuous archiving is not required. Schedule the dump from the database host and store the output in your existing backup system:

terminal (database host)
pg_dump -Fc -U pandev pandev_metrics > pandev_metrics_$(date +%F).dump

Disaster recovery RPO and RTO are set by your operational policy. PanDev Metrics does not prescribe a target — restore the database with pg_restore, restart the stack with docker compose up -d, and migrations align automatically.

Next steps