Skip to main content

On-Premise Deployment

Deploy Optimal Platform in your own data center or private infrastructure using bare-metal Kubernetes or existing clusters.

Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────┐
│ On-Premise Data Center │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Kubernetes Cluster │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Control Plane (HA) │ │ │
│ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │
│ │ │ │ Master 1 │ │ Master 2 │ │ Master 3 │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────────────────────────────────────────┐ │ │
│ │ │ Worker Nodes │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │ Worker1 │ │ Worker2 │ │ Worker3 │ │ Worker4 │ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ └─────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ PostgreSQL │ │ Redis │ │ Harbor │ │ NFS/Ceph │ │
│ │ Cluster │ │ Cluster │ │ Registry │ │ Storage │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Load Balancer (HAProxy / MetalLB / F5) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘

Prerequisites

Hardware Requirements

ComponentMinimumRecommended (Production)
Control Plane3 nodes, 4 CPU, 8GB RAM3 nodes, 8 CPU, 16GB RAM
Worker Nodes3 nodes, 8 CPU, 32GB RAM6 nodes, 16 CPU, 64GB RAM
Storage500GB SSD2TB NVMe per node
Network1 Gbps10 Gbps

Software Requirements

RequirementVersionNotes
Kubernetes1.28+RKE2, Kubeadm, or OpenShift
Container Runtimecontainerd 1.7+Or CRI-O
CNICalico or CiliumWith network policy support
Storage ClassCSI driverFor persistent volumes
Load BalancerMetalLB or hardware LBFor service type LoadBalancer

Supported Kubernetes Distributions

DistributionSupport LevelNotes
RKE2FullRecommended for STIG compliance
KubeadmFullStandard upstream
OpenShiftFull4.12+ required
RancherFullVia RKE2
TanzuFullTKG 2.0+
K3sDevelopmentNot recommended for production

Step 1: Prepare Kubernetes Cluster

# On first master node
curl -sfL https://get.rke2.io | sh -

# Configure RKE2
cat > /etc/rancher/rke2/config.yaml <<EOF
tls-san:
- optimal-cluster.yourdomain.com
cni: calico
profile: cis-1.23
EOF

# Start RKE2
systemctl enable rke2-server
systemctl start rke2-server

# Get kubeconfig
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config

Option B: Kubeadm

# Initialize control plane
kubeadm init \
--control-plane-endpoint "optimal-cluster.yourdomain.com:6443" \
--upload-certs \
--pod-network-cidr=10.244.0.0/16

# Install CNI
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml

Step 2: Configure Storage

helm repo add longhorn https://charts.longhorn.io
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--create-namespace \
--set defaultSettings.defaultDataPath="/var/lib/longhorn"

Option B: Rook-Ceph

git clone --single-branch --branch v1.12.0 https://github.com/rook/rook.git
cd rook/deploy/examples

kubectl create -f crds.yaml -f common.yaml -f operator.yaml
kubectl create -f cluster.yaml
kubectl create -f filesystem.yaml
kubectl create -f storageclass.yaml

Option C: NFS

helm repo add nfs-subdir-external-provisioner \
https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner

helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=nfs.yourdomain.com \
--set nfs.path=/exports/kubernetes \
--set storageClass.defaultClass=true

Step 3: Configure Load Balancer

Option A: MetalLB

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.10/config/manifests/metallb-native.yaml

# Configure IP pool
cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default
namespace: metallb-system
EOF

Option B: Hardware Load Balancer

Configure your F5, HAProxy, or other load balancer to point to Kubernetes worker nodes on ports:

  • 80 (HTTP)
  • 443 (HTTPS)
  • 6443 (Kubernetes API - for management)

Step 4: Deploy Platform

# Clone repository
git clone https://github.com/optimal-cyber/optimal-platform.git
cd optimal-platform

# Add Helm repositories
make helm-deps

# Create namespace
kubectl create namespace optimal-system

# Deploy with on-premise values
helm upgrade --install optimal-platform k8s/helm-charts/optimal-platform \
--namespace optimal-system \
-f k8s/helm-charts/optimal-platform/values-production.yaml \
--set global.cloud.provider=on-premise \
--set global.storageClass=longhorn \
--set ingress.className=nginx

On-Premise Specific Values

# values-on-premise.yaml
global:
cloud:
provider: on-premise
storageClass: longhorn

# Internal PostgreSQL (or use external)
postgresql:
enabled: true
primary:
persistence:
storageClass: longhorn
size: 100Gi

# Internal Redis
redis:
enabled: true
master:
persistence:
storageClass: longhorn

# Ingress with cert-manager
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
tls:
- secretName: optimal-tls
hosts:
- platform.yourdomain.com

# Harbor registry (internal)
harbor:
enabled: true
persistence:
persistentVolumeClaim:
registry:
storageClass: longhorn

Step 5: Configure TLS Certificates

Option A: Let's Encrypt (if internet accessible)

# Install cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml

# Create ClusterIssuer
cat <<EOF | kubectl apply -f -
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: admin@yourdomain.com
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
EOF

Option B: Internal CA

# Create self-signed CA
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ca.key -out ca.crt \
-subj "/CN=Optimal Platform CA"

# Create TLS secret
kubectl create secret tls optimal-tls \
--cert=platform.crt \
--key=platform.key \
-n optimal-system

Step 6: Configure External Database (Optional)

For production, use an external PostgreSQL cluster:

postgresql:
enabled: false
external:
host: postgresql.yourdomain.com
port: 5432
database: optimal_platform
username: optimal_user
existingSecret: postgresql-credentials
# Create database credentials secret
kubectl create secret generic postgresql-credentials \
--from-literal=password=your-password \
-n optimal-system

Step 7: Verify Deployment

# Check all pods
kubectl get pods -n optimal-system

# Check services
kubectl get svc -n optimal-system

# Check ingress
kubectl get ingress -n optimal-system

# View logs
kubectl logs -n optimal-system -l app=optimal-portal --tail=100

High Availability Configuration

Database HA

postgresql:
architecture: replication
readReplicas:
replicaCount: 2
primary:
persistence:
size: 100Gi

Redis HA

redis:
architecture: replication
replica:
replicaCount: 2

Pod Disruption Budgets

portal:
podDisruptionBudget:
minAvailable: 1

apiGateway:
podDisruptionBudget:
minAvailable: 1

Security Hardening

Network Policies

# Enable strict network policies
kubectl apply -f k8s/network-policies/

Pod Security Standards

# Apply restricted PSS
kubectl label namespace optimal-system \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/warn=restricted

Backup and Recovery

Velero Setup

# Install Velero with MinIO backend
velero install \
--provider aws \
--plugins velero/velero-plugin-for-aws:v1.7.0 \
--bucket optimal-backups \
--secret-file ./credentials-minio \
--backup-location-config region=minio,s3ForcePathStyle=true,s3Url=http://minio.storage.svc:9000

# Schedule daily backups
velero schedule create daily-backup \
--schedule="0 2 * * *" \
--include-namespaces optimal-system

Production Checklist

  • High availability control plane (3+ masters)
  • Distributed storage with replication
  • Network policies enabled
  • Pod security standards enforced
  • TLS certificates configured
  • Backup solution configured
  • Monitoring and alerting set up
  • Log aggregation configured
  • Disaster recovery tested

Troubleshooting

Storage Issues

# Check storage class
kubectl get sc

# Check PVC status
kubectl get pvc -n optimal-system

Network Issues

# Test internal DNS
kubectl run test --rm -it --image=busybox -- nslookup kubernetes

# Check network policies
kubectl get networkpolicies -n optimal-system

Certificate Issues

# Check certificate status
kubectl get certificates -n optimal-system
kubectl describe certificate optimal-tls -n optimal-system

Next Steps