Enterprise runtime

Your metal. Our images.

Stand Pravadh PM on any server you own. You get signed images and a license — never a line of our code, and never Labs payment or NVIDIA keys.

What you receive

Super Admin registers your hostname and sends a pack: LICENSE_KEY, compose, Kubernetes YAML, node-agent.sh, and a GitHub Packages pull token (read:packages). Images are ghcr.io/dhairyasalesforce/pravadh-pm-backend:stable and …-frontend:stable.

This page has no secrets. Ask Labs for the pack for your hostname. Public control plane: pravadhpm.pravadhlabs.com.

Never put these on your box

  • The GitHub repo, a zip of source, or any .py / .jsx files
  • Labs Razorpay keys, NVIDIA keys, or the Super Admin password
  • The hosted Pravadh PM .env from Labs servers

You generate

  • JWT_SECRET on the new box (python3 -c "import secrets; print(secrets.token_urlsafe(48))")
  • TLS for your hostname
  • Your copilot model key after first login (OpenAI, Claude, Cursor, or your proxy)

Pick a runtime

Any host that can run OCI images works. You do not unpack Python or React.

Option A

Docker Compose

Any Linux VM or Windows with Docker Desktop. Images listen on 127.0.0.1:8080. You put nginx, Caddy, Traefik, or a cloud load balancer in front.

Option B

Podman

Same compose file. No Docker daemon. node-agent.sh uses Podman when Docker is missing.

Option C

Kubernetes

Same two images. Secret from your .env. Ingress to your hostname. Labs never gets cluster credentials.

Option D

Air-gap

Pull and docker save the two images on a connected machine. Copy only the tar plus compose and .env. docker load on the dark server. Still no source.

Compose on a VM

  1. DNS: your hostname → this server.
  2. echo GHCR_TOKEN | docker login ghcr.io -u TOKEN_USER --password-stdin
  3. mkdir -p /opt/pravadh-pm && cd /opt/pravadh-pm
  4. Save .env from the pack. Replace JWT_SECRET. CORS must match https://your-host.
  5. Save docker-compose.yml and node-agent.sh, then chmod +x node-agent.sh.
  6. docker compose pull && docker compose up -d (or podman compose).
  7. Proxy 127.0.0.1:8080 with TLS. Hourly cron for node-agent.sh.
server {
    listen 80;
    server_name pm.yourcompany.com;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Authorization $http_authorization;
        client_max_body_size 20m;
    }
}

Then certbot, Caddy, or your load balancer. Kubernetes uses the YAML in the pack instead of this nginx block.

Kubernetes

  1. Save the YAML from the pack. Create namespace pravadh-pm.
  2. kubectl -n pravadh-pm create secret generic pravadh-pm --from-env-file=.env
  3. Create a GHCR docker-registry secret with the pull token Labs sent — not a GitHub repo token with write.
  4. kubectl apply -f kubernetes.yaml
  5. Point Ingress at service pravadh-pm:80. TLS is yours (cert-manager or a load balancer). Labs never gets cluster credentials.

Air-gap

# On a connected machine (images only — no git)
docker pull ghcr.io/dhairyasalesforce/pravadh-pm-backend:stable
docker pull ghcr.io/dhairyasalesforce/pravadh-pm-frontend:stable
docker save -o pravadh-pm-images.tar \
  ghcr.io/dhairyasalesforce/pravadh-pm-backend:stable \
  ghcr.io/dhairyasalesforce/pravadh-pm-frontend:stable

# Copy tar + compose + .env + node-agent.sh to the dark server
docker load -i pravadh-pm-images.tar
docker compose up -d

After it boots

Owner signs in, sets logo and colors, names the copilot, pastes their model key. Subscription, trial dates, and revoke stay with Pravadh Labs Super Admin. This box cannot change them. Unpaid or revoked = read-only. No heartbeat for 72 hours = lock.