Skip to main content

On-Premise Deployment: PanDev Metrics With Docker and Kubernetes in 30 Minutes

· 9 min read
Artur Pan
CTO & Co-Founder at PanDev

Not every company can send engineering data to the cloud. Regulated industries, government contractors, and security-conscious organizations need their metrics platform on-premise — inside their own network, on their own servers. According to the CNCF Annual Survey, over 80% of organizations now run Kubernetes in production, making container-based on-premise deployment a well-understood operational pattern.

PanDev Metrics supports full on-premise deployment via Docker Compose (for small teams) and Kubernetes with Helm (for larger organizations). This guide covers both paths, including LDAP authentication, TLS certificates, and persistent storage.

Architecture Overview

PanDev Metrics on-premise consists of these components:

┌─────────────────────────────────────────────┐
│ Load Balancer │
│ (nginx / traefik) │
└──────────────────┬──────────────────────────┘

┌─────────┴─────────┐
│ │
┌────────▼──────┐ ┌───────▼───────┐
│ Web App │ │ API Server │
│ (frontend) │ │ (backend) │
│ Port 3000 │ │ Port 8080 │
└───────────────┘ └───────┬───────┘

┌─────────────┼─────────────┐
│ │ │
┌────────▼──┐ ┌──────▼─────┐ ┌───▼────────┐
│ PostgreSQL │ │ Redis │ │ Webhook │
│ (primary │ │ (cache + │ │ Worker │
│ database) │ │ queues) │ │ (async │
│ Port 5432 │ │ Port 6379 │ │ processing│
└────────────┘ └────────────┘ └────────────┘
ComponentPurposeResources (minimum)
Web AppFrontend UI512 MB RAM, 0.5 CPU
API ServerREST API, webhook receiver1 GB RAM, 1 CPU
Webhook WorkerAsync processing of git events1 GB RAM, 1 CPU
PostgreSQLPrimary data store2 GB RAM, 1 CPU, 20 GB disk
RedisCaching, job queues512 MB RAM, 0.5 CPU

Minimum total: 5 GB RAM, 4 CPU cores, 25 GB disk for a team of up to 50 developers.

Option A: Docker Compose (Quick Start)

Best for teams under 50 developers or proof-of-concept deployments.

Prerequisites

  • Docker Engine 24+ and Docker Compose v2
  • A Linux server with 8 GB RAM and 4 CPU cores
  • A domain name pointing to the server (for TLS)

Step 1: Download the Compose File

mkdir -p /opt/pandev && cd /opt/pandev
curl -fsSL https://get.pandev-metrics.com/docker/docker-compose.yml -o docker-compose.yml
curl -fsSL https://get.pandev-metrics.com/docker/.env.example -o .env

Mail settings showing SMTP configuration for on-premise deployment Mail settings let you configure SMTP host, port, protocol, and sender email — essential for on-premise deployments where email notifications need to route through your internal mail server.

Step 2: Configure Environment Variables

Edit the .env file:

# .env — PanDev Metrics On-Premise Configuration

# === Required ===
PANDEV_LICENSE_KEY=your-license-key-here
PANDEV_DOMAIN=pandev.internal.company.com
PANDEV_ADMIN_EMAIL=admin@company.com
PANDEV_ADMIN_PASSWORD=change-me-immediately

# === Database ===
POSTGRES_PASSWORD=strong-random-password-here
POSTGRES_DB=pandev
REDIS_PASSWORD=another-strong-password

# === TLS ===
TLS_CERT_PATH=/opt/pandev/certs/fullchain.pem
TLS_KEY_PATH=/opt/pandev/certs/privkey.pem

# === Optional: LDAP ===
# LDAP_ENABLED=true
# LDAP_URL=ldaps://ldap.company.com:636
# LDAP_BASE_DN=dc=company,dc=com
# LDAP_BIND_DN=cn=pandev-svc,ou=service-accounts,dc=company,dc=com
# LDAP_BIND_PASSWORD=ldap-service-password
# LDAP_USER_FILTER=(uid={username})
# LDAP_CA_CERT_PATH=/opt/pandev/certs/ldap-ca.pem

Generate strong passwords:

openssl rand -base64 32 # Use for POSTGRES_PASSWORD
openssl rand -base64 32 # Use for REDIS_PASSWORD

Step 3: Add TLS Certificates

mkdir -p /opt/pandev/certs

# Option 1: Copy your corporate certificates
cp /path/to/fullchain.pem /opt/pandev/certs/
cp /path/to/privkey.pem /opt/pandev/certs/

# Option 2: Generate self-signed (for testing only)
openssl req -x509 -nodes -days 365 \
-newkey rsa:2048 \
-keyout /opt/pandev/certs/privkey.pem \
-out /opt/pandev/certs/fullchain.pem \
-subj "/CN=pandev.internal.company.com"

Step 4: Start the Stack

cd /opt/pandev
docker compose up -d

Watch the logs:

docker compose logs -f

You should see:

pandev-api | ✅ Database connected
pandev-api | ✅ Redis connected
pandev-api | ✅ Migrations applied
pandev-api | ✅ API server listening on :8080
pandev-web | ✅ Web app listening on :3000
pandev-worker | ✅ Webhook worker started, processing queue...
pandev-nginx | ✅ HTTPS on :443 → web:3000, api:8080

Step 5: Verify

Open https://pandev.internal.company.com in your browser. Log in with the admin email and password from your .env file.

Docker Compose Commands Reference

# Start
docker compose up -d

# Stop
docker compose down

# Update to latest version
docker compose pull && docker compose up -d

# View logs
docker compose logs -f [service-name]

# Backup database
docker compose exec postgres pg_dump -U pandev pandev > backup.sql

# Restore database
docker compose exec -T postgres psql -U pandev pandev < backup.sql

Option B: Kubernetes with Helm (Production)

Best for larger organizations, high availability requirements, or existing Kubernetes infrastructure.

Prerequisites

  • Kubernetes 1.26+
  • Helm 3.12+
  • kubectl configured for your cluster
  • A StorageClass for persistent volumes
  • An Ingress controller (nginx-ingress or Traefik)

Step 1: Add the Helm Repository

helm repo add pandev https://charts.pandev-metrics.com
helm repo update

Step 2: Create a Values File

# values-production.yaml

global:
domain: pandev.internal.company.com
licenseKey: "your-license-key-here"

api:
replicas: 2
resources:
requests:
memory: "1Gi"
cpu: "1000m"
limits:
memory: "2Gi"
cpu: "2000m"

web:
replicas: 2
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"

worker:
replicas: 2
resources:
requests:
memory: "1Gi"
cpu: "1000m"
limits:
memory: "2Gi"
cpu: "2000m"

postgresql:
enabled: true # Set to false if using external database
auth:
password: "strong-random-password"
database: pandev
primary:
persistence:
size: 50Gi
storageClass: "gp3" # Adjust for your cloud provider
resources:
requests:
memory: "2Gi"
cpu: "1000m"

redis:
enabled: true
auth:
password: "another-strong-password"
master:
persistence:
size: 5Gi

ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
tls:
- secretName: pandev-tls
hosts:
- pandev.internal.company.com

# LDAP Configuration (optional)
ldap:
enabled: false
# url: "ldaps://ldap.company.com:636"
# baseDN: "dc=company,dc=com"
# bindDN: "cn=pandev-svc,ou=service-accounts,dc=company,dc=com"
# bindPassword: "ldap-service-password"
# userFilter: "(uid={username})"
# caCert: |
# -----BEGIN CERTIFICATE-----
# ... your LDAP CA certificate ...
# -----END CERTIFICATE-----

Step 3: Create the Namespace and Secrets

kubectl create namespace pandev

# Create the license secret
kubectl create secret generic pandev-license \
--namespace pandev \
--from-literal=license-key=your-license-key-here

# If using external TLS certificates (not cert-manager)
kubectl create secret tls pandev-tls \
--namespace pandev \
--cert=/path/to/fullchain.pem \
--key=/path/to/privkey.pem

Step 4: Install

helm install pandev pandev/pandev-metrics \
--namespace pandev \
--values values-production.yaml

Watch the rollout:

kubectl -n pandev get pods -w

Expected output:

NAME READY STATUS RESTARTS AGE
pandev-api-7d4b8f9c6-abcde 1/1 Running 0 2m
pandev-api-7d4b8f9c6-fghij 1/1 Running 0 2m
pandev-web-5c6d7e8f9-klmno 1/1 Running 0 2m
pandev-web-5c6d7e8f9-pqrst 1/1 Running 0 2m
pandev-worker-3a4b5c6d7-uvwxy 1/1 Running 0 2m
pandev-worker-3a4b5c6d7-zabcd 1/1 Running 0 2m
pandev-postgresql-0 1/1 Running 0 2m
pandev-redis-master-0 1/1 Running 0 2m

Step 5: Verify

# Check the ingress
kubectl -n pandev get ingress

# Test API health
curl -k https://pandev.internal.company.com/api/health

# Expected response:
# {"status":"ok","version":"2.14.0","database":"connected","redis":"connected"}

LDAP/AD settings with Integration Connected badge The LDAP settings page shows your Active Directory integration status and configuration options.

LDAP Authentication

Both Docker and Kubernetes deployments support LDAP and LDAPS for user authentication.

Basic LDAP Setup

Enable LDAP in your configuration:

# Docker (.env)
LDAP_ENABLED=true
LDAP_URL=ldaps://ldap.company.com:636
LDAP_BASE_DN=dc=company,dc=com
LDAP_BIND_DN=cn=pandev-svc,ou=service-accounts,dc=company,dc=com
LDAP_BIND_PASSWORD=ldap-service-password
LDAP_USER_FILTER=(uid={username})
LDAP_EMAIL_ATTR=mail
LDAP_DISPLAY_NAME_ATTR=displayName

Custom CA Certificates

If your LDAP server uses a certificate signed by an internal CA:

# Docker: mount the CA cert
# In docker-compose.yml, add to the api service:
volumes:
- /opt/pandev/certs/ldap-ca.pem:/etc/ssl/certs/ldap-ca.pem:ro

# Set the environment variable
LDAP_CA_CERT_PATH=/etc/ssl/certs/ldap-ca.pem

For Kubernetes, include the CA certificate directly in values-production.yaml:

ldap:
enabled: true
url: "ldaps://ldap.company.com:636"
caCert: |
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiUMA0Gcz...
(paste your full CA certificate here)
-----END CERTIFICATE-----

LDAP Group Mapping

Map LDAP groups to PanDev roles:

LDAP_GROUP_BASE_DN=ou=groups,dc=company,dc=com
LDAP_ADMIN_GROUP=cn=engineering-leads,ou=groups,dc=company,dc=com
LDAP_MANAGER_GROUP=cn=team-leads,ou=groups,dc=company,dc=com
LDAP_USER_GROUP=cn=developers,ou=groups,dc=company,dc=com

Configuring Webhooks for On-Premise

When running on-premise, your git provider needs to send webhooks to your internal PanDev instance.

GitLab (Self-Managed)

If both GitLab and PanDev are on the same network, use the internal URL:

Webhook URL: https://pandev.internal.company.com/api/v1/gitlab/webhook

If GitLab can't reach PanDev directly, set up a network route or reverse proxy.

GitHub Enterprise

Same approach — point webhooks to your internal PanDev URL:

Webhook URL: https://pandev.internal.company.com/api/v1/github/webhook

Firewall Rules

Ensure these network paths are open:

Git Provider → PanDev API (port 443) # Webhooks
Developer machines → PanDev API (port 443) # IDE plugins
PanDev API → Git Provider API (port 443) # Data fetching
PanDev API → LDAP server (port 636) # Authentication

Backup and Recovery

Database Backup

Schedule daily backups:

# Docker
0 2 * * * docker compose -f /opt/pandev/docker-compose.yml exec -T postgres \
pg_dump -U pandev pandev | gzip > /opt/pandev/backups/pandev-$(date +\%Y\%m\%d).sql.gz

# Kubernetes
0 2 * * * kubectl -n pandev exec pandev-postgresql-0 -- \
pg_dump -U pandev pandev | gzip > /backups/pandev-$(date +\%Y\%m\%d).sql.gz

Full Recovery

# Docker
gunzip < /opt/pandev/backups/pandev-20260308.sql.gz | \
docker compose exec -T postgres psql -U pandev pandev

# Kubernetes
gunzip < pandev-20260308.sql.gz | \
kubectl -n pandev exec -i pandev-postgresql-0 -- psql -U pandev pandev

Upgrading

Docker

cd /opt/pandev
docker compose pull
docker compose up -d

Database migrations run automatically on startup.

Kubernetes

helm repo update
helm upgrade pandev pandev/pandev-metrics \
--namespace pandev \
--values values-production.yaml

Check the release notes before upgrading — major versions may require manual migration steps.

Monitoring

Health Endpoints

# API health
curl https://pandev.internal.company.com/api/health

# Detailed status
curl https://pandev.internal.company.com/api/health/detailed
# Returns: database latency, redis latency, queue depth, worker status

Prometheus Metrics

PanDev exposes a /metrics endpoint for Prometheus:

# prometheus.yml
scrape_configs:
- job_name: pandev
static_configs:
- targets: ['pandev.internal.company.com:443']
scheme: https
metrics_path: /api/metrics

Key metrics to monitor:

MetricAlert threshold
pandev_webhook_queue_depth> 1000
pandev_api_response_time_p99> 2s
pandev_database_connections_active> 80% of pool
pandev_worker_error_rate> 5%

Troubleshooting

IssueSolution
Database connection refusedCheck POSTGRES_PASSWORD matches in both the database and API config
LDAP authentication failsTest with ldapsearch from the PanDev server to verify connectivity and credentials
Webhooks timing outVerify firewall rules allow inbound traffic from your git provider
IDE plugins can't connectEnsure developers configure apiUrl to point to your on-premise instance, not the cloud URL
High memory usageIncrease PostgreSQL shared_buffers and work_mem in the Helm values or Docker Compose
Slow webhook processingScale up the worker replicas: helm upgrade --set worker.replicas=4 or adjust Docker Compose

Keep your engineering data on your infrastructure. Deploy PanDev Metrics on-premise with Docker or Kubernetes — full control, full privacy, same powerful dashboards. The Flexera 2024 State of the Cloud Report confirms that hybrid and on-premise deployments remain a top priority for enterprises managing sensitive data.

Try it yourself — free

Connect your IDE plugin in 2 minutes and see your real metrics. No credit card, no commitment.

Try Free