BeyondTrust/POV

← Back to dashboard

Onboarding troubleshooting

Audience: operator · Profile: both · Read this when: the dashboard will not start, will not pull, or will not let you in.

Part of the Onboarding Guide.

Onboarding script exits at preflight

WSL: docker pull fails with a certificate error

Symptom: docker pull postgres:16-alpine (or any image) fails with:

x509: certificate signed by unknown authority

Cause: Your network uses an SSL-inspection proxy (Zscaler, Palo Alto, etc.) that re-signs outbound TLS traffic with a corporate root CA. WSL does not inherit Windows' trusted root store, so Docker inside WSL rejects the intercepted certificate.

Fix — run once per WSL distro install:

Step 1 — identify and export the proxy root CA (PowerShell on Windows):

# List trusted roots — look for your security vendor (Zscaler, etc.)
Get-ChildItem Cert:\LocalMachine\Root | Select-Object Subject, Thumbprint | Sort-Object Subject

# Export the relevant cert (replace <Thumbprint> with the value above)
$cert = Get-ChildItem Cert:\LocalMachine\Root\<Thumbprint>
Export-Certificate -Cert $cert -FilePath "$env:TEMP\corp-root.cer" -Type CERT

If you are unsure which cert to export, export them all and let WSL sort it out:

New-Item -ItemType Directory -Force "$env:TEMP\roots" | Out-Null
Get-ChildItem Cert:\LocalMachine\Root | ForEach-Object {
    Export-Certificate -Cert $_ `
        -FilePath "$env:TEMP\roots\$($_.Thumbprint).cer" -Type CERT
}

Step 2 — import into WSL and update the system trust store:

# Single cert
openssl x509 -inform DER \
    -in /mnt/c/Users/$(cmd.exe /c echo %USERNAME% 2>/dev/null | tr -d '\r')/AppData/Local/Temp/corp-root.cer \
    -out /tmp/corp-root.pem
sudo cp /tmp/corp-root.pem /usr/local/share/ca-certificates/corp-root.crt
sudo update-ca-certificates

If you exported all certs, convert and import them in a loop:

WINTEMP="/mnt/c/Users/$(cmd.exe /c echo %USERNAME% 2>/dev/null | tr -d '\r')/AppData/Local/Temp/roots"
sudo mkdir -p /usr/local/share/ca-certificates/windows-roots
for f in "$WINTEMP"/*.cer; do
    name=$(basename "$f" .cer)
    openssl x509 -inform DER -in "$f" \
        -out "/usr/local/share/ca-certificates/windows-roots/$name.crt" 2>/dev/null || true
done
sudo update-ca-certificates

Step 3 — add the cert to Docker's registry trust store:

sudo mkdir -p /etc/docker/certs.d/registry-1.docker.io
sudo cp /tmp/corp-root.pem /etc/docker/certs.d/registry-1.docker.io/ca.crt
sudo service docker restart

Verify host-side pulls work:

docker pull hello-world

Step 4 — make the cert available inside the image build:

Steps 1–3 fix the host's connection to Docker Hub, but apt-get update and pip install inside the image build go through the same TLS-inspecting proxy and need the cert too. Drop a copy into corp-ca/ at the repo root:

cp /tmp/corp-root.pem ./corp-ca/corp-root.crt

The Dockerfile copies any .crt / .pem file in corp-ca/ into the image's system trust store and points pip, requests, and curl at it. Files in that directory are gitignored, so your cert stays local.

Now rerun ./scripts/onboard.sh --build.

Step 5 — (--hub only) trust the cert inside the published container:

The published image is built by CI on a clean network, so it carries no corp CA — and unlike the build path, there's no image build to inject it into. That's fine until a feature makes outbound TLS calls from inside the container: Terraform-backed provisioning (cloud databases) runs terraform init, which fetches providers from registry.terraform.io and fails with:

terraform init failed: ... x509: certificate signed by unknown authority

Fix: start the hub stack with the corp-CA overlay, which bind-mounts the host's system CA bundle (updated in step 2 above) read-only over the container's, and sets AWS_CA_BUNDLE for boto3:

./scripts/onboard.sh --hub --corp-ca
# or manually:
docker compose -f docker-compose.hub.yml -f docker-compose.corp-ca.yml up -d

On a non-Linux host (no /etc/ssl/certs/ca-certificates.crt), point CORP_CA_BUNDLE at a PEM file containing the public roots plus your corp CA.

Stack starts but /api/health doesn't respond

docker compose logs --tail 100 app

Common causes:

Symptom in logs Likely cause Fix
InvalidClientTokenId / InvalidSignature AWS access key wrong or rotated Rerun aws iam create-access-key, then update via the reconfigure wizard (/setup)
AuthenticationFailed from Azure Azure SP secret wrong or expired Regenerate with az ad sp credential reset, then update via the reconfigure wizard (/setup)
connection refused on port 5432 Postgres container not healthy docker compose ps; check db container logs
Address already in use on 8001 Another process is bound to 8001 Stop it, or change the port mapping in docker-compose.yml

Login fails with "Invalid credentials"

JWT key file: backup and loss recovery

.jwt_secret_key at the repo root is the root of trust for all credentials you store through the setup wizard. The app uses it to encrypt every integration secret (AWS keys, Azure SP credentials, etc.) in the database.

It cannot be migrated to a vault in the community edition — it's the bootstrap key that decrypts everything (including any vault credentials), so it must be present at startup from the host. See Protect and back up the JWT key above and why. (Removing the on-disk key via cloud workload identity is a SaaS-edition feature.)

Protect it: back it up somewhere safe (password manager, encrypted drive), and don't commit it to git (it's in .gitignore).

If you lose it, every stored credential is unrecoverable and the app will refuse to start (the key file is required). Recovery procedure:

# 1. Stop the stack
docker compose down

# 2. Remove the old key and database volume (⚠ wipes all stored credentials)
rm .jwt_secret_key
docker volume rm vm-dashboard-community_pgdata   # adjust prefix to match 'docker volume ls'

# 3. Rerun the onboard script — it regenerates the key and the wizard reappears
./scripts/onboard.sh

Rotating the key is not currently supported without clearing the database.

Where to file issues

Open a GitHub issue with:

  1. The output of .\scripts\Onboard-Dashboard.ps1 (copy the terminal)
  2. The last 100 lines of docker compose logs app
  3. Your OS / Docker Desktop / PowerShell versions
  4. What you expected vs. what happened

Do not paste .env contents — they contain your cloud credentials.