Deployment architecture
DigiFIR runs in three kinds of environment. Development runs everything on one machine with Docker Compose. CI runs the same network in containers. The pilot runs on Kubernetes, hosted in India on NIC/NBF or a MeitY-empanelled cloud: Fabric through the hlf-operator (bevel-operator-fabric v1.14.0), and the backend through a Helm chart.
Environments
| Environment | Fabric network | Backend | Outside systems |
|---|---|---|---|
dev | digifir-network with Docker Compose: 5 CAs, 3 orderers, 6 peers, 6 CouchDB, chaincode servers | PostgreSQL, Redis and SeaweedFS in Docker; the three processes from source | Simulators |
ci | The same network in GitHub Actions | Tests against the real network on request | Simulators |
staging | Kubernetes, to rehearse the pilot | Helm chart | Simulators or test endpoints |
pilot | Kubernetes, one cluster per institution | Helm chart in its own cluster | Live adapters as each is approved |
Pilot topology
- Each institution runs its own cluster, with its own hlf-operator, admission policies and monitoring. Nobody holds another institution's administrator identity.
- The national platform runs the ordering service in one cluster and the backend in a second one. The backend never shares a cluster with the hlf-operator, whose ClusterRole can read every Secret in its cluster.
- Every peer and orderer has an external name on port 443 of its cluster's Istio ingress gateway, with SNI passthrough, so TLS ends at the node and never at the gateway. The orderers' admin API is never exposed.
- The three orderers sit in three zones. The two peers of an institution are spread across nodes and zones, and a disruption budget keeps one running through maintenance.
- Namespaces are
orderer,police-a,police-b,judiciary,forensics,hlf-operator,monitoring, anddigifirfor the backend.
The backend on Kubernetes
The Helm chart digifir-backend deploys:
| Object | What it runs |
|---|---|
Deployment api | REST and server-sent events on port 8080, metrics on 9464; a HorizontalPodAutoscaler from 2 to 10 replicas at 70 % CPU |
Deployment projector | Two replicas: one active per database, the other on standby |
Deployment worker | Two replicas: jobs and the notification outbox |
Job migrations | Database migrations before each install or upgrade |
| Ingresses | Public (the API), internal with client certificates (operators), and a console host reachable only from institution networks |
| PodDisruptionBudgets, ServiceMonitor | At least one pod of each process through drains; Prometheus scraping |
| NetworkPolicies | Default deny, with named egress rules for each outside destination |
Every pod passes the Kubernetes restricted Pod Security profile: non-root, no privilege escalation, all capabilities dropped, a read-only root file system. Secrets are passed only by reference. In the pilot the chart refuses to render without image digests, or if an institution does not have its own HSM token. The officials' console has its own chart, digifir-console.
Outbound traffic
The backend reaches internal services (PostgreSQL, Redis, object storage, the network HSM, the peers) by address, and outside services by name through an SNI egress gateway on port 443 or 465. The allow-list covers Google attestation and FCM, the NIC SMS gateway and mail relay, DigiLocker, eCourts, CCTNS, ICJS, e-Sakshya, e-Forensics, the geocoder and the CERT-In log store. Each destination has its own environment variable and network policy.
Deploying the pilot, in phases
| Phase | Who | What |
|---|---|---|
| 0. Every cluster | Platform team | Pinned tools, the hlf-operator, cluster-wide admission policies (images pinned by digest from an approved registry, no API tokens in Fabric pods), the ingress address allow-list |
| 1. Nodes | Each institution in its own cluster; the national platform for the orderers | The CA, peers, CouchDB and orderers. Two PKI officers enrol the CA registrar from their own workstation and keep its key outside the cluster. Each institution publishes its CA and TLS CA certificates, checked by a second person over another channel. |
| 2. The channel | National platform, then each institution | The platform creates firnational. Every institution verifies the genesis block against what it committed before joining. A job replaces the operator's loose organisation policies with role lists, and the block validation policy is narrowed to orderer nodes. Each institution's reviewers approve the exact chaincode definitions; the judiciary commits only once every member has approved. |
| 3. Monitoring and the backend | Every institution; the national platform | Monitoring in every cluster. The backend starts only after the live channel passes every governance check, and after the institutions agree on the genesis block hash the backend pins. |
Before applying an institution's configuration, k8s.sh preflight <institution> refuses documentation addresses, weak credential files, missing revocation lists, operator-held administrators and CA keys in software.
IMPORTANT
The pilot manifests are validated offline (kubeconform on every overlay, Helm lint and template). Phases 0 to 3 still need a rehearsal on a staging set of clusters that enforce network policies. From MVP to pilot lists every open item.
Validation tooling
deploy/k8s/k8s.sh tools # pinned kind, kubectl, helm, kubeconform, kustomize
deploy/k8s/k8s.sh validate # every overlay and the backend chart, offline
deploy/k8s/k8s.sh preflight police-a # before applying a pilot institution
deploy/k8s/k8s.sh backend-check <values.yaml> # the backend's cluster against a release's values
deploy/k8s/k8s.sh kind-up && deploy/k8s/k8s.sh smoke # CA, orderer, peer, channel, chaincode, one invokeSources: digifir-network docs/KUBERNETES.md, docs/EGRESS.md, README.md; digifir-backend deploy/helm/README.md, docs/architecture/DECISIONS.md ADR-04 and ADR-20.