Skip to content

Afshan738/link-vault

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Link Vault

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.

React Node.js MongoDB Docker Kubernetes Prometheus Grafana

What is Link Vault?

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

Architecture

image

Key Engineering Decisions

Stateful vs Stateless Workload Management

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.

Secrets Management — Credential Isolation

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_URI

Persistent Storage — PersistentVolumeClaim

MongoDB 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: 1Gi

Multi-Stage Dockerfiles — Lean Production Images

Build 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"]

Kubernetes Manifests

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

Quick Start — Kubernetes

Prerequisites

  • kubectl configured against a running cluster or minikube
  • Docker

1. Clone

git clone https://github.com/Afshan738/link-vault
cd link-vault

2. Apply manifests

kubectl apply -f kubernetes/secret.yaml
kubectl apply -f kubernetes/configmap.yaml
kubectl apply -f kubernetes/

3. Verify pods

kubectl get pods
kubectl get pvc

4. Access the app

kubectl port-forward svc/frontend-service 3000:80

Quick Start — Local Development (Docker Compose)

git clone https://github.com/Afshan738/link-vault
cd link-vault
cp .env.example .env      # add your MONGODB_URI
docker-compose up --build

App runs at http://localhost:3000

Environment Variables

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

Tech Stack

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

Author

Afshan Qasim · GitHub · LinkedIn

About

Kubernetes-orchestrated MERN app with Secrets, cAdvisor, Grafana

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors