A secure, cloud-native MERN application for saving and organizing web links — built with a DevOps-first architecture. The primary purpose of this project is demonstrating a complete, production-grade Kubernetes deployment workflow where every infrastructure component is defined as version-controlled code.
Most MERN tutorials stop at npm run dev. Link Vault goes further — every
service runs as a Kubernetes workload, every credential lives in a Secret,
and every configuration value is decoupled from the container image.
Key engineering decisions:
- StatefulSet for MongoDB — stable network identity and persistent storage that survives pod restarts, unlike a standard Deployment
- Secrets + ConfigMaps — credentials never hardcoded or passed as plain environment variables. Kubernetes manages injection at runtime
- Multi-stage Dockerfiles — build tools stripped from production images, producing lean, minimal containers
- Live monitoring — Prometheus + cAdvisor expose per-container CPU, memory, and network metrics visualized in Grafana dashboards
The application correctly separates stateful and stateless concerns:
| Service | Controller | Why |
|---|---|---|
| React frontend | Deployment | Stateless — any pod can serve any request |
| Node.js backend | Deployment | Stateless — scales horizontally without coordination |
| MongoDB | StatefulSet | Stateful — needs stable network identity and persistent disk |
A StatefulSet gives MongoDB a predictable pod name (mongo-0) and a stable
DNS entry, so the backend always knows where to connect even after a pod restart.
Sensitive values are stored as Kubernetes Secrets and injected into pods as environment variables at runtime. The application image contains no credentials.
# kubernetes/secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: link-vault-secrets
type: Opaque
stringData:
MONGODB_URI: "mongodb://mongo-0.mongo-service:27017/linkvault"
JWT_SECRET: "your-secret-here"# Referenced in backend deployment
env:
- name: MONGODB_URI
valueFrom:
secretKeyRef:
name: link-vault-secrets
key: MONGODB_URIMongoDB data survives pod restarts because it is written to a PersistentVolume, not the container's ephemeral filesystem.
# kubernetes/mongo-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongo-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1GiBuild tools and source files are stripped from the final image. Only the compiled output and runtime dependencies are included.
# Stage 1 — build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2 — production (no build tools, no source)
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
EXPOSE 5000
CMD ["node", "dist/index.js"]All infrastructure is defined as code in the /kubernetes directory:
kubernetes/
├── secret.yaml # MONGODB_URI, JWT_SECRET
├── configmap.yaml # API_URL, NODE_ENV
├── frontend-deployment.yaml # React — Deployment, replicas: 2
├── frontend-service.yaml # ClusterIP service
├── backend-deployment.yaml # Node.js — Deployment, replicas: 2
├── backend-service.yaml # ClusterIP service
├── mongo-statefulset.yaml # MongoDB — StatefulSet
├── mongo-service.yaml # Headless service for stable DNS
└── mongo-pvc.yaml # PersistentVolumeClaim — 1Gi
kubectlconfigured against a running cluster or minikube- Docker
git clone https://github.com/Afshan738/link-vault
cd link-vaultkubectl apply -f kubernetes/secret.yaml
kubectl apply -f kubernetes/configmap.yaml
kubectl apply -f kubernetes/kubectl get pods
kubectl get pvckubectl port-forward svc/frontend-service 3000:80git clone https://github.com/Afshan738/link-vault
cd link-vault
cp .env.example .env # add your MONGODB_URI
docker-compose up --buildApp runs at http://localhost:3000
| Variable | Source | Description |
|---|---|---|
MONGODB_URI |
Kubernetes Secret | MongoDB connection string |
JWT_SECRET |
Kubernetes Secret | Token signing key |
API_URL |
ConfigMap | Backend API base URL |
NODE_ENV |
ConfigMap | production or development |
| Layer | Technology |
|---|---|
| Frontend | React 18, Vite |
| Backend | Node.js 20, Express.js, Mongoose |
| Database | MongoDB (StatefulSet) |
| Auth | JWT |
| Containerization | Docker, multi-stage builds |
| Orchestration | Kubernetes |
| Config management | Kubernetes Secrets + ConfigMaps |
| Storage | PersistentVolumeClaim |
| Monitoring | cAdvisor, Prometheus, Grafana |
| Local dev | Docker Compose |