> For the complete documentation index, see [llms.txt](https://docs.certinext.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.certinext.io/documentation/deployment-guide-for-on-prem/kubernetes-deployment-guide.md).

# Kubernetes Deployment Guide

## **CERTInext OnPremise v2.8 - Kubernetes Deployment Guide**

**Product:** CERTInext Certificate Lifecycle Management\
**Version:** 2.8 (OnPremise)\
**Deployment:** Kubernetes (kubeadm + containerd)\
**Date:** February 2026

***

### **Table of Contents**

* Introduction
* Architecture Overview
* Prerequisites
* Database Setup
* Property Files
* Docker Images
* Kubernetes Secrets
* Application Deployment
* Post-Deployment Configuration
* Verification & Health Checks
* Troubleshooting
* Appendices

***

### **1. Introduction**

This document describes how to deploy CERTInext OnPremise v2.8 on a Kubernetes cluster using pre-built Docker images. It covers infrastructure prerequisites, database setup, application configuration, deployment procedures, and post-deployment validation.

***

### **2. Architecture Overview**

CERTInext consists of four microservices with distinct roles and database requirements:

| Service                     | Image                     | Role                                        | Database             |
| --------------------------- | ------------------------- | ------------------------------------------- | -------------------- |
| **CERTInext Backend API**   | certinextbackendapiv2.8   | Core business logic, certificate operations | certinext            |
| **CERTInext**               | certinextv2.8             | Main portal - UI, OAuth2 login              | certinext\_discovery |
| **CERTInext Backoffice**    | certinextbackofficev2.8   | Admin panel for internal management         | certinext            |
| **CERTInext Discovery API** | certinextdiscoveryapiv2.8 | Certificate discovery, bot management       | certinext\_discovery |

#### **Deployment Order**

The CERTInext Backend API must be deployed and healthy before other services:

1. **CERTInext Backend API (first)** - other services depend on it
2. **CERTInext (second)** - calls Backend API during startup
3. **Backoffice and Discovery API (third)** - can be deployed in parallel

***

### **3. Prerequisites**

#### **3.1 Kubernetes Cluster**

* Kubernetes cluster installed using kubeadm
* containerd configured as the container runtime
* Control plane and worker nodes joined and in Ready state
* CNI plugin installed (Calico recommended)

**Verify cluster readiness:**

```bash
kubectl get nodes -o wide
kubectl get pods -A
```

#### **3.2 MetalLB Load Balancer**

On-premise clusters need MetalLB to provide load balancing capability.

* Layer2 mode with dedicated IP address pool
* Assigns external IPs to LoadBalancer type services

**Verify MetalLB:**

```bash
kubectl -n metallb-system get pods
kubectl get svc -A | grep LoadBalancer
```

#### **3.3 NGINX Ingress Controller**

* NGINX Ingress Controller deployed and exposed via MetalLB
* Provides host-based routing, TLS termination, centralized traffic management

**Verify Ingress Controller:**

```bash
kubectl -n ingress-nginx get pods
kubectl -n ingress-nginx get svc
```

#### **3.4 DNS Entries**

Each CERTInext service requires a DNS record pointing to the Ingress Controller external IP.

| Service                 | Example Hostname                |
| ----------------------- | ------------------------------- |
| CERTInext Backend API   | api.certinext.example.com       |
| CERTInext               | certinext.example.com           |
| CERTInext Backoffice    | bo.certinext.example.com        |
| CERTInext Discovery API | discovery.certinext.example.com |

Replace `example.com` with your organization's domain.

#### **3.5 TLS Certificates**

* Wildcard certificate (\*.certinext.example.com) or per-service certificates
* Certificate and private key files available on Kubernetes nodes

#### **3.6 External MySQL 8.0**

* MySQL 8.0 server accessible from all worker nodes
* Character set: utf8mb4
* Collation: utf8mb4\_0900\_ai\_ci
* ONLY\_FULL\_GROUP\_BY mode disabled

***

### **4. Database Setup (External MySQL)**

#### **4.1 Create MySQL User**

```sql
CREATE USER 'certinext_app'@'%' IDENTIFIED BY '<STRONG_PASSWORD>';
```

Replace `<STRONG_PASSWORD>` with a secure password.

#### **4.2 Create Databases**

```sql
CREATE DATABASE IF NOT EXISTS `certinext`
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;

CREATE DATABASE IF NOT EXISTS `certinext_discovery`
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
```

#### **4.3 Grant Permissions**

```sql
GRANT ALL PRIVILEGES ON `certinext`.* TO 'certinext_app'@'%';
GRANT ALL PRIVILEGES ON `certinext_discovery`.* TO 'certinext_app'@'%';
FLUSH PRIVILEGES;
```

#### **4.4 Execute SQL Scripts**

Three SQL scripts must be executed in strict order:

| Order | Script                                             | Database             | Purpose                            |
| ----- | -------------------------------------------------- | -------------------- | ---------------------------------- |
| 1     | 01\_CERTInext\_Database\_Setup.sql                 | certinext            | Creates tables and seed data       |
| 2     | 02\_CERTInextDiscovery\_Database\_Setup.sql        | certinext\_discovery | Creates discovery database         |
| 3     | 03\_CERTInext\_Post\_Deployment\_Configuration.sql | both                 | Environment-specific configuration |

**Execute in order:**

```bash
mysql -h <MYSQL_HOST> -u certinext_app -p < "01_CERTInext_Database_Setup.sql"
mysql -h <MYSQL_HOST> -u certinext_app -p < "02_CERTInextDiscovery_Database_Setup.sql"
mysql -h <MYSQL_HOST> -u certinext_app -p < "03_CERTInext_Post_Deployment_Configuration.sql"
```

#### **4.5 Disable ONLY\_FULL\_GROUP\_BY**

CERTInext requires ONLY\_FULL\_GROUP\_BY to be disabled. Add to MySQL configuration:

```ini
[mysqld]
sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"
```

Then restart MySQL or apply dynamically:

```sql
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
```

***

### **5. Prepare Property Files**

Each service requires a property file with database connection details and configuration.

#### **5.1 CERTInext Backend API Configuration**

```properties
MYSQL_DB_USERNAME=<ENCRYPTED_USERNAME>
MYSQL_DB_PASSWORD=<ENCRYPTED_PASSWORD>
MYSQL_DB_HOST=<MYSQL_HOST>
MYSQL_DB_PORT=3306
MYSQL_DB_NAME=certinext
LOGFOLDER=/data/certinext-backend-api/Logs/
FILE_DIRECTORY=/data/certinext-backend-api/Temp/
ONPREM=1
```

#### **5.2 CERTInext - certHub.properties**

```properties
WRAPPER_API_URL=http://certinext-backend-api/
WRAPPER_API_APPCODE=emSign@123
WRAPPER_API_AUTHKEY=emSign@123
MYSQL_DB_USERNAME=<ENCRYPTED_USERNAME>
MYSQL_DB_PASSWORD=<ENCRYPTED_PASSWORD>
MYSQL_DB_HOST=<MYSQL_HOST>
MYSQL_DB_PORT=3306
MYSQL_DB_NAME=certinext_discovery
FILE_DIRECTORY=/data/certinext-hub/Temp/
LOGFOLDER=/data/certinext-hub/Logs/
ONPREM=1
```

#### **5.3 CERTInext Backoffice - DB.properties**

```properties
MYSQL_DB_USERNAME=<ENCRYPTED_USERNAME>
MYSQL_DB_PASSWORD=<ENCRYPTED_PASSWORD>
MYSQL_DB_HOST=<MYSQL_HOST>
MYSQL_DB_PORT=3306
MYSQL_DB_NAME=certinext
LOGFOLDER=/data/certinext-backoffice/Logs/
FILE_DIRECTORY=/data/certinext-backoffice/Temp/
ONPREM=1
```

#### **5.4 CERTInext Discovery API - DB.properties**

```properties
MYSQL_DB_USERNAME=<ENCRYPTED_USERNAME>
MYSQL_DB_PASSWORD=<ENCRYPTED_PASSWORD>
MYSQL_DB_HOST=<MYSQL_HOST>
MYSQL_DB_PORT=3306
MYSQL_DB_NAME=certinext_discovery
WRAPPER_API_URL=http://certinext-backend-api/
WRAPPER_API_APPCODE=emSign@123
WRAPPER_API_AUTHKEY=emSign@123
FILE_DIRECTORY=/data/certinext-discovery-api/Temp/
LOGFOLDER=/data/certinext-discovery-api/Logs/
ONPREM=1
```

#### **Key Configuration Notes**

* **ONPREM=1** must be set on all four services
* **Database credentials must be encrypted** using Base64 wrapping
* **File directories must point to container-internal writable paths**
* **Service URLs use internal Kubernetes DNS names**

***

### **6. Import Docker Images**

Docker images must be imported into containerd on every worker node. These are not pulled from a registry.

#### **6.1 Copy Image Files to Worker Nodes**

```bash
scp DockerImages/*.tar <user>@<worker-node>:/tmp/certinext-images/
```

#### **6.2 Import Images on Each Worker Node**

```bash
ctr -n k8s.io images import /tmp/certinext-images/certinextbackendapiv2.8.tar
ctr -n k8s.io images import /tmp/certinext-images/certinextv2.8.tar
ctr -n k8s.io images import /tmp/certinext-images/certinextbackofficev2.8.tar
ctr -n k8s.io images import /tmp/certinext-images/certinextdiscoveryapiv2.8.tar
```

#### **6.3 Verify Imported Images**

```bash
ctr -n k8s.io images ls | grep certinext
```

***

### **7. Namespace Strategy**

#### **Option A - Single Shared Namespace (Recommended)**

A single certinext namespace is recommended for on-premise deployments. It simplifies service communication and secret management.

```bash
kubectl create namespace certinext
```

#### **Option B - Separate Namespaces Per Service**

For stricter isolation, create separate namespaces. Service URLs require fully qualified names:

```bash
kubectl create namespace certinext-backend-api
kubectl create namespace certinext-hub
kubectl create namespace certinext-backoffice
kubectl create namespace certinext-discovery-api
```

***

### **8. Create Kubernetes Secrets**

#### **8.1 TLS Certificate Secret**

```bash
kubectl -n certinext create secret tls certinext-tls \
  --cert=/path/to/certificate.crt \
  --key=/path/to/private.key
```

#### **8.2 Database Property Secrets**

Create a secret for each service from its property file:

```bash
kubectl -n certinext create secret generic certinext-backend-api-db \
  --from-file=db.properties=/path/to/db.properties

kubectl -n certinext create secret generic certinext-hub-db \
  --from-file=certHub.properties=/path/to/certHub.properties

kubectl -n certinext create secret generic certinext-backoffice-db \
  --from-file=DB.properties=/path/to/backoffice-DB.properties

kubectl -n certinext create secret generic certinext-discovery-api-db \
  --from-file=DB.properties=/path/to/discoveryapi-DB.properties
```

***

### **9. Deploy Applications**

YAML manifests are in `Deployment/yaml/`. Each contains a Deployment, Service, and Ingress.

#### **Deployment Order**

* Backend API must be healthy before other services
* CERTInext depends on Backend API
* Backoffice and Discovery API can deploy in parallel

#### **Step 1: Deploy Backend API**

```bash
kubectl apply -f Deployment/yaml/certinext-backend-api.yaml
kubectl -n certinext rollout status deploy/certinext-backend-api
```

#### **Step 2: Deploy CERTInext**

```bash
kubectl apply -f Deployment/yaml/certinext-hub.yaml
```

#### **Step 3: Deploy Backoffice and Discovery API**

```bash
kubectl apply -f Deployment/yaml/certinext-backoffice.yaml
kubectl apply -f Deployment/yaml/certinext-discovery-api.yaml
```

***

### **10. Post-Deployment Configuration**

#### **10.1 Update Database Settings**

```sql
USE certinext;
UPDATE mas_hub_wrapper_creds SET apiBaseURL = 'https://certinext.example.com' WHERE ID = 1;
```

***

### **11. Verification & Health Checks**

#### **11.1 Check Pod Status**

```bash
kubectl -n certinext get pods -o wide
```

All pods should show Running with 1/1 Ready.

#### **11.2 Review Application Logs**

```bash
kubectl -n certinext logs deploy/certinext-backend-api --tail=200
```

Look for successful database connections and Spring Boot startup messages.

#### **11.3 HTTP Health Checks**

```bash
curl -k https://api.certinext.example.com/
curl -k https://certinext.example.com/
curl -k https://bo.certinext.example.com/
curl -k https://discovery.certinext.example.com/
```

***

### **12. Troubleshooting**

#### **Pod in CrashLoopBackOff**

**Symptoms:** Pod continuously restarts.

**Resolution:**

* Check pod logs for error messages
* Verify property file secret is mounted correctly
* Verify database is reachable from pod network

#### **Backend API Not Reachable**

**Symptoms:** Connection errors to WRAPPER\_API\_URL.

**Resolution:**

* Verify Backend API pod is Running
* Test DNS from within cluster
* Verify WRAPPER\_API\_URL in config files

#### **Database Connection Failures**

**Symptoms:** Connection link failures or access denied errors.

**Resolution:**

* Verify MySQL accessibility from worker nodes
* Verify secret contents and encryption
* Check MySQL user grants

#### **Image Pull Errors**

**Symptoms:** Pod stuck in ErrImagePull.

**Resolution:**

* Verify images imported on scheduled worker node
* Confirm imagePullPolicy is IfNotPresent
* Import images on all worker nodes

***

### **Appendix A: YAML Manifest Summary**

| YAML File                    | Resources                      | Service Port | Ingress Host                    |
| ---------------------------- | ------------------------------ | ------------ | ------------------------------- |
| certinext-backend-api.yaml   | Deployment + Service + Ingress | 80 → 8080    | api.certinext.example.com       |
| certinext-hub.yaml           | Deployment + Service + Ingress | 80 → 8080    | certinext.example.com           |
| certinext-backoffice.yaml    | Deployment + Service + Ingress | 80 → 8080    | bo.certinext.example.com        |
| certinext-discovery-api.yaml | Deployment + Service + Ingress | 80 → 8080    | discovery.certinext.example.com |

#### **Common Deployment Patterns**

* Init container creates log and temp directories
* imagePullPolicy set to IfNotPresent for offline environments
* Readiness probe: HTTP GET / with 30s initial delay
* Liveness probe: HTTP GET / with 60s initial delay
* Volumes: Secrets for config, hostPath for logs and temp
* Ingress: NGINX with TLS termination enabled

#### **Quick Reference Checklist**

* Verify Kubernetes cluster meets all prerequisites
* Set up external MySQL database
* Prepare and encrypt property files
* Import Docker images on all worker nodes
* Create Kubernetes namespace and secrets
* Deploy services in correct order
* Run post-deployment configuration
* Execute health checks and verification

***

**Document Version:** 2.8.1\
**Last Updated:** February 2026
