Manage an On-Premises Deployment
The on-premises installer is available to Enterprise customers with an on-premises license. To get a license, contact Permit.io.
This page is for operators who run a self-hosted Permit Platform on Kubernetes. It covers day-2 operations: signing in, checking health, applying configuration changes, scaling, backing up, upgrading, rotating certificates, collecting a support bundle, and uninstalling. For every values.yaml key and installer flag, see the on-premises reference. For fixes to specific errors, see on-premises troubleshooting.
Before you begin
- Install Permit Platform with the installation guide.
- Configure
kubectlandhelmwith access to the cluster and the Permit Platform namespace. - Run the commands on this page from the root of the extracted installer package. The package contains the
charts/permit-platform/andscripts/directories.
The commands use the default namespace, permit-platform. If you installed with --namespace, replace permit-platform with your namespace. The installer deploys three Helm releases into that namespace: third-party-services, migrations, and permit-platform.
Several procedures on this page re-run the installer, and every one of them shows --gke --skip-images. Replace those flags with the flags you installed with: --gke for any existing Kubernetes cluster, --openshift for OpenShift, or --kind for a local Kind cluster. A run with no target flag takes the Kind path and fails on an existing cluster, so never drop the target flag. See Installer command reference.
Sign in and reach the platform
Open the Permit frontend
Open https:// plus the domain you set in global.frontendDomain, and sign in with the admin username and the admin password from the end of the installation output. A successful sign-in opens the Permit Policy Editor.
The installer generates the admin password and prints it at the end of the installation. The installer stores the password in the global-infrastructure-secret secret under the KEYCLOAK_ADMIN_PASSWORD key. To read it again:
# Retrieve admin password
kubectl get secret global-infrastructure-secret -n permit-platform \
-o jsonpath='{.data.KEYCLOAK_ADMIN_PASSWORD}' | base64 -d
Older installations can keep the admin password in a keycloak-admin-secret secret under the password key. The installer reads that secret as a fallback when global-infrastructure-secret has no admin password.
Management dashboards
The ingress routes your domain to the Permit frontend. Keycloak, the identity provider that handles sign-in, is served under /auth on the same domain.
| Service | URL | Credentials | Purpose |
|---|---|---|---|
| Permit frontend | https://your-domain.com | Admin user and the generated password | Manage policies, users, and environments |
| Keycloak admin console | https://your-domain.com/auth | Admin user and the generated password | Manage authentication and identities |
Retrieve service credentials
The installer generates the passwords for Keycloak, RabbitMQ, and PostgreSQL and stores them in global-infrastructure-secret. When you run the installer again, it reuses the passwords already in that secret.
# Keycloak admin password
kubectl get secret global-infrastructure-secret -n permit-platform \
-o jsonpath='{.data.KEYCLOAK_ADMIN_PASSWORD}' | base64 -d
# RabbitMQ password
kubectl get secret global-infrastructure-secret -n permit-platform \
-o jsonpath='{.data.RABBITMQ_PASSWORD}' | base64 -d
# PostgreSQL password
kubectl get secret global-infrastructure-secret -n permit-platform \
-o jsonpath='{.data.POSTGRES_PASSWORD}' | base64 -d
Reach a local or OpenShift domain
When your domain has no DNS record, such as a Kind cluster or a .local domain, map the domain to 127.0.0.1 in your hosts file:
# macOS/Linux
echo "127.0.0.1 your-configured-domain.local" | sudo tee -a /etc/hosts
# Windows (PowerShell as Administrator)
Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "127.0.0.1 your-configured-domain.local"
On OpenShift ROSA, find the router hostname, resolve it to an IP address, and map your domain to that IP address:
# Get OpenShift router IP
oc get svc -n openshift-ingress router-default -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'
# Add to /etc/hosts
echo "[router-ip] your-configured-domain.com" | sudo tee -a /etc/hosts
Check service health
List the pods and confirm that each one shows Running with all containers ready (for example, 1/1). Migration job pods show Completed.
# Check all pods status
kubectl get pods -n permit-platform
# Backend health check (prints: true)
kubectl exec -n permit-platform deployment/permit-backend-v2 -- \
python3 -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8000/v2/healthy').read().decode())"
# Frontend reachability through the ingress (prints an HTTP status code, 200 when the frontend serves the page)
curl -k -s -o /dev/null -w '%{http_code}\n' https://your-domain.com/
Change the platform configuration
Configuration file
All platform settings live in charts/permit-platform/values.yaml in the installer package. The values.yaml reference lists every section. The examples below cover the most common changes.
Required settings
Set the frontend domain and the policy sync repository before the first installation. The installer stops with an error when frontendDomain still contains CHANGEME_FRONTEND_DOMAIN. Write sshPrivateKey as a multi-line block with |. The chart fails to render when the key is on one line.
# Must be configured before installation
global:
frontendDomain: "permit.yourcompany.com" # REQUIRED - Replace CHANGEME_FRONTEND_DOMAIN
permitServices:
policySync:
enabled: true
policyRepoUrl: "git@github.com:yourorg/permit-policies.git" # REQUIRED
sshPrivateKey: | # REQUIRED
-----BEGIN OPENSSH PRIVATE KEY-----
[Your SSH private key]
-----END OPENSSH PRIVATE KEY-----
Common customizations
Pull images from a private registry. Set global.imageRegistry to the registry you pushed the images to:
global:
imageRegistry: "myregistry.company.com" # Your private registry
# Or for cloud providers:
# imageRegistry: "123456789.dkr.ecr.region.amazonaws.com" # AWS ECR
# imageRegistry: "myregistry.azurecr.io" # Azure
# imageRegistry: "gcr.io/project-id" # GCP
Scale a Permit service and set its CPU and memory. Each service under permitServices accepts replicas and resources:
permitServices:
backend:
replicas: 3 # Scale backend for high availability
resources:
requests:
memory: "2Gi"
cpu: "1000m"
limits:
memory: "4Gi"
cpu: "2000m"
Increase storage for PostgreSQL and for OpenSearch, which stores audit logs. The chart reads persistence.size. The chart doesn't set a storage class, so the volumes use the cluster's default storage class. Kubernetes can only expand an existing volume when the storage class allows volume expansion.
thirdPartyServices:
postgres:
persistence:
size: "50Gi" # Increase for production
opensearch:
persistence:
size: "100Gi" # For production audit logs
Tune OpenSearch shards, replicas, and index rollover for the audit log index:
thirdPartyServices:
opensearch:
indexSettings:
auditLogs:
numberOfShards: 1 # Single-node: 1, Multi-node: 3-5
numberOfReplicas: 0 # Single-node: 0, HA: 1+
ism:
rollover:
minSize: "50gb" # Adjust based on volume
minAge: "30d" # Retention period
Apply configuration changes
The recommended way to apply a values.yaml change is to run the installer again with the same flags you installed with. The installer runs helm upgrade --install for all three releases, keeps the passwords already stored in the cluster, and saves a copy of values.yaml as values.yaml.backup.<timestamp> before it writes generated passwords into the file.
To upgrade the releases one at a time, use Helm directly. The installer passes more --set flags to each release than the commands below. Compare them with scripts/install-permit-platform.sh in your package before you use them in production.
# 1. Update third-party services (PostgreSQL, Redis, OpenSearch, RabbitMQ, Keycloak)
helm upgrade third-party-services charts/permit-platform \
--set permitServices.enabled=false \
--set thirdPartyServices.enabled=true \
-n permit-platform
# 2. Run migrations (database schema updates)
helm upgrade migrations charts/permit-platform \
--set permitServices.enabled=false \
--set thirdPartyServices.enabled=false \
--set migrations.enabled=true \
--set migrations.tag=<backend-image-tag> \
--set ingress.enabled=false \
--set secrets.enabled=false \
-n permit-platform
# 3. Update platform services (the Permit application services)
helm upgrade permit-platform charts/permit-platform \
--set permitServices.enabled=true \
-n permit-platform
# Check status of all deployments
kubectl rollout status deployment -n permit-platform
# Verify changes
helm list -n permit-platform
kubectl get pods -n permit-platform
The change is applied when helm list shows each release with status deployed and every pod is Running.
Inspect the running configuration
Environment variables
View the environment variables of a running deployment. To change them, edit values.yaml and run the installer again.
# View current configuration in backend deployment
kubectl describe deployment permit-backend-v2 -n permit-platform | grep -A 20 "Environment:"
# Update environment variables via values.yaml
vi charts/permit-platform/values.yaml
./scripts/install-permit-platform.sh --gke --skip-images # Re-apply configuration (use the flags you installed with)
# Check if configuration was applied
kubectl get deployment permit-backend-v2 -n permit-platform -o yaml | grep -A 10 env:
ConfigMaps and secrets
List the ConfigMaps and secrets in the namespace, or edit a deployment in place:
# View all configmaps
kubectl get configmaps -n permit-platform
# View all secrets (for environment variables)
kubectl get secrets -n permit-platform
# Edit configuration directly (advanced users only)
kubectl edit deployment permit-backend-v2 -n permit-platform
The next installer run or helm upgrade renders the deployments from values.yaml again. Changes you make with kubectl edit, kubectl patch, or kubectl scale are overwritten at that point. Put permanent changes in values.yaml.
Run daily operations
Check platform health
# Check all pods status
kubectl get pods -n permit-platform
# Get detailed pod information
kubectl describe pods -n permit-platform
# Check service endpoints
kubectl get services -n permit-platform
# View recent events
kubectl get events -n permit-platform --sort-by='.lastTimestamp'
View service logs
permit-backend-v2 is the Permit API service. Replace it with another deployment name to read that service's logs. Use --previous to read the logs of a container that crashed and restarted.
# View backend logs
kubectl logs -n permit-platform deployment/permit-backend-v2 --tail=100
# Follow logs in real-time
kubectl logs -n permit-platform deployment/permit-backend-v2 -f
# View logs for crashed pods
kubectl logs -n permit-platform <pod-name> --previous
# Export all logs (every pod with an app label)
kubectl logs -n permit-platform --selector=app --all-containers=true --prefix --tail=-1 > platform-logs.txt
Restart services
# Restart specific service
kubectl rollout restart deployment/permit-backend-v2 -n permit-platform
# Restart all services
kubectl rollout restart deployment -n permit-platform
# Check restart status
kubectl rollout status deployment/permit-backend-v2 -n permit-platform
The restart is complete when kubectl rollout status reports that the deployment is successfully rolled out.
Monitor resource usage
kubectl top needs the Kubernetes Metrics Server in the cluster. Without the Metrics Server, kubectl top reports that the metrics API is not available, and the kubectl get and kubectl describe commands still work.
A healthy platform shows every service pod Running with all containers ready, an endpoint for every service, and pod memory below the limits.memory you set in values.yaml. A pod at its memory limit is restarted by Kubernetes with reason OOMKilled, which kubectl describe pod reports.
Pod and service health
# Monitor pod health and resource usage
kubectl top pods -n permit-platform
# Check all services health
kubectl get pods,svc,ingress -n permit-platform
# Check service endpoints and connectivity
kubectl get endpoints -n permit-platform
Resource consumption
# Resource utilization across all services
kubectl top pods -n permit-platform --sort-by=memory
kubectl top nodes
# Check resource limits vs usage
kubectl describe nodes | grep -A 5 "Allocated resources"
# Monitor specific service performance
kubectl logs -n permit-platform deployment/permit-backend-v2 --tail=100 | grep -E "(ERROR|WARN|response_time)"
Scale services
For a permanent change, set replicas and resources for the service in values.yaml (see Common customizations). Use kubectl scale and kubectl patch for a temporary change only. The next installer run resets both to the values in values.yaml.
Add replicas
# Scale backend services
kubectl scale deployment permit-backend-v2 -n permit-platform --replicas=3
# Scale worker processes
kubectl scale deployment celery-general -n permit-platform --replicas=2
# Scale OPAL components
kubectl scale deployment opal-server -n permit-platform --replicas=2
kubectl scale deployment permit-opal-relay-consumer-v2 -n permit-platform --replicas=2
# Check scaling status
kubectl get deployments -n permit-platform
Change CPU and memory
# Update resource requests and limits
kubectl patch deployment permit-backend-v2 -n permit-platform -p='{"spec":{"template":{"spec":{"containers":[{"name":"permit-backend-v2","resources":{"requests":{"memory":"2Gi","cpu":"1000m"},"limits":{"memory":"4Gi","cpu":"2000m"}}}]}}}}'
# View current resource usage
kubectl top pods -n permit-platform
# Check resource quotas and limits
kubectl describe deployment permit-backend-v2 -n permit-platform | grep -A 10 "Limits\|Requests"
Manage the policy Git repository
Permit Platform syncs policies with the Git repository set in permitServices.policySync.policyRepoUrl. The permit-policy-sync-v2 service handles the sync, and the Open Policy Administration Layer (OPAL) server, opal-server, distributes policy updates.
Check policy sync
# Check policy sync pod status
kubectl get pods -n permit-platform -l app=permit-policy-sync-v2
# View policy sync logs
kubectl logs -n permit-platform deployment/permit-policy-sync-v2
# Check OPAL server status (coordinates policy distribution)
kubectl logs -n permit-platform deployment/opal-server
# Restart policy sync if needed
kubectl rollout restart deployment/permit-policy-sync-v2 -n permit-platform
Change the repository or SSH key
The chart reads the repository URL from permitServices.policySync.policyRepoUrl and the deploy key from permitServices.policySync.sshPrivateKey in values.yaml. The chart passes both values to the permit-policy-sync-v2 deployment as environment variables. To change either one, edit values.yaml and run the installer again.
# Update Git repository configuration in values.yaml
vi charts/permit-platform/values.yaml
# Re-apply configuration (use the flags you installed with)
./scripts/install-permit-platform.sh --gke --skip-images
# Restart services to pick up new configuration
kubectl rollout restart deployment/permit-policy-sync-v2 -n permit-platform
kubectl rollout restart deployment/opal-server -n permit-platform
Back up and restore
Create backups
Back up before every upgrade and before any manual database change. The commands below save the Permit database, values.yaml, all secrets, and the persistent volume claim (PVC) definitions.
# Database backup using kubectl
kubectl exec -n permit-platform deployment/postgres -- pg_dump -U permit permit > backup-$(date +%Y%m%d-%H%M%S).sql
# Backup configuration (values.yaml)
cp charts/permit-platform/values.yaml values-backup-$(date +%Y%m%d-%H%M%S).yaml
# Backup all secrets
kubectl get secrets -n permit-platform -o yaml > secrets-backup-$(date +%Y%m%d-%H%M%S).yaml
# Backup persistent volume claims
kubectl get pvc -n permit-platform -o yaml > pvc-backup-$(date +%Y%m%d-%H%M%S).yaml
The backup is complete when all four files exist in the current directory and the .sql dump is not empty. Confirm the dump with tail -2 backup-<timestamp>.sql: a pg_dump run that finished ends the file with the line -- PostgreSQL database dump complete.
The backups have these limits:
- Keycloak data isn't in the Permit database dump. Keycloak stores its data in a separate
keycloak-postgresdeployment. Dump it withkubectl exec -n permit-platform deploy/keycloak-postgres -- pg_dump -U keycloak keycloak > keycloak-backup.sql. - The PVC export saves claim definitions, not the data on the volumes. Use your storage provider's snapshots to back up volume data, such as OpenSearch audit logs.
kubectl get secrets -o yaml writes the passwords base64-encoded, which anyone can decode. Anyone with the file can sign in to Keycloak and connect to the databases. Store the file encrypted, and restrict access to it.
Restore from a backup
Replace the timestamps in the file names with the timestamp of your backup.
# List available backups
ls -la *backup*.{sql,yaml}
# Restore database from backup
kubectl exec -i -n permit-platform deployment/postgres -- psql -U permit -d permit < backup-20241201-143022.sql
# Restore configuration
cp values-backup-20241201-143022.yaml charts/permit-platform/values.yaml
./scripts/install-permit-platform.sh --gke --skip-images # Re-apply configuration (use the flags you installed with)
The restore succeeded when psql reports no errors, helm list -n permit-platform shows all three releases with status deployed, every pod is Running, and you can sign in to the Permit frontend and see your policy.
psql applies the dump into the live database while the Permit services hold open connections and caches. Scale the Permit services to zero before you restore (see Stop and start services for planned maintenance), restore, then run the installer again to bring the services back with the replica counts from values.yaml.
Upgrade Permit Platform
Upgrade to a new installer version
- Back up the platform.
- Extract the new installer package.
- Copy your settings from your current
values.yamlinto the new package'scharts/permit-platform/values.yaml. Compare the two files instead of overwriting the new one, because the new file can contain new keys. - Run the installer with the flags you used for the first installation. The installer upgrades the existing releases.
# Extract new version package
tar -xzf permit-platform-on-prem-installer-<new-version>.tar.gz
cd permit-platform-on-prem-installer-<new-version>
# Backup current configuration
cp /path/to/current/charts/permit-platform/values.yaml ./values-backup.yaml
# Update configuration with your settings
vi charts/permit-platform/values.yaml
# Run installation (automatically upgrades existing deployment; use the flags you installed with)
./scripts/install-permit-platform.sh --gke --skip-images
# Verify upgrade completed successfully
kubectl get pods -n permit-platform
helm list -n permit-platform
The upgrade succeeded when helm list shows third-party-services, migrations, and permit-platform with status deployed and every pod is Running.
When the new package contains a different Keycloak version, Keycloak migrates its database schema on first start. The schema migration can't be rolled back, and sign-in is unavailable while it runs. Dump the keycloak-postgres database first (see Create backups) and schedule a maintenance window. The installer asks you to confirm the migration. For a non-interactive run, pass --yes.
Roll back a release
helm rollback returns the permit-platform release to an earlier revision. It doesn't reverse database schema changes from the migrations release or from Keycloak. To return data to its state before an upgrade, restore from a backup.
# Rollback using Helm (most recent release)
helm rollback permit-platform -n permit-platform
# Rollback to specific release number
helm history permit-platform -n permit-platform
helm rollback permit-platform 3 -n permit-platform
# Check rollback status
helm status permit-platform -n permit-platform
kubectl get pods -n permit-platform
Rotate certificates and passwords
Replace the TLS certificate
The ingress reads its certificate from the secret named in ingress.tls.secretName. The installer names it permit-frontend-tls. The last command restarts the NGINX ingress controller. If you use another ingress controller, restart that controller instead.
# Check current TLS certificate
kubectl get secret permit-frontend-tls -n permit-platform -o yaml
# Check certificate expiration
kubectl get secret permit-frontend-tls -n permit-platform -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -dates
# Update TLS certificate
kubectl create secret tls permit-frontend-tls -n permit-platform \
--cert=./new-cert.pem \
--key=./new-key.pem \
--dry-run=client -o yaml | kubectl apply -f -
# Restart ingress to pick up new certificate
kubectl rollout restart deployment/ingress-nginx-controller -n ingress-nginx
The certificate is replaced when the openssl x509 -noout -dates command prints the new expiration date.
Rotate passwords
The installer generates the PostgreSQL, RabbitMQ, Keycloak admin, and Keycloak database passwords on the first install and stores all four in the global-infrastructure-secret secret. Every later installer run reads the four values out of that secret and reuses them, so an installer run never rotates a password.
Read the current values with the commands in Retrieve service credentials.
A password lives in two places: the global-infrastructure-secret secret, and the account inside PostgreSQL, RabbitMQ, or Keycloak. kubectl patch or kubectl edit changes only the secret. The Permit services then present the new value to an account that still has the old password, and they fail to connect until you set both sides to the same value in the same maintenance window.
A rotation therefore means changing the account inside each service and the secret together, in an order that depends on which services your installation runs and how it terminates connections. Permit support plans that order with you. Open a rotation request with Permit support, and attach a support bundle and the list of credentials you need rotated.
Audit pod security settings
# Check pod security context
kubectl get pods -n permit-platform -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.securityContext}{"\n"}{end}'
# Review service account permissions
kubectl describe serviceaccount -n permit-platform
# Check for privileged containers
kubectl get pods -n permit-platform -o jsonpath='{range .items[*]}{.metadata.name}{": "}{.spec.containers[*].securityContext.privileged}{"\n"}{end}'
# Audit logs from OpenSearch
kubectl port-forward -n permit-platform svc/opensearch 9200:9200 &
curl "http://localhost:9200/audit_logs/_search?q=*&size=100"
Check a multi-node cluster
Nodes and cluster events
# View cluster status
kubectl cluster-info
kubectl get nodes -o wide
# Check node resources and conditions
kubectl describe nodes
# View cluster events
kubectl get events --all-namespaces --sort-by='.lastTimestamp'
# Check cluster health
kubectl get --raw='/readyz?verbose'
Ingress and service connectivity
# Check ingress controller status
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
# View load balancer configuration
kubectl get ingress -n permit-platform -o yaml
# Test service connectivity through the backend service DNS name (prints: true)
kubectl exec -n permit-platform deployment/permit-backend-v2 -- \
python3 -c "import urllib.request; print(urllib.request.urlopen('http://permit-backend-v2.permit-platform.svc.cluster.local:8000/v2/healthy').read().decode())"
Diagnose problems from the command line
System diagnostics
These commands list every resource in the namespace, show resource usage, and test connections from the backend to PostgreSQL and Redis. For fixes to specific errors, see on-premises troubleshooting.
# Comprehensive system check
kubectl get all -n permit-platform
kubectl top nodes
kubectl top pods -n permit-platform
# Network connectivity test
kubectl exec -n permit-platform deployment/permit-backend-v2 -- python3 -c "import socket; socket.create_connection(('postgres', 5432), 3)" || echo "Database connection failed"
kubectl exec -n permit-platform deployment/permit-backend-v2 -- python3 -c "import socket; socket.create_connection(('redis', 6379), 3)" || echo "Redis connection failed"
# Storage health check
kubectl get pv,pvc -n permit-platform
kubectl describe pvc -n permit-platform
On a healthy platform, neither connectivity command prints a failure message, and every persistent volume claim shows the phase Bound. A claim stuck in Pending means the cluster has no default storage class or no volume that satisfies the claim, which kubectl describe pvc reports in its events.
Collect a support bundle
Attach a support bundle when you contact Permit support. The bundle contains cluster state, events, and logs. Review the logs before you send them, because application logs can contain user identifiers.
Cluster summary
Write the cluster, pod, event, service, and storage state to one file:
{
echo "=== CLUSTER INFO ==="
kubectl cluster-info
echo "=== PERMIT PLATFORM PODS ==="
kubectl get pods -n permit-platform -o wide
echo "=== RECENT EVENTS ==="
kubectl get events -n permit-platform --sort-by='.lastTimestamp' | tail -20
echo "=== SERVICES ==="
kubectl get svc,ingress -n permit-platform
echo "=== STORAGE ==="
kubectl get pv,pvc -n permit-platform
} > permit-support-bundle.txt
Service logs
Save the logs of all pods except PostgreSQL, and the logs of the backend and Keycloak separately:
# Collect all pod logs
kubectl logs -n permit-platform --all-containers=true --selector=app!=postgres --prefix --tail=-1 > all-logs.txt
# Collect specific service logs
kubectl logs -n permit-platform deployment/permit-backend-v2 > backend-logs.txt
kubectl logs -n permit-platform deployment/keycloak > auth-logs.txt
Archive the bundle
Collect system information and resource usage, then pack every .txt file in the current directory into one archive:
# Collect all pod logs for support
kubectl logs -n permit-platform --all-containers=true --selector=app!=postgres --prefix --tail=-1 > permit-platform-logs.txt
# Collect system information
kubectl get pods,svc,ingress,pv,pvc -n permit-platform -o wide > system-info.txt
kubectl get events -n permit-platform --sort-by='.lastTimestamp' > events.txt
# Add resource usage information
kubectl top pods -n permit-platform > resource-usage.txt
kubectl top nodes > node-usage.txt
# Include all files in support bundle
tar -czf permit-platform-support-$(date +%Y%m%d-%H%M%S).tar.gz \
*.txt
The bundle is ready when permit-platform-support-<timestamp>.tar.gz is in the current directory. Send the newest archive.
Plan maintenance windows
Stop and start services for planned maintenance
While the deployments have zero replicas, users can't sign in to the Permit frontend and the Permit API doesn't respond.
# Scale down all services for maintenance
kubectl scale deployment --replicas=0 -n permit-platform --all
# Verify all pods are down
kubectl get pods -n permit-platform
# After maintenance, restore the replica counts from values.yaml (use the flags you installed with)
./scripts/install-permit-platform.sh --gke --skip-images
# Verify all pods are back
kubectl get pods -n permit-platform
To start every service with the replica counts from values.yaml, run the installer again instead of scaling each deployment by hand.
Emergency procedures
The emergency stop keeps the PostgreSQL and Redis deployments running and scales the other deployments to zero.
# Emergency stop all platform services
kubectl scale deployment --replicas=0 -n permit-platform --selector=app!=postgres,app!=redis
# Emergency restart all services
kubectl rollout restart deployment -n permit-platform
# Safe mode - restart only essential services
kubectl scale deployment permit-backend-v2 -n permit-platform --replicas=1
kubectl scale deployment permit-frontend -n permit-platform --replicas=1
Uninstall Permit Platform
Deleting the namespace and the persistent volumes permanently deletes the Permit database, Keycloak users, and audit logs. Create backups first if you might need the data.
Remove everything
Uninstall the three Helm releases, delete the namespace, and delete the persistent volumes that belonged to the namespace. Run kubectl get pv | grep permit-platform first and check the list before you delete the volumes.
# Remove all 3 Helm releases (the platform uses 3 separate charts)
helm uninstall permit-platform -n permit-platform 2>/dev/null || true # Permit application services
helm uninstall migrations -n permit-platform 2>/dev/null || true # Database schema
helm uninstall third-party-services -n permit-platform 2>/dev/null || true # PostgreSQL, Redis, OpenSearch, etc.
# Delete namespace (removes all resources)
kubectl delete namespace permit-platform
# Clean up persistent volumes (careful!)
kubectl get pv | grep permit-platform
kubectl delete pv $(kubectl get pv -o jsonpath='{.items[?(@.spec.claimRef.namespace=="permit-platform")].metadata.name}')
Uninstallation is complete when helm list -n permit-platform returns no releases and kubectl get namespace permit-platform returns NotFound.
Remove only the Permit services
Uninstall the permit-platform release to remove the Permit application services. The third-party-services release, including the databases and their data, stays in place.
# Remove only platform services (keep data)
helm uninstall permit-platform -n permit-platform
# Remove specific deployments
kubectl delete deployment permit-backend-v2 -n permit-platform
kubectl delete deployment permit-frontend -n permit-platform
Get help
- Email support@permit.io with your support bundle, the installer package file name, and your Kubernetes distribution.
- Ask the community in the Permit Slack community.