An open API service indexing awesome lists of open source software.

https://github.com/mutugading/goapps-infra


https://github.com/mutugading/goapps-infra

Last synced: 5 months ago
JSON representation

Awesome Lists containing this project

README

          

# GoApps Infrastructure (goapps-infra)

Infrastructure as Code (IaC) for **GoApps Microservices Platform** - managing Kubernetes deployments, monitoring, backups, and GitOps.

---

## πŸ“‹ Table of Contents

1. [Overview](#overview)
2. [Platform Architecture](#platform-architecture)
3. [Technology Stack](#technology-stack)
4. [Repository Structure](#repository-structure)
5. [Quick Start](#quick-start)
6. [Environment Configuration](#environment-configuration)
7. [Infrastructure Components](#infrastructure-components)
8. [Service Deployment](#service-deployment)
9. [Monitoring & Observability](#monitoring--observability)
10. [Backup & Disaster Recovery](#backup--disaster-recovery)
11. [Security & Secrets Management](#security--secrets-management)
12. [CI/CD Pipeline](#cicd-pipeline)
13. [Troubleshooting](#troubleshooting)
14. [Related Documentation](#related-documentation)

---

## Overview

This repository contains all infrastructure configurations for the GoApps platform, including:

- **Kubernetes Manifests**: Deployments, Services, ConfigMaps, Secrets
- **Kustomize Overlays**: Environment-specific configurations (staging/production)
- **Helm Values**: Configuration for Prometheus, Grafana, Loki, ArgoCD
- **GitOps Workflows**: ArgoCD Applications for auto-sync from Git
- **Automation Scripts**: Bootstrap, monitoring, and maintenance scripts

### GoApps Ecosystem Repositories

```
goapps/
β”œβ”€β”€ goapps-infra/ # πŸ”§ Infrastructure (this repo)
β”œβ”€β”€ goapps-backend/ # πŸ–₯️ Backend microservices (Go + gRPC)
β”œβ”€β”€ goapps-frontend/ # 🌐 Frontend application (Next.js)
└── goapps-shared-proto/ # πŸ“ Protocol Buffer definitions
```

| Repository | Description | Tech Stack |
|------------|-------------|------------|
| `goapps-infra` | Infrastructure as Code | Kubernetes, Kustomize, Helm, ArgoCD |
| `goapps-backend` | Microservices APIs | Go, gRPC, PostgreSQL, Redis |
| `goapps-frontend` | Web Application | Next.js 15, React, TypeScript |
| `goapps-shared-proto` | API Contracts | Protocol Buffers, Buf |

---

## Platform Architecture

### High-Level Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ goapps Platform β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ EXTERNAL ACCESS β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ HTTPS β”‚ β”‚ HTTPS β”‚ β”‚ HTTPS β”‚ β”‚ gRPC β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ :443 β”‚ β”‚ :443 β”‚ β”‚ :30090 β”‚ β”‚ :50051 β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ INGRESS LAYER (NGINX) β”‚ β”‚
β”‚ β”‚ TLS Termination + Path-Based Routing β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β–Ό β–Ό β–Ό β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ APPLICATIONS β”‚ β”‚ MONITORING β”‚ β”‚ STORAGE β”‚ β”‚
β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚frontend-svc β”‚ β”‚ β”‚ β”‚ Grafana β”‚ β”‚ β”‚ β”‚ PostgreSQL β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ (Next.js) β”‚ β”‚ β”‚ β”‚ /grafana β”‚ β”‚ β”‚ β”‚ (Primary DB) β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚finance-svc β”‚ β”‚ β”‚ β”‚ Prometheus β”‚ β”‚ β”‚ β”‚ PgBouncer β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ (Go/gRPC) β”‚ β”‚ β”‚ β”‚ /prometheus β”‚ β”‚ β”‚ β”‚ (Pool Conn) β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ iam-svc β”‚ β”‚ β”‚ β”‚ Loki β”‚ β”‚ β”‚ β”‚ Redis β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ (future) β”‚ β”‚ β”‚ β”‚ (Logs) β”‚ β”‚ β”‚ β”‚ (Caching) β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Alertmanagerβ”‚ β”‚ β”‚ β”‚ RabbitMQ β”‚ β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ (Email) β”‚ β”‚ β”‚ β”‚ (Messaging) β”‚ β”‚ β”‚
β”‚ β”‚ GITOPS β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ MinIO β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ ArgoCD β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ (Object Store) β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ /argocd β”‚ β”‚ β”‚ OBSERVABILITY β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚
β”‚ β”‚ β”‚ Jaeger β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ (Tracing) β”‚ β”‚ β”‚
β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

### Namespace Architecture

```mermaid
graph TB
subgraph "Kubernetes Cluster (K3s)"

subgraph "ingress-nginx"
NGINX[NGINX Ingress Controller]
end

subgraph "goapps-staging"
FS_STG[finance-service]
FE_STG[frontend]
end

subgraph "goapps-production"
FS_PRD[finance-service]
FE_PRD[frontend]
end

subgraph "database"
PG[PostgreSQL 18]
PGB[PgBouncer]
REDIS[Redis]
RMQ[RabbitMQ]
EXP[Postgres Exporter]
end

subgraph "minio"
MINIO[MinIO Server]
end

subgraph "monitoring"
PROM[Prometheus]
GRAF[Grafana]
LOKI[Loki]
PROMTAIL[Promtail]
ALERT[Alertmanager]
end

subgraph "observability"
JAEGER[Jaeger]
end

subgraph "argocd"
ARGO[ArgoCD Server]
end
end

NGINX --> FS_STG
NGINX --> FE_STG
NGINX --> FS_PRD
NGINX --> FE_PRD
NGINX --> GRAF
NGINX --> PROM
NGINX --> ARGO

FS_STG --> PG
FS_STG --> REDIS
FS_PRD --> PG
FS_PRD --> REDIS
```

### Data Flow Diagram

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ REQUEST FLOW β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

User Request
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ HTTPS │────▢│ NGINX │────▢│ Frontend │────▢│ Backend β”‚
β”‚ :443 β”‚ β”‚ Ingress β”‚ β”‚ (Next.js) β”‚ β”‚ (gRPC) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ β”‚ β”‚
β–Ό β–Ό β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚PostgreSQLβ”‚ β”‚ Redis β”‚ β”‚ RabbitMQ β”‚ β”‚ Oracle β”‚
β”‚ (Main DB)β”‚ β”‚ (Cache) β”‚ β”‚ (Queue) β”‚ β”‚(External)β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PgBouncerβ”‚ (Connection Pooling)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ BACKUP FLOW β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PostgreSQL │─────▢│ MinIO │─────▢│ Backblaze β”‚
β”‚ pg_dump β”‚ β”‚ (Local S3) β”‚ β”‚ B2 (Cloud) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ VPS Disk β”‚ β”‚ VPS Disk β”‚
β”‚ /mnt/backup β”‚ β”‚ /mnt/backupβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## Technology Stack

### Kubernetes & Orchestration

| Component | Version | Description |
|-----------|---------|-------------|
| K3s | v1.34.x | Lightweight Kubernetes distribution |
| Kustomize | v5.3.0 | Native Kubernetes configuration management |
| Helm | v3.x | Package manager for Kubernetes charts |
| ArgoCD | v7.7.5 | GitOps continuous delivery |

### Database & Storage

| Component | Version | Description |
|-----------|---------|-------------|
| PostgreSQL | 18-alpine | Primary relational database |
| PgBouncer | latest | Connection pooling |
| Redis | 7-alpine | In-memory caching |
| RabbitMQ | 3-management | Message queue |
| MinIO | latest | S3-compatible object storage |

### Monitoring & Observability

| Component | Version | Description |
|-----------|---------|-------------|
| Prometheus | 2.x (via kube-prometheus-stack) | Metrics collection |
| Grafana | 11.x | Visualization & dashboards |
| Loki | 2.x | Log aggregation |
| Promtail | 2.x | Log shipping agent |
| Alertmanager | 0.x | Alert routing & notifications |
| Jaeger | latest | Distributed tracing |

### Networking & Security

| Component | Description |
|-----------|-------------|
| NGINX Ingress Controller | L7 load balancer & TLS termination |
| TLS/SSL | Wildcard certificate (*.mutugading.com) |
| Basic Auth | Prometheus protection (production) |

---

## Repository Structure

```
goapps-infra/
β”‚
β”œβ”€β”€ πŸ“ base/ # Base Kustomize resources (shared)
β”‚ β”œβ”€β”€ argocd/ # ArgoCD base configuration
β”‚ β”‚ └── kustomization.yaml
β”‚ β”œβ”€β”€ backup/ # Backup configurations
β”‚ β”‚ β”œβ”€β”€ cronjobs/ # PostgreSQL backup schedules
β”‚ β”‚ β”‚ β”œβ”€β”€ minio-backup.yaml # MinIO to VPS backup
β”‚ β”‚ β”‚ └── postgres-backup.yaml # 3x daily backups
β”‚ β”‚ β”œβ”€β”€ minio/ # MinIO deployment
β”‚ β”‚ β”‚ β”œβ”€β”€ deployment.yaml
β”‚ β”‚ β”‚ └── service.yaml
β”‚ β”‚ └── kustomization.yaml
β”‚ β”œβ”€β”€ database/ # Database layer
β”‚ β”‚ β”œβ”€β”€ exporter/ # Postgres exporter for metrics
β”‚ β”‚ β”œβ”€β”€ oracle/ # Oracle external service config
β”‚ β”‚ β”œβ”€β”€ pgbouncer/ # Connection pooler
β”‚ β”‚ β”œβ”€β”€ postgres/ # PostgreSQL StatefulSet
β”‚ β”‚ β”œβ”€β”€ rabbitmq/ # Message queue
β”‚ β”‚ β”œβ”€β”€ redis/ # Cache layer
β”‚ β”‚ └── kustomization.yaml
β”‚ β”œβ”€β”€ ingress/ # Ingress base configs
β”‚ β”œβ”€β”€ kubernetes-dashboard/ # K8s Dashboard admin
β”‚ β”œβ”€β”€ monitoring/ # Monitoring stack
β”‚ β”‚ β”œβ”€β”€ alert-rules/ # Grafana alert definitions
β”‚ β”‚ β”œβ”€β”€ dashboards/ # Grafana dashboard JSONs
β”‚ β”‚ β”œβ”€β”€ datasources/ # Grafana datasource configs
β”‚ β”‚ └── helm-values/ # Prometheus/Loki Helm values
β”‚ β”œβ”€β”€ namespaces/ # Namespace definitions
β”‚ β”œβ”€β”€ observability/ # Jaeger tracing
β”‚ └── secrets/ # Secret templates (NOT REAL SECRETS!)
β”‚
β”œβ”€β”€ πŸ“ overlays/ # Environment-specific patches
β”‚ β”œβ”€β”€ staging/ # Staging environment
β”‚ β”‚ β”œβ”€β”€ backup/ # Staging backup paths
β”‚ β”‚ β”œβ”€β”€ backup-patch.yaml # Override backup locations
β”‚ β”‚ β”œβ”€β”€ ingress.yaml # Staging ingress rules
β”‚ β”‚ └── minio/ # Staging MinIO config
β”‚ └── production/ # Production environment
β”‚ β”œβ”€β”€ backup/ # Production backup paths
β”‚ β”œβ”€β”€ backup-patch.yaml # Override backup locations
β”‚ β”œβ”€β”€ ingress.yaml # Production ingress rules
β”‚ └── minio/ # Production MinIO config
β”‚
β”œβ”€β”€ πŸ“ services/ # Application deployments
β”‚ β”œβ”€β”€ finance-service/ # Finance microservice
β”‚ β”‚ β”œβ”€β”€ base/ # Base deployment
β”‚ β”‚ β”‚ β”œβ”€β”€ deployment.yaml # Container spec
β”‚ β”‚ β”‚ β”œβ”€β”€ hpa.yaml # Auto-scaling
β”‚ β”‚ β”‚ β”œβ”€β”€ ingress.yaml # Service ingress
β”‚ β”‚ β”‚ β”œβ”€β”€ kustomization.yaml
β”‚ β”‚ β”‚ └── service.yaml
β”‚ β”‚ └── overlays/
β”‚ β”‚ β”œβ”€β”€ staging/ # Staging overrides
β”‚ β”‚ └── production/ # Production overrides
β”‚ └── frontend/ # Frontend service
β”‚ β”œβ”€β”€ base/
β”‚ └── overlays/
β”‚
β”œβ”€β”€ πŸ“ argocd/ # ArgoCD GitOps configs
β”‚ β”œβ”€β”€ apps/ # ArgoCD Application manifests
β”‚ β”‚ β”œβ”€β”€ shared/ # Shared apps (database, monitoring)
β”‚ β”‚ β”œβ”€β”€ staging/ # Staging-only apps
β”‚ β”‚ └── production/ # Production-only apps
β”‚ └── projects/ # ArgoCD Projects
β”‚
β”œβ”€β”€ πŸ“ scripts/ # Automation scripts
β”‚ β”œβ”€β”€ bootstrap.sh # Initial cluster setup
β”‚ β”œβ”€β”€ reset-k3s.sh # Clean uninstall K3s
β”‚ β”œβ”€β”€ install-monitoring.sh # Install Prometheus/Grafana/Loki
β”‚ β”œβ”€β”€ install-argocd.sh # Install ArgoCD
β”‚ β”œβ”€β”€ install-nginx-ingress.sh # Install NGINX Ingress
β”‚ β”œβ”€β”€ install-runner.sh # Install GitHub Actions runner
β”‚ β”œβ”€β”€ fix-staging.sh # Staging troubleshooting
β”‚ └── fix-production.sh # Production troubleshooting
β”‚
β”œβ”€β”€ πŸ“ docs/ # Documentation
β”‚ β”œβ”€β”€ deployment-guide.md # Step-by-step deployment
β”‚ β”œβ”€β”€ vps-reset-guide.md # Complete VPS reset procedure
β”‚ └── runbooks/ # Operational runbooks
β”‚
β”œβ”€β”€ πŸ“ .github/ # GitHub Actions
β”‚ β”œβ”€β”€ workflows/
β”‚ β”‚ β”œβ”€β”€ ci.yml # Validate manifests & lint
β”‚ β”‚ β”œβ”€β”€ health-check.yml # Scheduled health checks
β”‚ β”‚ └── sync-argocd.yml # ArgoCD sync on push
β”‚ β”œβ”€β”€ ISSUE_TEMPLATE/ # Issue templates
β”‚ β”‚ β”œβ”€β”€ bug_report.md
β”‚ β”‚ β”œβ”€β”€ feature_request.md
β”‚ β”‚ β”œβ”€β”€ new_service.md
β”‚ β”‚ β”œβ”€β”€ incident_report.md
β”‚ β”‚ └── config.yml
β”‚ β”œβ”€β”€ PULL_REQUEST_TEMPLATE.md
β”‚ └── actions/
β”‚ └── argocd-sync/ # Reusable ArgoCD sync action
β”‚
β”œβ”€β”€ .gitignore # Git ignore rules
β”œβ”€β”€ .yamllint.yml # YAML linting config
β”œβ”€β”€ Makefile # Common make targets
β”œβ”€β”€ README.md # This file
β”œβ”€β”€ RULES.md # Development rules & conventions
β”œβ”€β”€ CONTRIBUTING.md # Contribution guidelines
└── LICENSE # Proprietary license
```

---

## Quick Start

### Prerequisites

On VPS (Ubuntu 24.04 LTS):
- SSH access with root/sudo
- Disk partition for backup (`/dev/sdb1`)
- SSL certificates (`ssl-bundle.crt`, `mutugading.com.key`)

On local machine:
- Git installed
- kubectl configured

### 1. Clone Repository

```bash
ssh deploy@
cd ~
git clone https://github.com/mutugading/goapps-infra.git
cd goapps-infra
chmod +x scripts/*.sh
```

### 2. Bootstrap K3s Cluster

```bash
# Staging VPS
./scripts/bootstrap.sh

# Production VPS
ENVIRONMENT=production ./scripts/bootstrap.sh
```

This script will:
- Install K3s (without Traefik - using NGINX Ingress)
- Install Helm
- Create namespaces: `database`, `monitoring`, `minio`, `argocd`, `goapps-staging/production`
- Install VPA (Vertical Pod Autoscaler)

### 3. Create Secrets

> ⚠️ **IMPORTANT**: Secrets must NOT be committed to Git!

```bash
# PostgreSQL
kubectl create secret generic postgres-secret -n database \
--from-literal=POSTGRES_USER=goapps_admin \
--from-literal=POSTGRES_PASSWORD='' \
--from-literal=POSTGRES_DB=goapps

# MinIO
kubectl create secret generic minio-secret -n minio \
--from-literal=MINIO_ROOT_USER=admin \
--from-literal=MINIO_ROOT_PASSWORD=''

# Copy MinIO secret to database namespace
kubectl get secret minio-secret -n minio -o yaml | \
sed 's/namespace: minio/namespace: database/' | \
kubectl apply -f -

# TLS Certificate
kubectl create secret tls goapps-tls -n monitoring \
--cert=ssl-bundle.crt \
--key=mutugading.com.key

# Copy TLS to other namespaces
for ns in argocd ingress-nginx goapps-staging kubernetes-dashboard; do
kubectl create ns $ns 2>/dev/null || true
kubectl get secret goapps-tls -n monitoring -o yaml | \
sed "s/namespace: monitoring/namespace: $ns/" | \
kubectl apply -f -
done

# Grafana SMTP
kubectl create secret generic grafana-smtp-secret -n monitoring \
--from-literal=password=''
```

See [docs/vps-reset-guide.md](docs/vps-reset-guide.md) for complete secrets list.

### 4. Install Monitoring Stack

```bash
export GRAFANA_PASSWORD='your-secure-password'
./scripts/install-monitoring.sh
```

### 5. Apply Base Infrastructure

```bash
# Apply all base configs
kubectl apply -k base/database/
kubectl apply -k base/backup/
kubectl apply -k base/monitoring/alert-rules/
```

### 6. Install ArgoCD

```bash
./scripts/install-argocd.sh
```

### 7. Install NGINX Ingress

```bash
./scripts/install-nginx-ingress.sh
```

### 8. Apply Ingress & ArgoCD Apps

```bash
# Staging
kubectl apply -f overlays/staging/ingress.yaml
kubectl apply -f argocd/apps/staging/
kubectl apply -f argocd/apps/shared/
kubectl apply -f argocd/projects/

# Production
kubectl apply -f overlays/production/ingress.yaml
kubectl apply -f argocd/apps/production/
kubectl apply -f argocd/apps/shared/
kubectl apply -f argocd/projects/
```

### 9. Verify Installation

```bash
make status
```

---

## Environment Configuration

### Staging vs Production

| Aspect | Staging | Production |
|--------|---------|------------|
| **VPS Specs** | 4 core, 8GB RAM | 8 core, 16GB RAM |
| **Domain** | staging-goapps.mutugading.com | goapps.mutugading.com |
| **Backup Mount** | `/staging-goapps-backup` | `/goapps-backup` |
| **ArgoCD Sync** | Automatic | Manual approval |
| **Prometheus Auth** | No auth | Basic Auth required |
| **Namespace** | `goapps-staging` | `goapps-production` |

### Access URLs

#### Staging
| Service | URL |
|---------|-----|
| Grafana | https://staging-goapps.mutugading.com/grafana |
| Prometheus | https://staging-goapps.mutugading.com/prometheus |
| ArgoCD | https://staging-goapps.mutugading.com/argocd |
| MinIO Console | https://staging-goapps.mutugading.com:30090 |

#### Production
| Service | URL |
|---------|-----|
| Grafana | https://goapps.mutugading.com/grafana |
| Prometheus | https://goapps.mutugading.com/prometheus |
| ArgoCD | https://goapps.mutugading.com/argocd |
| MinIO Console | https://goapps.mutugading.com:30090 |

---

## Infrastructure Components

### Database Layer

#### PostgreSQL 18

- **Location**: `base/database/postgres/`
- **Type**: StatefulSet with 20Gi PVC
- **Access**: `postgres.database.svc.cluster.local:5432`

```yaml
# Schemas created automatically:
- finance # Finance service data
- (future schemas added in init-schemas.sql)
```

#### PgBouncer

- **Location**: `base/database/pgbouncer/`
- **Mode**: Transaction pooling
- **Pool Size**: 100 connections
- **Access**: `pgbouncer.database.svc.cluster.local:5432`

#### Redis

- **Location**: `base/database/redis/`
- **Purpose**: Session cache, rate limiting
- **Access**: `redis.database.svc.cluster.local:6379`

#### RabbitMQ

- **Location**: `base/database/rabbitmq/`
- **Purpose**: Async message queue
- **Access**: `rabbitmq.database.svc.cluster.local:5672`
- **Management UI**: Port 15672

### Storage Layer

#### MinIO (S3-Compatible)

- **Location**: `base/backup/minio/`
- **Purpose**: Local object storage for backups
- **Access**: `minio.minio.svc.cluster.local:9000` (API), `:9001` (Console)
- **TLS**: Enabled via NodePort 30090

### Ingress Layer

#### NGINX Ingress Controller

- **Installation**: `scripts/install-nginx-ingress.sh`
- **Purpose**: L7 load balancing, TLS termination, path-based routing
- **Configuration**: `overlays/{staging,production}/ingress.yaml`

---

## Service Deployment

### Service Deployment Pattern

Each service follows the Kustomize base + overlays pattern:

```
services//
β”œβ”€β”€ base/
β”‚ β”œβ”€β”€ deployment.yaml # Container spec
β”‚ β”œβ”€β”€ service.yaml # K8s Service
β”‚ β”œβ”€β”€ hpa.yaml # HorizontalPodAutoscaler
β”‚ β”œβ”€β”€ ingress.yaml # Optional ingress rules
β”‚ └── kustomization.yaml # Kustomize config
└── overlays/
β”œβ”€β”€ staging/
β”‚ β”œβ”€β”€ kustomization.yaml
β”‚ └── patches/
└── production/
β”œβ”€β”€ kustomization.yaml
└── patches/
```

### Finance Service

**Base Configuration** (`services/finance-service/base/`):

```yaml
Ports:
- containerPort: 50051 # gRPC
- containerPort: 8080 # HTTP
- containerPort: 8090 # Metrics (/metrics)

Resources:
Requests: 128Mi memory, 100m CPU
Limits: 512Mi memory, 500m CPU

HPA:
Min: 1, Max: 5 replicas
Target CPU: 70%

Environment Variables:
- DATABASE_HOST: postgres.database.svc.cluster.local
- REDIS_HOST: redis.database.svc.cluster.local
- JAEGER_ENDPOINT: jaeger-collector.monitoring.svc.cluster.local:4317
```

### Deploy New Service

See [RULES.md](./RULES.md) for complete guide on adding new services.

```bash
# 1. Create directory structure
mkdir -p services/new-service/{base,overlays/{staging,production}}

# 2. Copy template from finance-service
cp -r services/finance-service/base/* services/new-service/base/

# 3. Update manifests (image, ports, env)
# Edit services/new-service/base/deployment.yaml

# 4. Create ArgoCD Application
cat > argocd/apps/staging/new-service.yaml << EOF
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: new-service-staging
namespace: argocd
spec:
project: goapps
source:
repoURL: https://github.com/mutugading/goapps-infra.git
targetRevision: main
path: services/new-service/overlays/staging
destination:
server: https://kubernetes.default.svc
namespace: goapps-staging
syncPolicy:
automated:
prune: true
selfHeal: true
EOF

# 5. Commit and push
git add . && git commit -m "feat: add new-service" && git push
```

---

## Monitoring & Observability

### Prometheus

- **Retention**: 30 days
- **Storage**: 20Gi PVC
- **Sub-path**: `/prometheus`
- **Basic Auth**: Production only

### Grafana

- **Persistence**: 10Gi PVC
- **Sub-path**: `/grafana`
- **SMTP**: Email alerts via mgtalert@mutugading.com

#### Available Dashboards

| Dashboard | File | Description |
|-----------|------|-------------|
| Go Apps Overview | `grafana-dashboard-go-apps.json` | Service metrics, HPA status |
| PostgreSQL | `grafana-dashboard-postgres.json` | Database performance |
| Loki Logs | `grafana-dashboard-loki.json` | Centralized logging |

### Alert Categories

| Category | Alert Examples |
|----------|----------------|
| Node Health | High CPU/Memory/Disk usage |
| Pod Status | CrashLoopBackOff, High restart count |
| HPA Scaling | Reached max replicas |
| PVC Storage | Volume nearly full |
| PostgreSQL | Connection pool exhausted, Slow queries |
| Backup | Backup job failed, Old backups |

### Jaeger Tracing

- **Namespace**: `observability`
- **Collector**: `jaeger-collector.monitoring.svc.cluster.local:4317`
- **Access**: Port-forward to localhost:16686

---

## Backup & Disaster Recovery

### Backup Strategy

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ BACKUP STRATEGY β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Target β”‚ Destination β”‚ Schedule β”‚ Retention β”‚ Type β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ PostgreSQL β”‚ MinIO (Local) β”‚ 3x daily β”‚ 7 days β”‚ pg_dump β”‚
β”‚ PostgreSQL β”‚ Backblaze B2 β”‚ 3x daily β”‚ 7 days β”‚ pg_dump β”‚
β”‚ PostgreSQL β”‚ VPS Disk β”‚ 3x daily β”‚ 7 days β”‚ pg_dump β”‚
β”‚ MinIO β”‚ VPS Disk only β”‚ Daily β”‚ 7 days β”‚ mc mirror β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

### Backup Schedule

| CronJob | Time (WIB) | Timezone |
|---------|------------|----------|
| `postgres-backup-morning` | 06:00 | Asia/Jakarta |
| `postgres-backup-afternoon` | 14:00 | Asia/Jakarta |
| `postgres-backup-night` | 22:00 | Asia/Jakarta |
| `minio-backup` | 03:00 | Asia/Jakarta |

### Backup Locations

| Environment | VPS Path | MinIO Bucket |
|-------------|----------|--------------|
| Staging | `/staging-goapps-backup/postgres` | `postgres-backups` |
| Production | `/goapps-backup/postgres` | `postgres-backups` |

### Manual Backup

```bash
# Trigger backup manually
make backup-now

# Or directly
kubectl create job --from=cronjob/postgres-backup-morning \
postgres-backup-manual-$(date +%Y%m%d%H%M%S) -n database
```

### Restore Procedure

```bash
# 1. List available backups
ls -la /mnt/goapps-backup/postgres/
# or
mc ls minio/postgres-backups/

# 2. Copy backup to pod
kubectl cp .sql.gz database/postgres-0:/tmp/

# 3. Restore
kubectl exec -it postgres-0 -n database -- bash -c "
gunzip -c /tmp/.sql.gz | psql -U postgres -d goapps
"
```

---

## Security & Secrets Management

### Secrets Checklist

| Secret Name | Namespace | Required Keys |
|-------------|-----------|---------------|
| `postgres-secret` | database | POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB |
| `minio-secret` | minio, database | MINIO_ROOT_USER, MINIO_ROOT_PASSWORD |
| `rabbitmq-secret` | database | RABBITMQ_USER, RABBITMQ_PASSWORD |
| `oracle-credentials` | goapps-* | ORACLE_HOST, ORACLE_PORT, ORACLE_*_USER, ORACLE_*_PASSWORD |
| `goapps-tls` | multiple | tls.crt, tls.key |
| `grafana-admin-secret` | monitoring | admin-user, admin-password |
| `grafana-smtp-secret` | monitoring | password |
| `s3-cloud-credentials` | database | S3_ENDPOINT, S3_BUCKET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY |
| `ghcr-secret` | goapps-* | Docker registry credentials |
| `prometheus-basic-auth` | monitoring | auth (htpasswd format) |

### Security Rules

1. **Never commit secrets to Git** - Use `kubectl create secret` manually
2. **Use separate passwords per environment** - Staging β‰  Production
3. **Rotate credentials regularly** - Especially for production
4. **Limit secret access** - Use RBAC appropriately
5. **Monitor secret access** - Enable audit logging

---

## CI/CD Pipeline

### GitHub Actions Workflows

#### 1. CI Workflow (`ci.yml`)

Triggers: Push to `main`/`develop`, PRs to `main`

Steps:
1. Validate base kustomizations
2. Validate staging/production overlays
3. Validate service manifests
4. Lint YAML files (yamllint)
5. Security scan (Trivy)

#### 2. ArgoCD Sync (`sync-argocd.yml`)

Triggers: Push to `main` (paths: base/**, overlays/**, services/**, argocd/**)

Steps:
1. Sync staging applications (automatic)
2. Sync production applications (manual dispatch only)
3. Wait for applications to be healthy

#### 3. Health Check (`health-check.yml`)

Triggers: Scheduled (cron), manual dispatch

Steps:
1. Check cluster connectivity
2. Verify critical pods status
3. Report health status

### Self-Hosted Runners

Runner labels:
- `staging`: Runs on staging VPS
- `production`: Runs on production VPS
- `goapps-runner`: Common label for all runners

Install runner:
```bash
./scripts/install-runner.sh
```

---

## Troubleshooting

### Common Issues & Solutions

#### Pod CrashLoopBackOff

```bash
# Check pod events
kubectl describe pod -n

# Check previous logs
kubectl logs -n --previous
```

#### Database Connection Issues

```bash
# Test PostgreSQL directly
kubectl exec -it postgres-0 -n database -- \
psql -U goapps_admin -d goapps -c "SELECT 1"

# Test via PgBouncer
kubectl run test-pg --rm -it --image=postgres:18-alpine -- \
psql -h pgbouncer.database -U goapps_admin -d goapps
```

#### Ingress Not Working

```bash
# Check ingress status
kubectl get ingress -A
kubectl describe ingress -n

# Check NGINX controller logs
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx
```

#### ArgoCD Sync Failed

```bash
# Get ArgoCD password
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d

# Check application status
kubectl get applications -n argocd

# Force sync
argocd app sync --force
```

#### Storage Issues

```bash
# Check PVC status
kubectl get pvc -A

# Check PV status
kubectl get pv

# Describe PVC
kubectl describe pvc -n
```

### Useful Commands

```bash
# Cluster overview
make status

# PostgreSQL logs
make logs-postgres

# ArgoCD logs
make logs-argocd

# Port forward Grafana
make port-forward-grafana

# Port forward ArgoCD
make port-forward-argocd

# Validate manifests
make lint

# Manual backup
make backup-now
```

---

## Related Documentation

| Document | Path | Description |
|----------|------|-------------|
| Development Rules | [RULES.md](./RULES.md) | Conventions and guidelines |
| Contributing Guide | [CONTRIBUTING.md](./CONTRIBUTING.md) | How to contribute |
| Deployment Guide | [docs/deployment-guide.md](./docs/deployment-guide.md) | Step-by-step deployment |
| VPS Reset Guide | [docs/vps-reset-guide.md](./docs/vps-reset-guide.md) | Complete VPS reset |
| License | [LICENSE](./LICENSE) | Proprietary license |

### Issue Templates

| Template | Description |
|----------|-------------|
| [πŸ› Bug Report](.github/ISSUE_TEMPLATE/bug_report.md) | Report bugs or infrastructure issues |
| [✨ Feature Request](.github/ISSUE_TEMPLATE/feature_request.md) | Request new features or enhancements |
| [πŸš€ New Service](.github/ISSUE_TEMPLATE/new_service.md) | Request deployment for new service |
| [🚨 Incident Report](.github/ISSUE_TEMPLATE/incident_report.md) | Report production incidents |

### Pull Request Template

All PRs use the standard template: [PULL_REQUEST_TEMPLATE.md](.github/PULL_REQUEST_TEMPLATE.md)

---

## Support & Contact

- **Team**: GoApps DevOps
- **Organization**: PT Mutu Gading Tekstil
- **Repository Issues**: [GitHub Issues](https://github.com/mutugading/goapps-infra/issues)

---

## License

This project is proprietary software. See the [LICENSE](./LICENSE) file for details.

**Β© 2024-2026 PT Mutu Gading Tekstil. All Rights Reserved.**