Quick Start Guide
Overview
Section titled “Overview”This guide walks you through installing QHx on a Kubernetes cluster and deploying your first workload with automated workload identity and mTLS communication.
Time to complete: 30 minutes
What you’ll learn:
- Install QHx on Kubernetes
- Deploy a workload with automatic SPIFFE identity
- Verify mTLS communication between workloads
- View workload identity statements
Prerequisites
Section titled “Prerequisites”Before you begin, ensure you have:
-
Kubernetes cluster (1.28 or later)
-
kubectl configured to access your cluster
Terminal window kubectl cluster-info# Should show your cluster endpoint -
Helm 3.x installed
Terminal window helm version# Version should be v3.x.x
Step 1: Install QHx
Section titled “Step 1: Install QHx”Add QHx Helm Repository
Section titled “Add QHx Helm Repository”helm repo add messier42 https://charts.messier42.comhelm repo updateInstall QHx with Default Configuration
Section titled “Install QHx with Default Configuration”helm install qhx messier42/qhx \ --namespace qhx-system \ --create-namespace \ --waitWhat this does:
- Creates
qhx-systemnamespace - Deploys QHx Manager (admission controller)
- Deploys PKI Server (SPIRE server for ML-DSA-65)
- Deploys PKI Agents as DaemonSet (one per node)
- Creates default QHxClusterPolicy
Installation takes: ~2-3 minutes
Verify Installation
Section titled “Verify Installation”Check that all QHx components are running:
kubectl -n qhx-system get podExpected output:
NAME READY STATUS RESTARTS AGEqhx-manager-5d8c7b9f6d-xyz 1/1 Running 0 2mpki-server-0 2/2 Running 0 2mpki-agent-abc123 1/1 Running 0 2mpki-agent-def456 1/1 Running 0 2mAll pods should show Running status with READY matching total containers.
Troubleshooting:
# If pods are not ready, check logskubectl -n qhx-system logs -l app=qhx-managerkubectl -n qhx-system logs pki-server-0 -c pki-server
# Check eventskubectl -n qhx-system get events --sort-by='.lastTimestamp'Step 2: Create Your First Namespace
Section titled “Step 2: Create Your First Namespace”Create a namespace for your application with MLS labels:
kubectl apply -f - <<EOFapiVersion: v1kind: Namespacemetadata: name: demo annotations: mls.qhx.dev/level: "us:s" mls.qhx.dev/compartment: "us:demo"EOFNote: The mls.qhx.dev/* annotations define the Multi-Level Security classification for workloads in this namespace. With default policy, only users with appropriate clearance can deploy to this namespace.
Verify the namespace:
kubectl get namespace demo -o yaml | grep mls.qhx.devStep 3: Deploy an HTTP Server
Section titled “Step 3: Deploy an HTTP Server”Deploy a simple HTTP server that will receive an identity:
kubectl apply -f - <<EOFapiVersion: apps/v1kind: Deploymentmetadata: name: http-server namespace: demospec: replicas: 1 selector: matchLabels: app: http-server template: metadata: labels: app: http-server spec: serviceAccountName: default containers: - name: server image: hashicorp/http-echo:latest args: - "-text=Hello from QHx!" - "-listen=:8080" ports: - containerPort: 8080---apiVersion: v1kind: Servicemetadata: name: http-server namespace: demospec: selector: app: http-server ports: - port: 8080 targetPort: 8080EOFWait for the deployment to be ready:
kubectl -n demo wait --for=condition=available --timeout=60s deployment/http-serverInspect the Workload Identity
Section titled “Inspect the Workload Identity”QHx automatically injects SPIFFE identities into workloads. Let’s examine what was created:
# Get the pod namePOD=$(kubectl -n demo get pod -l app=http-server -o jsonpath='{.items[0].metadata.name}')
# Check for SPIFFE identity fileskubectl -n demo exec $POD -- ls -la /run/secrets/qhx.dev/Expected output:
total 12-rw-r--r-- 1 root root 1234 ... svid.pem # X.509 certificate-rw------- 1 root root 456 ... svid-key.pem # Private key-rw-r--r-- 1 root root 2345 ... bundle.pem # Trust bundleView the SPIFFE ID
Section titled “View the SPIFFE ID”kubectl -n demo exec $POD -- \ cat /run/secrets/qhx.dev/svid.pem | \ openssl x509 -text -noout | grep URIExpected output:
URI:spiffe://qhx.dev/ns/demo/sa/default/pod/http-server-abc123/...This SPIFFE ID uniquely identifies this workload and includes:
- Trust domain:
qhx.dev - Namespace:
demo - Service account:
default - Pod name:
http-server-abc123 - Pod UID: (unique identifier)
Step 4: Deploy an HTTP Client
Section titled “Step 4: Deploy an HTTP Client”Deploy a client workload to test communication:
kubectl apply -f - <<EOFapiVersion: v1kind: Podmetadata: name: http-client namespace: demospec: serviceAccountName: default containers: - name: client image: curlimages/curl:latest command: ["sleep", "3600"]EOFWait for the pod to be ready:
kubectl -n demo wait --for=condition=ready --timeout=60s pod/http-clientStep 5: Test Communication
Section titled “Step 5: Test Communication”Direct Communication (Without mTLS)
Section titled “Direct Communication (Without mTLS)”First, try connecting directly to the HTTP server:
kubectl -n demo exec http-client -- \ curl -s http://http-server:8080Expected output:
Hello from QHx!This works because both workloads are in the same namespace and default Kubernetes networking allows it.
mTLS Communication (With QHx Proxy)
Section titled “mTLS Communication (With QHx Proxy)”For production deployments, you would deploy QHx proxy sidecars to enable automatic mTLS. The proxy sidecars:
- Intercept traffic
- Authenticate using SPIFFE identities
- Establish mTLS connections
- Enforce policy
Note: Proxy deployment is covered in the Proxy Architecture Guide.
Step 6: View Workload Attestation
Section titled “Step 6: View Workload Attestation”QHx PKI Server maintains a registry of all attested workloads. You can query it:
kubectl -n qhx-system exec pki-server-0 -c pki-server -- \ /opt/spire/bin/spire-server entry showSample output:
Entry ID : abc123...SPIFFE ID : spiffe://qhx.dev/ns/demo/sa/defaultParent ID : spiffe://qhx.dev/agent/k8s/node-1Selectors : k8s:ns:demo k8s:sa:defaultTTL : 3600This shows the registration entries that allow workloads in the demo namespace with service account default to receive identities.
Step 7: Verify Node Attestation
Section titled “Step 7: Verify Node Attestation”QHx PKI Agents on each node attest to the PKI Server. Check agent status:
kubectl -n qhx-system exec pki-server-0 -c pki-server -- \ /opt/spire/bin/spire-server agent listSample output:
SPIFFE ID : spiffe://qhx.dev/agent/k8s/node-1Attestation type : k8s_psatExpiration time : 2026-02-03 10:00:00 +0000 UTCSerial number : 123456789This shows the agents that have successfully attested and are authorized to request SVIDs for workloads.
Step 8: Check Metrics (Optional)
Section titled “Step 8: Check Metrics (Optional)”QHx components expose Prometheus metrics. Port-forward to view them:
# PKI Server metricskubectl -n qhx-system port-forward pki-server-0 9090:9090
# In another terminal, query metricscurl http://localhost:9090/metrics | grep spire_server_server_ca_sign_x509_svidSample metrics:
spire_server_server_ca_sign_x509_svid_count{status="OK"} 42spire_server_server_ca_sign_x509_svid_elapsed_time{status="OK"} 0.045This shows successful SVID signing operations and their latency.
Common Issues
Section titled “Common Issues”Pods Stuck in Pending
Section titled “Pods Stuck in Pending”Symptom: QHx pods remain in Pending state
Diagnosis:
kubectl -n qhx-system describe pod <pod-name>Common causes:
- Insufficient cluster resources (CPU/memory)
- Node selector constraints
- PersistentVolumeClaim not bound
Solution:
# Check resource availabilitykubectl top nodes
# Check PVC statuskubectl -n qhx-system get pvcAdmission Controller Denies Deployments
Section titled “Admission Controller Denies Deployments”Symptom: Error: admission webhook "qhx-manager.qhx.dev" denied the request
Common causes:
- MLS labels not set on namespace
- User lacks required Kubernetes groups
- Policy violation (incompatible labels)
Solution:
# Check policykubectl get qhxclusterpolicy qhx-cluster-policy -o yaml
# Verify namespace has MLS labelskubectl get namespace demo -o yaml | grep mls.qhx.devSVID Files Not Present
Section titled “SVID Files Not Present”Symptom: /run/secrets/qhx.dev/ directory empty or missing
Common causes:
- PKI Agent not running on node
- Workload attestation failed
- No registration entry for workload
Diagnosis:
# Check PKI Agent logskubectl -n qhx-system logs -l app=pki-agent --tail=50
# Check for registration entrieskubectl -n qhx-system exec pki-server-0 -c pki-server -- \ /opt/spire/bin/spire-server entry show -parentID spiffe://qhx.dev/agent/k8s/<node-name>Clean Up
Section titled “Clean Up”To remove the demo resources:
# Delete demo namespace (removes all workloads)kubectl delete namespace demo
# Uninstall QHx (if desired)helm uninstall qhx -n qhx-systemkubectl delete namespace qhx-systemNext Steps
Section titled “Next Steps”Now that you have QHx running, explore these topics:
Security
Section titled “Security”- MLS Policy Authoring - Configure classification levels and compartments
- Attestation Strategies - Node and workload attestation options
- Security Hardening - Production security configuration
Features
Section titled “Features”- Proxy Architecture - Enable mTLS and request notarization
- Request Notarization - Sign and verify HTTP requests
- Flowspecs - Define network access policies
Operations
Section titled “Operations”- Federation Setup - Connect multiple clusters
- Compartment Management - Isolate workloads by classification
- Production Deployment (EKS) - Deploy on AWS with Cilium
Monitoring
Section titled “Monitoring”- Telemetry and Monitoring - Prometheus, logs, alerts
Learning Resources
Section titled “Learning Resources”- Example Applications: Check the Examples section for real-world deployments
- Architecture Overview: Understand the system design
- API Reference: Explore the OpenAPI specification
Getting Help
Section titled “Getting Help”- Documentation: https://docs.messier42.com
- Support Email: support@messier42.com
- GitHub Issues: Report bugs or feature requests
- Customer Portal: https://portal.messier42.com (for customers)
Summary
Section titled “Summary”You’ve successfully:
- ✅ Installed QHx on Kubernetes
- ✅ Deployed workloads with automatic SPIFFE identities
- ✅ Verified workload attestation
- ✅ Checked node attestation status
- ✅ Explored metrics and monitoring
QHx is now managing workload identities for your cluster. Workloads automatically receive:
- SPIFFE IDs (X.509-SVIDs)
- Short-lived certificates (1 hour TTL, auto-rotated)
- Trust bundles for verification
- MLS labels for policy enforcement
You’re ready to explore advanced features like mTLS proxies, request notarization, and multi-cluster federation!