Deploy Prowler's web application on Kubernetes with this production-ready Helm chart.
Prowler is an Open Cloud Security tool for AWS, Azure, GCP and Kubernetes. It helps with continuous monitoring, security assessments and audits, incident response, compliance, hardening and forensics readiness. Includes CIS, NIST 800, NIST CSF, CISA, FedRAMP, PCI-DSS, GDPR, HIPAA, FFIEC, SOC2, GXP, Well-Architected Security, ENS and more.
This chart deploys the Prowler App (web UI + API), not the Prowler Dashboard.
- 🚀 One-Command Deployment - Get Prowler running in minutes with sensible defaults
- 🔒 Security by Default - Pod Security Standards, non-root containers, auto-generated secrets, pinned images
- 📊 Web UI & REST API - User-friendly interface and programmatic access
- 🔄 Scheduled Scanning - Automatic recurring security scans with Celery
- 📈 Horizontal Autoscaling - Built-in HPA support for API and Workers
- 💾 Flexible Storage - Support for emptyDir, PVC, and cloud provider storage
- 🗄️ Database Options - Built-in PostgreSQL/Valkey or bring your own managed databases
- 🌐 Ingress Ready - Built-in Ingress configuration with TLS support
- 🔐 RBAC & Network Policies - Per-component network policies and fine-grained service accounts
- ☁️ Cloud Native - IAM roles for service accounts (AWS IRSA, Azure Workload Identity, GCP Workload Identity)
- 📦 Production Examples - Ready-to-use configurations for production deployments
- 🔧 Highly Configurable -
extraEnv/extraEnvFromper component, configurable secret names, image digest support
- Features
- Requirements
- Architecture
- Quick Start
- Installation
- Configuration
- Security
- Examples
- Documentation
- Upgrading
- Troubleshooting
- Contributing
- License
| Component | Minimum | Recommended | Notes |
|---|---|---|---|
| Kubernetes Version | 1.21+ | 1.27+ | PodDisruptionBudget requires 1.21+ |
| Helm Version | 3.0+ | 3.12+ | Helm 3.8+ recommended for OCI support |
| CPU | 2 cores | 8+ cores | For development vs production |
| Memory | 4 GB | 16+ GB | For development vs production |
| Nodes | 1 | 3+ | For high availability |
| Storage Class | Any | RWX-capable | ReadWriteMany for shared storage |
| Component | Purpose | Required For |
|---|---|---|
| Ingress Controller | External access | Production deployments |
| Cert-Manager | TLS certificates | HTTPS with Let's Encrypt |
| Metrics Server | Autoscaling | HPA (Horizontal Pod Autoscaler) |
| CNI with Network Policies | Network segmentation | Network Policies feature |
| External Databases | Production reliability | Production deployments |
| Provider | ReadWriteOnce | ReadWriteMany | Notes |
|---|---|---|---|
| AWS | EBS ✅ | EFS ✅ | EFS requires CSI driver |
| Azure | Managed Disks ✅ | Azure Files ✅ | Both Standard and Premium |
| GCP | Persistent Disk ✅ | Filestore ✅ | Filestore for RWX |
| On-premises | Most storage ✅ | NFS, Ceph, GlusterFS ✅ | Depends on setup |
For local development or testing:
- Minikube (2 CPUs, 4 GB RAM minimum)
- kind (Docker Desktop with 4 GB RAM)
- k3s (Lightweight Kubernetes)
- MicroK8s (Ubuntu/Linux)
See FAQ.md for detailed requirements.
The Prowler App consists of three main components:
- Prowler UI: A user-friendly web interface for running Prowler and viewing results, powered by Next.js.
- Prowler API: The backend API that executes Prowler scans and stores the results, built with Django REST Framework.
- Prowler SDK: A Python SDK that integrates with the Prowler CLI for advanced functionality.
The app leverages the following supporting infrastructure:
- PostgreSQL: Used for persistent storage of scan results.
- Celery Workers: Facilitate asynchronous execution of Prowler scans.
- Valkey: An in-memory database serving as a message broker for the Celery workers.
- Neo4j (DozerDB): Graph database for Attack Paths feature (Prowler 5.17+).
Get Prowler running in 2 minutes:
# Install from OCI registry (recommended)
helm install prowler oci://ghcr.io/cytario/prowler \
--version 3.1.2 \
--create-namespace \
--namespace prowler
# Wait for pods to be ready
kubectl wait --for=condition=ready pod -l app.kubernetes.io/instance=prowler -n prowler --timeout=5m
# Create superuser for login
kubectl exec -n prowler -it deployment/prowler-api -- \
python manage.py createsuperuser
# Access UI (port-forward for testing)
kubectl port-forward -n prowler svc/prowler-ui 3000:3000Then open http://localhost:3000 and login with the credentials you just created.
helm repo add prowler-app https://cytario.github.io/prowler-helm-chart
helm repo updateInstall directly from OCI registry (no repo add required):
helm install prowler oci://ghcr.io/cytario/prowler \
--version 3.1.2 \
--create-namespace \
--namespace prowlerFor development/testing with built-in databases:
helm install prowler prowler-app/prowler -n prowler --create-namespaceNote: Built-in databases use emptyDir storage by default (data is lost on pod restart). See Database Configuration for persistence options.
For production with external managed databases:
# 1. Create namespace
kubectl create namespace prowler
# 2. Create database secrets (see examples/values-external-db.yaml)
kubectl create secret generic prowler-postgres-secret -n prowler \
--from-literal=POSTGRES_HOST=your-db-endpoint \
--from-literal=POSTGRES_PORT=5432 \
--from-literal=POSTGRES_ADMIN_USER=prowler_admin \
--from-literal=POSTGRES_ADMIN_PASSWORD=your-password \
--from-literal=POSTGRES_USER=prowler \
--from-literal=POSTGRES_PASSWORD=your-password \
--from-literal=POSTGRES_DB=prowler_db
kubectl create secret generic prowler-valkey-secret -n prowler \
--from-literal=VALKEY_HOST=your-redis-endpoint \
--from-literal=VALKEY_PORT=6379 \
--from-literal=VALKEY_PASSWORD=your-password \
--from-literal=VALKEY_DB=0
# 3. Install with production values
helm install prowler prowler-app/prowler \
-n prowler \
-f examples/values-production.yamlSee examples/ directory for complete production configurations.
Install with custom values file:
# Create your custom values
cat > my-values.yaml <<EOF
api:
replicaCount: 3
resources:
limits:
cpu: 2000m
memory: 2Gi
worker:
replicaCount: 5
autoscaling:
enabled: true
maxReplicas: 20
ui:
ingress:
enabled: true
hosts:
- host: prowler.example.com
EOF
# Install with custom values
helm install prowler prowler-app/prowler \
-n prowler \
-f my-values.yaml# Check pod status
kubectl get pods -n prowler
# Check all resources
kubectl get all -n prowler
# View logs
kubectl logs -n prowler -l app.kubernetes.io/component=api
# Run Helm tests
helm test prowler -n prowlerBy default, this chart deploys PostgreSQL and Valkey using Bitnami's charts.
For Production:
- AWS: RDS for PostgreSQL, ElastiCache for Redis
- Azure: Azure Database for PostgreSQL, Azure Cache for Redis
- GCP: Cloud SQL for PostgreSQL, Memorystore for Redis
See examples/values-external-db.yaml for detailed external database configuration.
This chart implements several security features:
- Auto-generated secrets: Django keys are automatically generated during installation
- Security contexts: All pods run as non-root with dropped capabilities
- Network policies: Optional pod-to-pod communication control
- RBAC: Minimal read-only permissions for Kubernetes scanning
- Pod Security Standards: Compliance with restricted security profile
For detailed security configuration, see SECURITY.md.
The chart is highly configurable through the values.yaml file. All configuration options are documented inline with comments and examples.
api:
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512Mi
worker:
resources:
limits:
cpu: 2000m
memory: 2Gi
requests:
cpu: 500m
memory: 512MiSee values.yaml for recommended values for each component.
api:
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
worker:
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
targetCPUUtilizationPercentage: 70ui:
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: prowler.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: prowler-ui-tls
hosts:
- prowler.example.com
api:
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: prowler-api.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: prowler-api-tls
hosts:
- prowler-api.example.comsharedStorage:
type: persistentVolumeClaim
persistentVolumeClaim:
create: true
storageClassName: "efs-sc" # or your storage class
accessMode: ReadWriteMany
size: 50GiNetwork policies are now configured per component (v2.0.0+):
api:
networkPolicy:
enabled: true
worker:
networkPolicy:
enabled: true
egress: []
ui:
networkPolicy:
enabled: true
ingress: []
egress: []
neo4j:
networkPolicy:
enabled: true
ingress: []Note: Requires CNI plugin with network policy support (Calico, Cilium, etc.). See UPGRADING.md for migration from the previous single-toggle model.
Control the number of concurrent Celery worker processes to prevent OOM kills:
worker:
# Each scan task uses ~1-1.5 GiB. Size memory limits relative to concurrency.
concurrency: 2 # default; set to null to use celery default (cpu_count)
resources:
limits:
memory: 4Gi # concurrency * 2 GiB
requests:
memory: 2GiWhen concurrency is set, the chart bypasses the Prowler entrypoint and invokes Celery directly with --concurrency N. This is necessary because the upstream entrypoint does not support the CELERY_WORKER_CONCURRENCY environment variable.
Inject per-component environment variables without forking the chart:
worker:
extraEnv:
- name: MY_CUSTOM_VAR
value: "my-value"
extraEnvFrom:
- secretRef:
name: my-extra-secretsAll four components (api, worker, worker_beat, ui) support extraEnv and extraEnvFrom.
Use custom secret names for External Secrets Operator, Sealed Secrets, or any external secret management:
externalSecrets:
postgres:
secretName: my-postgres-secret # default: prowler-postgres-secret
valkey:
secretName: my-valkey-secret # default: prowler-valkey-secretPin images by immutable digest for supply-chain security:
api:
image:
digest: "sha256:abc123..." # takes precedence over tag when setAWS (IRSA):
worker:
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/prowler-scannerAzure (Workload Identity):
worker:
serviceAccount:
annotations:
azure.workload.identity/client-id: "your-client-id"
podLabels:
azure.workload.identity/use: "true"GCP (Workload Identity):
worker:
serviceAccount:
annotations:
iam.gke.io/gcp-service-account: prowler@project.iam.gserviceaccount.comFor complete configuration reference, see:
- values.yaml - All available options with inline documentation
- examples/values-production.yaml - Production-ready configuration
- examples/values-external-db.yaml - External database setup
This chart implements security best practices by default:
- ✅ Pod Security Standards - Restricted profile compliance
- ✅ Non-root Containers - All pods run as non-root user (UID 1000)
- ✅ Dropped Capabilities - All Linux capabilities dropped except required ones
- ✅ Read-only Root Filesystem - Where possible, filesystems are read-only
- ✅ Seccomp Profiles - RuntimeDefault seccomp profile applied
- ✅ Auto-generated Secrets - Django keys generated securely on install with pinned image
- ✅ No Hardcoded Secrets - All secrets must be explicitly provided
- ✅ RBAC - Minimal permissions with dedicated service accounts per component (API, Worker, Neo4j, Scan Recovery)
- ✅ Network Policies - Per-component network policies with least-privilege defaults
- ✅ Image Digest Support - Pin images by immutable SHA256 digest
- ✅ Least-Privilege SA Tokens - UI and Beat scheduler do not mount K8s API tokens by default
- Use external managed databases (not built-in)
- Set strong PostgreSQL password
- Enable TLS/SSL for ingress
- Enable Network Policies
- Use external secrets management (e.g., External Secrets Operator)
- Enable audit logging
- Configure resource limits
- Use private container registries (if required)
- Enable Pod Disruption Budgets
- Configure backups for databases
- Review and customize RBAC permissions
- Enable admission controllers (OPA/Gatekeeper)
See SECURITY.md for comprehensive security documentation.
Ready-to-use configuration examples are provided in the examples/ directory:
Complete production-ready configuration with:
- External managed databases
- High availability (3+ replicas)
- Horizontal autoscaling
- Persistent storage
- Ingress with TLS
- Network policies
- Resource limits
- Pod Disruption Budgets
Focused guide for connecting to external databases:
- AWS RDS + ElastiCache configuration
- Azure Database + Cache for Redis setup
- GCP Cloud SQL + Memorystore setup
- Network configuration guidance
- Performance tuning recommendations
- Migration guide from built-in databases
See examples/README.md for usage instructions and more examples.
- FAQ.md - Frequently asked questions (20+ questions)
- UPGRADING.md - Upgrade procedures and version-specific notes
- docs/troubleshooting.md - Common issues and solutions
- SECURITY.md - Security best practices and configuration
- CONTRIBUTING.md - How to contribute to this project
- CHANGELOG.md - Version history and release notes
- values.yaml - Complete configuration options with inline docs
- examples/ - Real-world configuration examples
- Prowler Documentation - Official Prowler documentation
- Prowler GitHub - Prowler source code
- OCI Registry - Helm chart OCI packages
# Update Helm repository
helm repo update
# Check what will change
helm diff upgrade prowler prowler-app/prowler -n prowler
# Backup current configuration
helm get values prowler -n prowler > backup-values.yaml
# Perform upgrade
helm upgrade prowler prowler-app/prowler -n prowler --reuse-values- Always backup your data before upgrading
- Review CHANGELOG.md for breaking changes
- Test upgrades in non-production environment first
- Database migrations run automatically on upgrade
See UPGRADING.md for detailed upgrade procedures, version-specific notes, and rollback instructions.
# Check pod status
kubectl get pods -n prowler
# View recent events
kubectl get events -n prowler --sort-by='.lastTimestamp' | tail -20
# Check logs
kubectl logs -n prowler -l app.kubernetes.io/component=api --tail=50
kubectl logs -n prowler -l app.kubernetes.io/component=worker --tail=50
# Describe problematic pod
kubectl describe pod -n prowler <pod-name>- Check database connection
- Verify secrets are created
- Check resource limits
See docs/troubleshooting.md#pod-startup-problems
- Verify Django keys are generated
- Check API accessibility from UI
- Create superuser if not exists
See docs/troubleshooting.md#authentication-and-login-problems
- Check Valkey connection
- Verify worker pods are running
- Check worker-beat is scheduling
See docs/troubleshooting.md#worker-and-celery-issues
See docs/troubleshooting.md for comprehensive troubleshooting covering:
- Installation issues
- Pod startup problems
- Database connection issues
- Authentication problems
- Worker and Celery issues
- Storage and volume issues
- Networking and Ingress issues
- Performance problems
- Upgrade issues
We welcome contributions! This project follows standard open-source contribution practices.
- 🐛 Report Bugs - Open an issue with details
- 💡 Suggest Features - Share your ideas
- 📝 Improve Documentation - Fix typos, add examples
- 🔧 Submit Pull Requests - Fix bugs or add features
- ⭐ Star the Repository - Show your support
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Test thoroughly (lint, template validation, local deployment)
- Commit using Conventional Commits
- Push to your fork
- Open a Pull Request
See CONTRIBUTING.md for detailed contribution guidelines, development setup, coding standards, and testing procedures.
- 📖 Documentation - Start with FAQ.md and docs/troubleshooting.md
- 🐛 Bug Reports - GitHub Issues
- 💬 Questions - GitHub Discussions
- 📧 Security Issues - See SECURITY.md
- Check FAQ.md for common questions
- Search existing issues
- Review troubleshooting guide
- Collect debug information (logs, pod status, events)
For enterprise support, SLA-backed assistance, or custom development, contact Prowler Cloud.
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
- Prowler - The amazing cloud security tool this chart deploys
- Bitnami Charts - PostgreSQL and Valkey dependencies
- All contributors who have helped improve this project
- Chart Repository: prowler-helm-chart
- Prowler: prowler-cloud/prowler
- Documentation: docs.prowler.com
- OCI Registry: ghcr.io/cytario/prowler
⭐ If you find this chart useful, please consider starring the repository!
