PVPipe Biometric Authentication - Production Deployment Guide
Overview
This guide provides comprehensive instructions for deploying the PVPipe Biometric Authentication service in production environments, including high availability, security hardening, and monitoring setup.
Prerequisites
Infrastructure Requirements
Minimum Production Requirements
- Kubernetes: v1.24+ or Docker Swarm
- PostgreSQL: v15+ with streaming replication
- Redis: v7+ with clustering
- Load Balancer: NGINX, HAProxy, or cloud provider
- Certificate Management: Let's Encrypt or enterprise CA
Recommended Hardware Specifications
| Component | Minimum | Recommended | High Load |
|---|---|---|---|
| CPU | 2 cores | 4 cores | 8+ cores |
| Memory | 4 GB | 8 GB | 16+ GB |
| Storage | 50 GB SSD | 100 GB SSD | 500+ GB SSD |
| Network | 1 Gbps | 10 Gbps | 10+ Gbps |
Software Dependencies
# Container Runtime
docker >= 20.10.0
containerd >= 1.6.0
# Orchestration (choose one)
kubernetes >= 1.24.0
docker-compose >= 2.0.0
# Database
postgresql >= 15.0
redis >= 7.0
# Monitoring (optional but recommended)
prometheus >= 2.40.0
grafana >= 9.0.0Production Architecture
High Availability Setup
┌─────────────────┐
│ Load Balancer │
│ (HAProxy) │
└─────────────────┘
│
┌─────────────┼─────────────┐
│ │ │
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ ms-auth │ │ ms-auth │ │ ms-auth │
│ Instance 1 │ │ Instance 2 │ │ Instance 3 │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└─────────────┼─────────────┘
│
┌─────────────┼─────────────┐
│ │ │
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ PostgreSQL │ │ Redis │ │ Firebase │
│ Primary │ │ Cluster │ │ FCM │
│ │ │ │ │ (External) │
│ ┌──────────┐ │ │ ┌──────────┐ │ │ │
│ │ Replica │ │ │ │ Replica │ │ │ │
│ └──────────┘ │ │ └──────────┘ │ │ │
└──────────────┘ └──────────────┘ └──────────────┘Kubernetes Production Deployment
1. Namespace Setup
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: pvpipe-auth
labels:
name: pvpipe-auth
environment: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: pvpipe-auth-quota
namespace: pvpipe-auth
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
persistentvolumeclaims: "10"2. Secrets Management
# secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: ms-auth-secrets
namespace: pvpipe-auth
type: Opaque
data:
# Generate with: echo -n "your-secret" | base64
DATABASE_URL: cG9zdGdyZXM6Ly91c2VyOnBhc3N3b3JkQGRiLWhvc3Q6NTQzMi9wdnBpcGU=
JWT_SECRET: eW91ci1zdXBlci1zZWN1cmUtand0LXNlY3JldC1rZXktaGVyZQ==
ENCRYPTION_KEY: eW91ci0zMi1ieXRlLWVuY3J5cHRpb24ta2V5LWhlcmU=
SMTP_USERNAME: c210cC11c2VybmFtZQ==
SMTP_PASSWORD: c210cC1wYXNzd29yZA==
---
apiVersion: v1
kind: Secret
metadata:
name: firebase-service-account
namespace: pvpipe-auth
type: Opaque
data:
firebase-service-account.json: |
ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAgInByb2plY3RfaWQiOiAieW91ci1wcm9qZWN0LWlkIiwKICAicHJpdmF0ZV9rZXlfaWQiOiAia2V5LWlkIiwKICAicHJpdmF0ZV9rZXkiOiAiLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tXG4uLi5cbi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS1cbiIsCiAgImNsaWVudF9lbWFpbCI6ICJmaXJlYmFzZS1hZG1pbnNkay14eXpAeW91ci1wcm9qZWN0LmlhbS5nc2VydmljZWFjY291bnQuY29tIiwKICAiY2xpZW50X2lkIjogIjEyMzQ1Njc4OSIsCiAgImF1dGhfdXJpIjogImh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9vL29hdXRoMi9hdXRoIiwKICAidG9rZW5fdXJpIjogImh0dHBzOi8vb2F1dGgyLmdvb2dsZWFwaXMuY29tL3Rva2VuIgp93. ConfigMap
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ms-auth-config
namespace: pvpipe-auth
data:
# Server Configuration
PORT: "8080"
NODE_ENV: "production"
LOG_LEVEL: "info"
# Database Configuration
DATABASE_MAX_CONNECTIONS: "50"
DATABASE_IDLE_TIMEOUT: "300"
# Redis Configuration
REDIS_HOST: "redis-service"
REDIS_PORT: "6379"
REDIS_PREFIX: "ms-auth:"
# SMTP Configuration
SMTP_HOST: "smtp.gmail.com"
SMTP_PORT: "587"
SMTP_FROM: "noreply@pvpipe.com"
SMTP_TLS: "true"
# Firebase Configuration
FCM_ENABLED: "true"
FCM_PROJECT_ID: "pvpipe-production"
FCM_CREDENTIALS_FILE: "/etc/secrets/firebase-service-account.json"4. Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ms-auth
namespace: pvpipe-auth
labels:
app: ms-auth
version: v1.0.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: ms-auth
template:
metadata:
labels:
app: ms-auth
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: ms-auth-service-account
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: ms-auth
image: pvpipe/ms-auth:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
protocol: TCP
envFrom:
- configMapRef:
name: ms-auth-config
- secretRef:
name: ms-auth-secrets
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
volumeMounts:
- name: firebase-credentials
mountPath: /etc/secrets
readOnly: true
- name: tmp
mountPath: /tmp
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumes:
- name: firebase-credentials
secret:
secretName: firebase-service-account
defaultMode: 0400
- name: tmp
emptyDir: {}
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ms-auth
topologyKey: kubernetes.io/hostname5. Service and Ingress
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: ms-auth-service
namespace: pvpipe-auth
labels:
app: ms-auth
spec:
type: ClusterIP
selector:
app: ms-auth
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ms-auth-ingress
namespace: pvpipe-auth
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- auth.pvpipe.com
secretName: ms-auth-tls
rules:
- host: auth.pvpipe.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ms-auth-service
port:
number: 806. RBAC Configuration
# rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: ms-auth-service-account
namespace: pvpipe-auth
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: ms-auth-role
namespace: pvpipe-auth
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ms-auth-role-binding
namespace: pvpipe-auth
subjects:
- kind: ServiceAccount
name: ms-auth-service-account
namespace: pvpipe-auth
roleRef:
kind: Role
name: ms-auth-role
apiGroup: rbac.authorization.k8s.io7. Network Policies
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ms-auth-network-policy
namespace: pvpipe-auth
spec:
podSelector:
matchLabels:
app: ms-auth
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 8080
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
name: database
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: redis
ports:
- protocol: TCP
port: 6379
- to: []
ports:
- protocol: TCP
port: 443 # HTTPS outbound (Firebase, SMTP)
- protocol: TCP
port: 587 # SMTP
- to: []
ports:
- protocol: TCP
port: 53 # DNS
- protocol: UDP
port: 53 # DNSDatabase Setup
PostgreSQL High Availability
1. Primary Database Configuration
# postgresql-primary.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgresql-primary
namespace: database
spec:
serviceName: postgresql-primary-service
replicas: 1
selector:
matchLabels:
app: postgresql-primary
template:
metadata:
labels:
app: postgresql-primary
spec:
containers:
- name: postgresql
image: postgres:15-alpine
env:
- name: POSTGRES_DB
value: pvpipe
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgresql-secret
key: username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-secret
key: password
- name: POSTGRES_REPLICATION_USER
value: replicator
- name: POSTGRES_REPLICATION_PASSWORD
valueFrom:
secretKeyRef:
name: postgresql-secret
key: replication-password
ports:
- containerPort: 5432
volumeMounts:
- name: postgresql-data
mountPath: /var/lib/postgresql/data
- name: postgresql-config
mountPath: /etc/postgresql/postgresql.conf
subPath: postgresql.conf
resources:
requests:
memory: "2Gi"
cpu: "500m"
limits:
memory: "4Gi"
cpu: "1000m"
volumes:
- name: postgresql-config
configMap:
name: postgresql-config
volumeClaimTemplates:
- metadata:
name: postgresql-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: fast-ssd
resources:
requests:
storage: 100Gi2. Database Migration Job
# migration-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: ms-auth-migration
namespace: pvpipe-auth
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: migration
image: pvpipe/ms-auth:1.0.0
command: ["/app/migrate"]
envFrom:
- secretRef:
name: ms-auth-secrets
env:
- name: MIGRATION_PATH
value: "/app/migrations"
backoffLimit: 3Database Backup Strategy
# backup-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: postgresql-backup
namespace: database
spec:
schedule: "0 2 * * *" # Daily at 2 AM
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: postgres:15-alpine
command:
- /bin/bash
- -c
- |
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
pg_dump $DATABASE_URL | gzip > /backup/pvpipe_backup_$TIMESTAMP.sql.gz
# Keep only last 30 backups
ls -t /backup/pvpipe_backup_*.sql.gz | tail -n +31 | xargs -r rm
envFrom:
- secretRef:
name: ms-auth-secrets
volumeMounts:
- name: backup-storage
mountPath: /backup
volumes:
- name: backup-storage
persistentVolumeClaim:
claimName: backup-pvc
restartPolicy: OnFailureRedis Cluster Setup
Redis Sentinel Configuration
# redis-sentinel.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis-sentinel
namespace: redis
spec:
serviceName: redis-sentinel-service
replicas: 3
selector:
matchLabels:
app: redis-sentinel
template:
metadata:
labels:
app: redis-sentinel
spec:
containers:
- name: redis-sentinel
image: redis:7-alpine
command:
- redis-sentinel
args:
- /etc/redis/sentinel.conf
ports:
- containerPort: 26379
volumeMounts:
- name: redis-sentinel-config
mountPath: /etc/redis/
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "200m"
volumes:
- name: redis-sentinel-config
configMap:
name: redis-sentinel-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-sentinel-config
namespace: redis
data:
sentinel.conf: |
port 26379
sentinel monitor mymaster redis-master-service 6379 2
sentinel auth-pass mymaster your-redis-password
sentinel down-after-milliseconds mymaster 5000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 10000Security Hardening
1. Pod Security Standards
# pod-security-policy.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: ms-auth-psp
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'persistentVolumeClaim'
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'2. Container Image Security
# Dockerfile.production
FROM golang:1.21-alpine AS builder
# Security: Create non-root user
RUN adduser -D -g '' appuser
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \
-ldflags='-w -s -extldflags "-static"' \
-a -installsuffix cgo \
-o auth-service cmd/server/main.go
# Production stage
FROM scratch
# Security: Copy CA certificates for HTTPS
COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
# Security: Copy non-root user
COPY /etc/passwd /etc/passwd
# Copy binary
COPY /app/auth-service /app/auth-service
# Security: Use non-root user
USER appuser
EXPOSE 8080
ENTRYPOINT ["/app/auth-service"]3. Secrets Encryption at Rest
# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfig
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {}Monitoring and Observability
1. Prometheus Configuration
# prometheus-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
namespace: monitoring
data:
prometheus.yml: |
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'ms-auth'
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- pvpipe-auth
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__2. Grafana Dashboard
{
"dashboard": {
"title": "PVPipe Authentication Service",
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_requests_total{job=\"ms-auth\"}[5m])",
"legendFormat": "{{method}} {{status_code}}"
}
]
},
{
"title": "Authentication Success Rate",
"type": "stat",
"targets": [
{
"expr": "rate(auth_attempts_total{result=\"success\"}[5m]) / rate(auth_attempts_total[5m]) * 100",
"legendFormat": "Success Rate %"
}
]
},
{
"title": "Response Time",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job=\"ms-auth\"}[5m]))",
"legendFormat": "95th percentile"
}
]
}
]
}
}3. Alerting Rules
# alerting-rules.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: alerting-rules
namespace: monitoring
data:
ms-auth.yml: |
groups:
- name: ms-auth
rules:
- alert: HighErrorRate
expr: rate(http_requests_total{job="ms-auth",status_code=~"5.."}[5m]) > 0.1
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate in ms-auth service"
description: "Error rate is {{ $value }} errors per second"
- alert: HighResponseTime
expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job="ms-auth"}[5m])) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "High response time in ms-auth service"
description: "95th percentile response time is {{ $value }} seconds"
- alert: AuthenticationFailures
expr: rate(auth_attempts_total{result="failure"}[5m]) > 5
for: 2m
labels:
severity: warning
annotations:
summary: "High authentication failure rate"
description: "Authentication failure rate is {{ $value }} failures per second"Performance Optimization
1. Database Performance
-- Production database optimizations
-- postgresql.conf settings
# Connection settings
max_connections = 200
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 16MB
maintenance_work_mem = 256MB
# Write performance
wal_buffers = 16MB
checkpoint_completion_target = 0.9
checkpoint_timeout = 10min
max_wal_size = 2GB
# Query performance
random_page_cost = 1.1 # SSD storage
effective_io_concurrency = 200
# Logging
log_min_duration_statement = 1000 # Log slow queries
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '2. Application Performance Tuning
# deployment-optimized.yaml
spec:
template:
spec:
containers:
- name: ms-auth
env:
# Database connection pool
- name: DATABASE_MAX_CONNECTIONS
value: "50"
- name: DATABASE_IDLE_TIMEOUT
value: "300"
# Redis settings
- name: REDIS_MAX_CONNECTIONS
value: "100"
- name: REDIS_IDLE_TIMEOUT
value: "240"
# Go runtime optimization
- name: GOMAXPROCS
value: "2"
- name: GOGC
value: "100"
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"3. Horizontal Pod Autoscaler
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: ms-auth-hpa
namespace: pvpipe-auth
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: ms-auth
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 25
periodSeconds: 60Deployment Checklist
Pre-Deployment Checklist
Infrastructure Ready
- Kubernetes cluster operational
- Database cluster configured with replication
- Redis cluster operational
- Load balancer configured
- SSL certificates obtained
Secrets Configured
- JWT secret generated (256-bit minimum)
- Database credentials configured
- Redis credentials configured
- SMTP credentials configured
- Firebase service account configured
Database Prepared
- Database created
- Migrations executed
- Indexes created
- Backup strategy implemented
Security Hardened
- Network policies applied
- Pod security policies configured
- RBAC rules implemented
- Container security scanned
Deployment Steps
Deploy Dependencies
kubectl apply -f namespace.yaml kubectl apply -f secrets.yaml kubectl apply -f configmap.yaml kubectl apply -f rbac.yamlDeploy Database
kubectl apply -f postgresql/ kubectl wait --for=condition=ready pod -l app=postgresql-primary --timeout=300sRun Migrations
kubectl apply -f migration-job.yaml kubectl wait --for=condition=complete job/ms-auth-migration --timeout=300sDeploy Application
kubectl apply -f deployment.yaml kubectl apply -f service.yaml kubectl apply -f ingress.yaml kubectl apply -f hpa.yamlDeploy Monitoring
kubectl apply -f monitoring/
Post-Deployment Verification
Service Health
- All pods running and ready
- Health checks passing
- Database connectivity verified
- Redis connectivity verified
API Functionality
- Authentication endpoints working
- Device registration working
- Biometric login working
- Push notifications working
Security Verification
- HTTPS enforced
- Rate limiting active
- Network policies enforced
- Audit logging functional
Monitoring Active
- Metrics being collected
- Alerts configured
- Dashboards accessible
- Log aggregation working
Rollback Procedure
# In case of deployment issues
kubectl rollout undo deployment/ms-auth -n pvpipe-auth
kubectl rollout status deployment/ms-auth -n pvpipe-auth
# Verify rollback success
kubectl get pods -n pvpipe-auth
kubectl logs -l app=ms-auth -n pvpipe-auth --tail=50This comprehensive deployment guide ensures a secure, scalable, and production-ready deployment of the PVPipe Biometric Authentication service.