# On Premise

## Overview

This page walks you through the **end-to-end setup and deployment of the DIGIT Complaints Management (CMS / PGR)** on a Rancher-managed Kubernetes cluster using **Helmfile-based deploy-as-code**.

## Pre-requisites

#### 1. Provision a Rancher Cluster

Ensure a Rancher-managed Kubernetes cluster is provisioned and running. This cluster will serve as the infrastructure for deploying DIGIT CMS services

#### 2. Provision a PostgreSQL Server

A PostgreSQL server is required to retain data related to logins and other application-specific information shared across services.

📘 Reference Guide: [Postgres Server Provisioning Guide](https://docs.google.com/document/d/1SvsHkB_dc9F1tLVOLqpf1NonvFE7OQI-x1qCixRhjiU/edit?tab=t.0)

#### 3. Setup PostgreSQL Replication (HA) (For production setup)

For high availability and fault tolerance, configure PostgreSQL replication.

📘 Reference Guide: [PostgreSQL HA Setup Guide](https://core.digit.org/guides/operations-guide/postgresql-ha?q=sops)

#### 4. Provision an NFS Server

An NFS server is required to enable persistent volume support for services that require data persistence.\
\
📘 Reference Guide: [NFS Server Deployment on Rancher](/complaints-management/complaints-resolution-v2.10/deploy/setup/production-setup/setup-infrastructure/on-premise/deploy-network-file-system-nfs-server.md)

#### 5. Export Rancher Cluster’s Kubeconfig

To interact with the cluster, copy and configure the kubeconfig file from the Rancher management cluster. This enables CLI-based access via kubectl.

#### 6. Install Required CLI Tools

Make sure the following command-line tools are installed on your system:

* [kubectl ](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/)— Kubernetes command-line tool for interacting with the cluster.
* Helmfile & Helm
* sops + age (recommended), and&#x20;
* optionally jq/yq

#### 7. Domain and Public IP Setup

1. Ensure the domain is mapped to a public IP.
2. Set up managed TLS certificates for secure communication (recommended for production servers).
3. DNS: CCRS domain → LoadBalancer external IP.
4. Network/Firewall: allow HTTPS to the LoadBalancer IP; allow egress to DB/Kafka/ES/SMTP/SMS/etc.
5. Environment files: env.yaml (non-secrets) and env-secrets.yaml (secrets, preferably encrypted with sops/age).

Once all these prerequisites are satisfied, proceed with the deployment of the CCRS app. If any of the above are missing, fix them before proceeding. Everything below assumes these pieces are ready.

***

## Steps

{% stepper %}
{% step %}

### Clone the CMS repo

```
git clone https://github.com/egovernments/Citizen-Complaint-Resolution-System.git
cd Citizen-Complaint-Resolution-System
# Use the default branch you've been following for CCRS (typically master/main)
```

{% endstep %}

{% step %}

### Prepare Environment Files (Helmfile values)

Create two files under the CMS deploy-as-code charts’ environments folder. Paths below are typical; if your repo layout differs, mirror the structure accordingly.

#### env.yaml (non-secrets)

Create (or copy) devops/deploy-as-code/charts/environments/pgr-sdc-prd.yaml:

```yaml
# devops/deploy-as-code/charts/environments/pgr-sdc-prd.yaml
global:
  domain: pgr.<state>.gov.in                # Your PGR domain (DNS → MetalLB IP)
  setup: fullsetup                          # (if the charts expect this flag)

root-ingress:
  cert-issuer: letsencrypt-prod                # Or your internal issuer

configmaps:
  egov-config:
    data:
      db-host: 10.10.0.25                        # PostgreSQL host/IP (reachable from cluster)
      db-name: pgrprd
      db-url: jdbc:postgresql://10.10.0.25:5432/pgrprd
    state-level-tenant-id: ethiopia                         # e.g., in.stateX or pb

pgr:
  # Helm subchart values for PGR services (examples below)
  enabled: true
  namespace: egov
  replicas: 2
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 1
      memory: 1Gi
```

Adjust Kafka, Elasticsearch or remove them if unused in your deployment.

#### env-secrets.yaml (secrets)

Create devops/deploy-as-code/charts/environments/pgr-sdc-prd-secrets.yaml:

\# devops/deploy-as-code/charts/environments/pgr-sdc-prd-secrets.yaml

```yaml
secrets:
  db:
    username: "REPLACE_ME"
    password: "REPLACE_ME"                  # Same password used by app and Flyway
    flywayUsername: "REPLACE_ME"
    flywayPassword: "REPLACE_ME"
  gateway:
    jwtSecret: "REPLACE_ME"                 # If your charts require a gateway secret
  gitSync:
    sshPrivateKey: |                        # If you sync configs/MDMS from private Git
      -----BEGIN OPENSSH PRIVATE KEY-----
      <your-private-key>                    # Indented exactly; no extra spaces
      -----END OPENSSH PRIVATE KEY-----
```

Strongly recommended: encrypt this file with sops:

```yaml
# generate age key once per operator machine
age-keygen -o ~/.age/key.txt
export SOPS_AGE_KEY_FILE=~/.age/key.txt
# encrypt in place
sops -e -i devops/deploy-as-code/charts/environments/pgr-sdc-prd-secrets.yaml
```

Keep the \~/.age/key.txt safe and share the public age key with other operators who need to decrypt.
{% endstep %}

{% step %}

### Wire the environment into Helmfile

Most CMS setups have a top-level Helmfile (e.g., devops/deploy-as-code/digit-helmfile.yaml) that references:

* the environments directory for values files, and
* DIGIT/CMS charts you want to deploy.

If your Helmfile uses an -e \<env> switch:

* The env name corresponds to the key used in digit-helmfile.yaml and other sub-helmfiles.

```yaml
environments:
  pgr-sdc-prd:        # this key will be used as environment selector
    values:
      - ./charts/environments/pgr-sdc-prd.yaml
      - ./charts/environments/pgr-sdc-prd-secrets.yaml
```

{% endstep %}

{% step %}

### Deploy with Helmfile (no Go deployer)

```
cd devops/deploy-as-code

Ensure your KUBECONFIG points to the Kubernetes cluster:
export KUBECONFIG=~/kubeconfigs/pgr-sdc.yaml

# (Optional) preview the manifests/plan if supported
helmfile -f digit-helmfile.yaml -e pgr-sdc-prd plan

# Apply
helmfile -f digit-helmfile.yaml -e pgr-sdc-prd apply

If your repo organises Helmfiles differently, adjust the -f path accordingly.

kubectl get nodes
```

{% endstep %}

{% step %}

### Post-Deploy Validation (first-boot)

At the end of the installation, you should have a fully functional CMS/PGR application up and running with default data & English labels. The default workflows, master data, users and labels can then be customised once you’ve verified the setup.&#x20;

Pods up & healthy

```
kubectl get pods --all-namespaces
kubectl get pods -n egov
```

Ingress & TLS

```
kubectl get svc -A | grep LoadBalancer
kubectl get certificate -A
kubectl describe ingress -n egov
```

Gateway routing refresh\
On first bring-up, if the gateway started before all services registered, refresh it once:

```
kubectl rollout restart deployment gateway -n egov

```

**Default data/seeding**&#x20;

Default seed data will be loaded via the data-handler service. This service can be scaled down once the deployment has been verified.

**Smoke tests**

```
# API search (adjust path if fronted via gateway)
curl -sS -X POST https://pgr.<state>.gov.in/pgr-services/v1/requests/_search \
  -H 'content-type: application/json' \
  -d '{"RequestInfo":{"apiId":"org.egov.pt"}, "searchCriteria":{"tenantId":"<tenant-id>"}}' | jq .
```

**UI reachability (citizen/employee)**

\# Open in your browser:

| <p>[https://pgr.\&#x3C;state>.gov.in/digit-ui/citizen](https://pgr.\&#x3C;state>.gov.in/digit-ui/citizen) #CITIZEN PORTAL<br>[https://pgr.\&#x3C;state>.gov.in/digit-ui/employee](https://pgr.\&#x3C;state>.gov.in/digit-ui/employee) #EMPLOYEE PORTAL</p> |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

**Follow the** [**Get Started documen**](https://docs.digit.org/complaints-resolution/deploy/setup/get-started)**t to log in with users and experience CMS.**
{% endstep %}
{% endstepper %}

***

### SDC - Quick Checklist

* DNS ↔ LoadBalancer: A record points to the exact loadbalancer/public IP assigned to ingress.
* Certificates: cert-manager Issuer/ClusterIssuer exists; Certificate Ready for PGR host.
* NFS: PVCs are bound; no CreateContainerConfigError due to missing volumes.
* DB connectivity: db-url, db.username, db.password correct; Flyway can run; API services not crash-looping.
* Kafka/ES (if enabled): bootstrap/hosts reachable.
* Gateway routes: after all services become Ready, restart the gateway once.

***

### Uninstall&#x20;

`cd devops/deploy-as-code`

`helmfile -f digit-helmfile.yaml -e pgr-sdc-prd destroy`

Manually delete leftover PVCs/secrets/certs only if you want a clean slate.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.digit.org/complaints-management/complaints-resolution-v2.10/deploy/setup/production-setup/setup-infrastructure/on-premise.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
