Skip to content

abhay1999/dev-env-platform

Repository files navigation

devctl — One-Click Dev Environment Platform

devctl architecture

Go Kubernetes Terraform Docker CI License

Spin up a full MERN, React, or Go + PostgreSQL development environment with a single command — isolated, ephemeral, and auto-destroyed after a TTL.

devctl up --template=mern

# ✅ Environment is ready!
#   URL:       http://abhay-mern.dev.local
#   Namespace: dev-abhay
#   TTL:       30m

The Problem

Every developer has been here:

Pain Point Reality
"It works on my machine" Environment drift between teammates causes hours of debugging
Slow onboarding A new engineer spends a full day getting their local stack running
Version conflicts Multiple projects need conflicting Node/Python/Go versions simultaneously
CI ≠ Local Bugs only appear in production because CI environments don't match local
Leftover containers Forgotten Docker containers consume RAM and cause port conflicts

devctl solves this. Every developer gets a real, isolated Kubernetes namespace with all services wired together — in under 60 seconds. When you're done, devctl down destroys everything cleanly. No leftover containers, no port conflicts, no config drift.


How It Works

devctl up --template=mern
    │
    │  POST /api/v1/environments  {template, username, ttl}
    ▼
Backend API  (202 Accepted immediately)
    ├── CreateNamespace     →  dev-abhay          (labels + TTL annotation)
    ├── ApplyResourceQuota  →  CPU/memory limits
    ├── ApplyPVC            →  mongodb-data (1Gi)
    ├── ApplyConfigMap      →  express-config, react-nginx-config
    ├── ApplyDeployment     →  mongodb, express, react  (with health probes)
    └── ApplyIngress        →  abhay-mern.dev.local → express:3000

CLI polls GET /environments/abhay-mern/status every 3s
    └── Aggregates pod phases → Ready / Provisioning / Error

Architecture

┌──────────────────────────────────────────────────────────────────┐
│                        Developer Laptop                           │
│                                                                   │
│  ┌─────────────┐   HTTP/REST   ┌──────────────────────────────┐  │
│  │  devctl CLI │──────────────▶│   devctl Backend (Go + Chi)  │  │
│  │  (Go/Cobra) │               │   POST /api/v1/environments  │  │
│  └─────────────┘               │   GET  /api/v1/templates     │  │
│                                └──────────────┬───────────────┘  │
│                                               │ client-go         │
│                                               ▼                   │
│                        ┌──────── Kind Cluster ────────────────┐   │
│                        │                                      │   │
│                        │  namespace: devctl-system            │   │
│                        │  ┌──────────────────────────────┐   │   │
│                        │  │  devctl-backend (Deployment) │   │   │
│                        │  │  ClusterRole + RBAC          │   │   │
│                        │  │  CronJob: TTL cleanup/5min   │   │   │
│                        │  └──────────────────────────────┘   │   │
│                        │                                      │   │
│                        │  namespace: dev-<username>           │   │
│                        │  ┌──────────┐ ┌─────────┐ ┌──────┐  │   │
│                        │  │ mongodb  │ │ express │ │react │  │   │
│                        │  │ PVC: 1Gi │ │ /health │ │  /   │  │   │
│                        │  └──────────┘ └────┬────┘ └──┬───┘  │   │
│                        │         ResourceQuota (CPU/Mem)      │   │
│                        │         Ingress → <user>-mern.dev.local  │
│                        └──────────────────────────────────────┘   │
│                                                                   │
│  ┌────────────────────┐   Helm    ┌────────────────────────────┐  │
│  │  Terraform (Kind)  │──────────▶│  ingress-nginx Controller  │  │
│  └────────────────────┘           └────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────┘

Templates

Template Services Ports Persistent Storage
mern MongoDB 7, Express (Node 20), React (nginx) 27017, 3000, 80 MongoDB: 1Gi PVC
react React (nginx 1.25) 80
go-api Go API, PostgreSQL 16 8080, 5432 Postgres: 1Gi PVC

All templates include namespace isolation, health probes, TTL-based auto-cleanup, and ingress routing.

devctl list-templates
# NAME      VERSION   SERVICES
# go-api    1.0.0     api, postgres
# mern      1.0.0     mongodb, express, react
# react     1.0.0     react

Project Structure

dev-env-platform/
│
├── cli/                          # devctl binary (Go + Cobra)
│   ├── cmd/
│   │   ├── root.go               # Global flags, Viper config, env bindings
│   │   ├── up.go                 # devctl up — creates + polls for ready
│   │   ├── down.go               # devctl down — deletes namespace
│   │   ├── status.go             # devctl status [--watch]
│   │   ├── list_templates.go     # devctl list-templates [--output=json]
│   │   ├── version.go            # devctl version
│   │   ├── up_test.go            # Tests: validateTemplate, getEnvStatus
│   │   └── down_test.go          # Tests: runDown against mock HTTP server
│   ├── Dockerfile                # Multi-stage Alpine build
│   ├── Makefile
│   └── go.mod
│
├── backend/                      # REST API server (Go + Chi)
│   ├── main.go                   # Entrypoint: init K8s client, start server
│   ├── internal/
│   │   ├── api/
│   │   │   ├── server.go         # Chi router, middleware wiring
│   │   │   ├── handlers/
│   │   │   │   ├── environments.go    # POST/DELETE/GET + K8sBackend interface
│   │   │   │   ├── templates.go       # GET /templates
│   │   │   │   ├── environments_test.go
│   │   │   │   ├── templates_test.go
│   │   │   │   └── mock_k8s_test.go   # Mock K8s client for unit tests
│   │   │   └── middleware/
│   │   │       ├── auth.go       # Bearer token validation
│   │   │       └── logging.go    # Request logging
│   │   ├── k8s/
│   │   │   ├── client.go         # In-cluster / kubeconfig fallback
│   │   │   ├── namespace.go      # Create/Delete/List namespaces
│   │   │   ├── manifests.go      # ApplyDeployment/Service/ConfigMap/PVC/Ingress
│   │   │   ├── status.go         # Pod phase aggregation → env phase
│   │   │   └── ingress.go        # Extract URL from Ingress rules
│   │   ├── templates/
│   │   │   ├── loader.go         # Embedded FS, ListTemplates, TemplateExists
│   │   │   ├── renderer.go       # Go text/template rendering, BuildVars
│   │   │   └── templates/        # Embedded template manifests
│   │   │       ├── mern/         # MongoDB + Express + React stack
│   │   │       ├── react/        # Standalone React (nginx)
│   │   │       └── go-api/       # Go API + PostgreSQL
│   │   └── models/
│   │       ├── environment.go    # Status enums, request/response types
│   │       └── template.go       # Template, Service structs
│   ├── Dockerfile
│   ├── Makefile
│   └── go.mod
│
├── k8s-manifests/
│   ├── backend/
│   │   ├── deployment.yaml       # devctl-backend: 1 replica, health probes
│   │   ├── service.yaml          # ClusterIP :8080
│   │   ├── clusterrole.yaml      # Full RBAC for namespaces/pods/deployments
│   │   ├── clusterrolebinding.yaml
│   │   └── serviceaccount.yaml
│   └── system/
│       └── cronjob-cleanup.yaml  # Every 5min: delete namespaces past TTL
│
├── terraform/
│   ├── main.tf                   # Kind provider + ingress-nginx Helm release
│   ├── variables.tf
│   ├── outputs.tf
│   └── modules/kind-cluster/     # Reusable Kind cluster module
│
├── scripts/
│   ├── setup.sh                  # Full bootstrap: terraform → deploy backend
│   ├── teardown.sh               # Full cleanup: namespaces → terraform destroy
│   ├── install-devctl.sh         # Build + install CLI to /usr/local/bin
│   ├── dev.sh                    # Hot-reload backend locally
│   └── integration-test.sh       # 9-step E2E: create → verify → status → destroy
│
├── docs/
│   ├── architecture.png          # Architecture diagram (1024×1024)
│   ├── demo.html                 # Animated terminal demo — open in browser
│   ├── STRUCTURE.md              # Full annotated folder tree + design decisions
│   └── DEPLOYMENT.md             # Step-by-step deployment guide (3 options)
│
├── .github/workflows/
│   ├── ci.yml                    # Lint, test (race), validate K8s YAML, build
│   └── release.yml               # GoReleaser + Docker push to GHCR on tag
│
├── .goreleaser.yaml              # Multi-platform CLI builds (Linux/macOS/Windows)
├── docker-compose.yml            # Backend + CLI for local dev (no Kind needed)
└── README.md

Prerequisites

Tool Version Install
Go 1.23+ golang.org/dl
Docker 20+ docs.docker.com
kubectl 1.28+ kubernetes.io/docs
Terraform 1.5+ developer.hashicorp.com
kind 0.22+ Installed automatically by Terraform

Deployment Guide

Full guide with troubleshooting: docs/DEPLOYMENT.md

Option A — Full Kubernetes (Recommended)

1. Clone and bootstrap the cluster

git clone https://github.com/abhaychaurasiya/dev-env-platform.git
cd dev-env-platform
./scripts/setup.sh

This script runs 5 steps automatically:

  1. Checks prerequisites (terraform, kubectl, docker)
  2. Provisions a Kind cluster via terraform apply
  3. Installs ingress-nginx via Helm
  4. Deploys the devctl backend + RBAC into devctl-system
  5. Deploys the TTL CronJob

2. Install the CLI

./scripts/install-devctl.sh
devctl version
# devctl v0.1.0

3. Forward the backend port (separate terminal)

kubectl port-forward -n devctl-system svc/devctl-backend 8080:8080

4. Create your first environment

devctl up --template=mern

# Add to /etc/hosts so the URL works:
echo "127.0.0.1  $(whoami)-mern.dev.local" | sudo tee -a /etc/hosts

# Open in browser:
open http://$(whoami)-mern.dev.local

5. Tear down everything

./scripts/teardown.sh
# Deletes all dev namespaces → removes devctl-system → terraform destroy

Option B — Docker Compose (No Kind required)

Runs the backend using your existing kubeconfig. Useful for testing the API against an existing cluster.

# Spin up the backend
docker compose up -d

# Verify it's healthy
curl http://localhost:8080/healthz
# {"status":"ok"}

curl http://localhost:8080/api/v1/templates
# [{"name":"go-api",...},{"name":"mern",...},{"name":"react",...}]

# Run the CLI as a one-shot container
docker compose --profile cli run cli up --template=react

Option C — Local Development (Hot-reload)

# Terminal 1 — backend with live reload
./scripts/dev.sh

# Terminal 2 — CLI against local backend
export DEVCTL_BACKEND_URL=http://localhost:8080
devctl up --template=react

CLI Reference

devctl up              Spin up a dev environment
devctl down            Tear down a dev environment
devctl status          Show environment status
devctl list-templates  List available templates
devctl version         Print version
Flag Command Default Description
--template / -t up (required) Template: mern, react, go-api
--timeout up 30m Environment TTL (e.g. 1h, 2h)
--username up $USER Namespace isolation key
--name down, status dev-$USER Environment to target
--watch / -w status false Refresh every 5 seconds
--output list-templates table table or json
--backend-url all http://localhost:8080 Backend URL (env: DEVCTL_BACKEND_URL)
--token all Auth token (env: DEVCTL_TOKEN)

Backend API

Method Endpoint Description
POST /api/v1/environments Create environment → 202 Accepted
DELETE /api/v1/environments/{name} Destroy environment → 204 No Content
GET /api/v1/environments/{name}/status Get phase + service statuses → 200
GET /api/v1/templates List available templates → 200
GET /healthz Health check → 200
# Create
curl -X POST http://localhost:8080/api/v1/environments \
  -H "Content-Type: application/json" \
  -d '{"template":"mern","username":"abhay","ttl":"1h"}'

# Status
curl http://localhost:8080/api/v1/environments/abhay-mern/status

Testing

# Backend unit tests (no cluster needed)
cd backend && make test

# CLI unit tests
cd cli && make test

# Full E2E integration test (requires running cluster + backend)
DEVCTL_BACKEND_URL=http://localhost:8080 ./scripts/integration-test.sh

The integration test covers 9 steps: health check → list templates → create → verify namespace → check ResourceQuota → wait for Ready → validate status → teardown → verify deletion.


Auto Teardown

Environments are tagged with an RFC3339 expiry annotation. A CronJob runs every 5 minutes and deletes any namespace past its TTL automatically.

devctl up --template=mern            # Default TTL: 30m
devctl up --template=mern --timeout=2h  # Custom TTL
devctl down                          # Manual teardown anytime

Roadmap

  • CLI — up, down, status, list-templates, version
  • Backend REST API with Kubernetes client-go
  • Namespace isolation + ResourceQuotas
  • Health probes (liveness + readiness) on all containers
  • PVC-backed storage for MongoDB and PostgreSQL
  • TTL-based auto cleanup via CronJob
  • Templates: MERN, React, Go+PostgreSQL
  • GitHub Actions CI + GoReleaser + Docker release pipeline
  • Unit tests (backend handlers + CLI commands)
  • Web UI dashboard
  • Multi-cloud support (EKS, GKE)
  • Secrets management (Vault integration)
  • Logging & monitoring (Loki + Grafana)

License

MIT © Abhay Chaurasiya

About

One-click dev environment platform — spin up isolated MERN/React/Go+PostgreSQL stacks on Kubernetes with a single CLI command

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors