A production-ready ASP.NET Core 8 REST API with MongoDB Atlas, demonstrating end-to-end DevOps practices — from code to cloud.
┌────────────────────────────────────────────────────────────────┐
│ GitHub (Source of Truth) │
│ main branch ──→ Production develop branch ──→ Staging │
└───────────────────────────┬────────────────────────────────────┘
│ push / PR
▼
┌────────────────────────────────────────────────────────────────┐
│ GitHub Actions CI/CD Pipeline │
│ Quality → Tests → Security Scan → Build → Sign → Deploy │
└───────────────────────────┬────────────────────────────────────┘
│ Helm upgrade
▼
┌─────────────────── AWS EKS Cluster ────────────────────────────┐
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Pod 1 │ │ Pod 2 │ │ Pod 3 │ ← HPA (2-10) │
│ │ API:8080 │ │ API:8080 │ │ API:8080 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ └─────────────┴─────────────┘ │
│ │ │
│ ┌───────┴────────┐ │
│ │ Nginx Ingress │ ← TLS termination │
│ │ + Rate Limit │ │
│ └───────┬────────┘ │
│ │ HTTPS │
└──────────────────────┼─────────────────────────────────────────┘
│
┌───────┴────────────┐
│ MongoDB Atlas │ ← Managed DB (M10+)
│ (Multi-Region) │
└────────────────────┘
Monitoring Stack (separate namespace):
Prometheus → Grafana → Alertmanager → Slack/PagerDuty
OTel Collector → Jaeger (traces)
Seq (structured logs)
| Category | Technology |
|---|---|
| Backend | ASP.NET Core 8, C# 12 |
| Database | MongoDB Atlas (cloud-managed) |
| Auth | JWT + Refresh Token rotation |
| Container | Docker (multi-stage, Alpine) |
| Orchestration | Kubernetes (EKS), Helm 3 |
| IaC | Terraform (AWS EKS, VPC, Secrets) |
| CI/CD | GitHub Actions |
| Registry | GitHub Container Registry (GHCR) |
| Monitoring | Prometheus + Grafana + Alertmanager |
| Tracing | OpenTelemetry + Jaeger |
| Logging | Serilog + Seq |
| Security | Trivy, CodeQL, Cosign (keyless) |
| Networking | Nginx + cert-manager (Let's Encrypt) |
| Testing | xUnit, Moq, FluentAssertions, Bogus |
taskmanager/
├── .github/
│ ├── workflows/
│ │ ├── ci-cd.yml # Main pipeline (test→build→deploy)
│ │ ├── pr-validation.yml # PR checks (title, size, deps)
│ │ └── security-scan.yml # Weekly CodeQL + Trivy scan
│ └── dependabot.yml # Automated dependency updates
│
├── src/TaskManagerApp/
│ ├── Controllers/ # API endpoints
│ ├── Services/ # Business logic
│ ├── Data/ # MongoDB context + indexes
│ ├── Models/ # Domain entities
│ ├── DTOs/ # Request/response + validators
│ ├── Middleware/ # Error handling, security headers
│ ├── Configuration/ # Settings classes
│ └── Program.cs # App bootstrap + DI
│
├── tests/TaskManagerApp.Tests/ # xUnit + Moq + FluentAssertions
│
├── infra/
│ ├── terraform/ # AWS EKS + VPC + Secrets Manager
│ └── helm/taskmanager/ # Helm chart (deploy, HPA, PDB, etc.)
│
├── k8s/base/ # Raw Kubernetes manifests
│
├── monitoring/
│ ├── prometheus/ # Scrape config + alerting rules
│ ├── grafana/ # Dashboards + provisioning
│ ├── alertmanager/ # Routing (Slack + PagerDuty)
│ └── otel-collector.yml # OTLP → Jaeger + Prometheus
│
├── nginx/nginx.conf # Reverse proxy + rate limiting
├── scripts/ # setup.sh, deploy.sh helpers
├── Dockerfile # Multi-stage build
└── docker-compose.yml # Full local dev stack
- Docker Desktop / Docker Engine 24+
- .NET 8 SDK
- MongoDB Atlas account (free M0 cluster works)
git clone https://github.com/yourusername/taskmanager.git
cd taskmanager
# Copy env template
cp .env.example .env
# Edit .env and add your MongoDB Atlas URI + JWT secret
nano .envchmod +x scripts/setup.sh
./scripts/setup.sh devThis will:
- Build the .NET application
- Run all tests
- Start the full Docker stack (API, Nginx, Prometheus, Grafana, Seq, Redis)
- Seed demo data
| Service | URL | Credentials |
|---|---|---|
| API | http://localhost:8080 | — |
| Swagger UI | http://localhost:8080/swagger | — |
| Grafana | http://localhost:3001 | admin / admin |
| Prometheus | http://localhost:9090 | — |
| Alertmanager | http://localhost:9093 | — |
| Seq Logs | http://localhost:5342 | — |
Admin: admin@taskmanager.com / Admin@1234!
User: demo@taskmanager.com / Demo@1234!
# Register
POST /api/auth/register
{
"email": "you@example.com",
"username": "yourname",
"password": "Strong@Pass1",
"firstName": "Your",
"lastName": "Name"
}
# Login
POST /api/auth/login
{ "email": "you@example.com", "password": "Strong@Pass1" }
# → { "accessToken": "...", "refreshToken": "...", "expiresAt": "..." }# Create task
POST /api/tasks
Authorization: Bearer <token>
{
"title": "Set up monitoring",
"priority": "High",
"dueDate": "2025-12-31T00:00:00Z",
"tags": ["devops", "monitoring"],
"estimatedHours": 4
}
# List tasks (paginated + filtered)
GET /api/tasks?page=1&pageSize=20&status=InProgress&priority=High
# Dashboard stats
GET /api/tasks/dashboardpush to develop/main
│
├─→ Code Quality (format check, build, NuGet audit)
│
├─→ Tests (xUnit + MongoDB service container + coverage gate 80%)
│
├─→ Security Scan (Trivy CVE scan + Hadolint Dockerfile lint)
│
├─→ Build & Push (multi-arch linux/amd64+arm64, GHCR)
│ ├── Image signing (Cosign keyless OIDC)
│ └── SBOM generation (SPDX)
│
├─→ Deploy Staging (develop branch)
│ ├── Helm upgrade --atomic
│ ├── kubectl rollout status
│ └── Smoke tests
│
└─→ Deploy Production (main branch, after staging)
├── Helm upgrade --atomic (zero-downtime rolling)
├── kubectl rollout status
├── Production smoke tests (3x retry)
├── GitHub Release created
└── Auto-rollback on failure
# AWS
AWS_ROLE_ARN_STAGING # OIDC role ARN for staging
AWS_ROLE_ARN_PROD # OIDC role ARN for production
AWS_REGION # e.g., us-east-1
# App secrets
MONGODB_URI_STAGING
MONGODB_URI_PROD
JWT_SECRET_STAGING
JWT_SECRET_PROD
# Notifications
SLACK_WEBHOOK_URL
PAGERDUTY_INTEGRATION_KEY # (optional)cd infra/terraform
# Initialize (S3 backend)
terraform init \
-backend-config="bucket=your-terraform-state-bucket" \
-backend-config="region=us-east-1"
# Plan
terraform plan \
-var="environment=production" \
-var="mongodb_uri=$MONGODB_URI" \
-out=tfplan
# Apply
terraform apply tfplanProvisions:
- VPC with public/private subnets across 3 AZs + NAT Gateways
- EKS Cluster (v1.31) with managed node groups (On-Demand + Spot)
- IRSA (IAM Roles for Service Accounts) — Secrets Manager access
- AWS Secrets Manager with KMS encryption for app secrets
- VPC Flow Logs to S3 (90-day retention, compliance)
Metrics (Prometheus + Grafana)
- HTTP request rate, error rate, p50/p95/p99 latency
- CPU/memory per pod, GC collections, thread pool
- Custom SLO dashboards with error budget burn rate
Traces (OpenTelemetry → Jaeger)
- Distributed tracing across HTTP requests
- Tail-based sampling: 100% errors, 10% success
- MongoDB query traces
Logs (Serilog → Seq)
- Structured JSON logs with correlation IDs
- Request/response logging (duration, status, user)
- 90-day TTL on audit logs via MongoDB TTL index
| Alert | Severity | Channel |
|---|---|---|
| API Down | Critical | PagerDuty + Slack |
| Error rate > 5% | Critical | Slack #alerts-critical |
| p95 latency > 1s | Warning | Slack #alerts-warnings |
| Pod crash-looping | Critical | PagerDuty + Slack |
| CPU > 85% | Warning | Slack |
| SLO error budget burning | Critical | Slack #slo-alerts |
- JWT authentication with refresh token rotation (7-day TTL)
- Account lockout after 5 failed login attempts (15min)
- bcrypt password hashing (work factor 12)
- Rate limiting — 100 req/min global, 10/15min for auth endpoints
- Security headers — HSTS, CSP, X-Frame-Options, etc.
- Container security — non-root user, read-only filesystem, no privilege escalation
- Kubernetes — NetworkPolicy, Pod Security Standards (restricted), RBAC
- Secrets — AWS Secrets Manager + KMS encryption (never in env files)
- Supply chain — Cosign keyless image signing + SBOM generation
- Dependencies — Dependabot weekly updates + Trivy/CodeQL scheduled scans
# Run all tests
dotnet test tests/TaskManagerApp.Tests/
# With coverage report
dotnet test tests/TaskManagerApp.Tests/ \
--collect:"XPlat Code Coverage" \
--results-directory coverage
# Generate HTML report
reportgenerator \
-reports:"coverage/**/coverage.cobertura.xml" \
-targetdir:"coverage-report" \
-reporttypes:HtmlCoverage target: 80% (enforced in CI via gate)
# Manual deploy (usually done by CI)
chmod +x scripts/deploy.sh
./scripts/deploy.sh 20241201-abc12345 production- Rolling update strategy (
maxSurge: 1, maxUnavailable: 0) - Pod Disruption Budget — minimum 1 pod always available
- preStop hook — 5s drain before SIGTERM
- gracefulTerminationPeriod — 30s for in-flight requests
- HPA — scales 2-10 pods on CPU/memory
# View logs
docker-compose logs -f api
# Restart API only
docker-compose restart api
# Update and redeploy locally
docker-compose pull && docker-compose up -d
# Check Kubernetes pod status
kubectl get pods -n taskmanager
kubectl describe pod <pod-name> -n taskmanager
kubectl logs <pod-name> -n taskmanager --follow
# Helm rollback (emergency)
helm rollback taskmanager --namespace taskmanagerMIT License — see LICENSE
Built as a DevOps showcase project demonstrating industry-standard practices. Covers: CI/CD, containerization, Kubernetes, IaC, monitoring, security, and testing.