0% found this document useful (0 votes)
2 views12 pages

DevOps Placement Guide Module1

The DevOps Deep-Dive Placement Guide provides an in-depth exploration of essential DevOps tools and practices, focusing on Docker, Kubernetes, Jenkins, and CI/CD pipelines. It is structured to enhance interview readiness by detailing concepts, internal workings, commands, and common interview questions, while mapping these to practical experiences from the author's resume. The guide emphasizes the importance of understanding the full DevOps lifecycle and the specific roles of various tools in managing application deployment and infrastructure.

Uploaded by

murphyalice0101
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views12 pages

DevOps Placement Guide Module1

The DevOps Deep-Dive Placement Guide provides an in-depth exploration of essential DevOps tools and practices, focusing on Docker, Kubernetes, Jenkins, and CI/CD pipelines. It is structured to enhance interview readiness by detailing concepts, internal workings, commands, and common interview questions, while mapping these to practical experiences from the author's resume. The guide emphasizes the importance of understanding the full DevOps lifecycle and the specific roles of various tools in managing application deployment and infrastructure.

Uploaded by

murphyalice0101
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

DevOps Deep-Dive Placement Guide

Module 1 — Docker, Kubernetes, Jenkins/CI-CD, AWS EC2, Nginx, PM2, Prometheus & Grafana
Built around Saranya M's resume — EventHub, TRAMS, and Scalezee DevOps Internship

This guide takes every DevOps line on your resume and expands it into interview-ready depth — not just 'what it is'
but 'why it exists, how it works internally, and how to defend it when a product-based company interviewer pushes
back with follow-up questions.'
Each module follows the same structure: Concept → How it works internally → Commands you should be fluent in
→ How it maps to YOUR EventHub project → Common interview questions with model answers → Common
mistakes candidates make.
Module 0: DevOps Foundations — The Big Picture
0.1 What DevOps actually is (beyond the buzzword)
DevOps is the practice of removing the wall between the team that writes code (Dev) and the team that runs it in
production (Ops), by automating the path from a code commit to a running, monitored service. Interviewers care
less about the definition and more about whether you can explain the full pipeline your project actually used.
Your resume shows two live examples of this pipeline:
• EventHub: GitHub push → GitHub Actions CI/CD → AWS EC2 → PM2 (process manager) → Nginx
(reverse proxy) → Prometheus (metrics scraping) → Grafana (dashboards).
• Scalezee internship: manual AWS EC2 setup → Jenkins job pipelines for continuous integration.
Notice these are two different CI/CD tools (GitHub Actions vs Jenkins). You should be able to speak to both —
many product companies still run Jenkins internally even though GitHub Actions is more common in newer stacks.

0.2 The DevOps lifecycle (memorize this flow)


Phase Goal Tools on your resume
Plan Track requirements/issues GitHub Issues/Projects
Code Version control, branching Git, GitHub
Build Compile/package the app npm build, Docker image build
Test Catch bugs before prod GitHub Actions test step
Release Package for deployment Docker image, GitHub Actions artifact
Deploy Push to servers Jenkins, GitHub Actions → AWS EC2
Operate Keep app running PM2, Nginx
Monitor Observe health/performance Prometheus, Grafana

Interview Q: Walk me through what happens from the moment you push code to when a user sees the change live.
A: I push to the main branch on GitHub. That triggers a GitHub Actions workflow which checks out the code,
installs dependencies, runs the build/test step, and if it passes, connects to my AWS EC2 instance over SSH and
pulls the latest code. PM2 then reloads the Node process with zero downtime, and Nginx continues routing incoming
HTTPS traffic to that process on localhost. Prometheus keeps scraping metrics the whole time, so if the deploy
caused a spike in error rate or latency, I'd see it in Grafana within seconds.
Module 1: Docker
1.1 The core problem Docker solves
Before Docker, 'it works on my machine' was a real production issue — different OS versions, different
Node/Python versions, missing environment variables. Docker solves this by packaging your application together
with its entire runtime environment (OS libraries, dependencies, config) into a single unit called an image, which
runs identically anywhere Docker is installed.

1.2 Image vs Container — the distinction interviewers always probe


Image Container
A read-only template/blueprint (like a class) A running instance of an image (like an object)
Built once with `docker build` Created with `docker run`, can start/stop many times
Stored in layers, cached for speed Has its own writable layer on top of the image
Stateless Can hold runtime state until it's removed

1.3 How Docker actually works internally


Docker is not a VM. A virtual machine virtualizes hardware and runs a full guest OS (heavy, slow to boot). Docker
containers instead share the host machine's OS kernel and use three Linux kernel features to isolate processes:
• Namespaces — give each container its own isolated view of PIDs, network interfaces, mount points,
hostname, so it 'thinks' it's the only thing running.
• cgroups (control groups) — limit and account for how much CPU, memory, and I/O each container can use.
• Union file systems (OverlayFS) — let images be built in stacked, cacheable layers, so a rebuild only re-creates
the layers that actually changed.
This is exactly why containers start in milliseconds while a VM takes minutes — you're not booting an OS, you're
just starting an isolated process.

1.4 Dockerfile — commands you must be fluent in


FROM node:18-alpine # base image (alpine = smaller, minimal Linux)
WORKDIR /app # sets working directory inside the container
COPY package*.json ./ # copy dependency manifests first (layer caching!)
RUN npm install --production
COPY . . # copy the rest of the source code
EXPOSE 5000 # documents the port the app listens on
CMD ["node", "[Link]"] # process that runs when the container starts

Why copy [Link] before the rest of the code?


Docker caches each instruction as a layer. If you copy all source code first, ANY code change invalidates the npm
install layer too, forcing a full reinstall on every build. By copying [Link] first, npm install only reruns when
dependencies actually change — this can cut build time from minutes to seconds.

1.5 Multi-stage builds (a strong thing to mention even if your resume doesn't
show it explicitly)
# Stage 1: build
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build

# Stage 2: run only the production output


FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/[Link]"]

This keeps build tools (compilers, dev dependencies) out of the final image, so the production image is dramatically
smaller and has a smaller attack surface.

1.6 Essential commands


Command Purpose
docker build -t app:v1 . Build an image from a Dockerfile
docker run -d -p 5000:5000 app:v1 Run detached, map host:container port
docker ps / docker ps -a List running / all containers
docker logs -f <id> Stream container logs
docker exec -it <id> sh Shell into a running container
docker-compose up -d Start a multi-container app defined in [Link]
docker system prune Remove unused images/containers to free disk space

1.7 Docker networking & volumes (frequently asked)


• Bridge network (default): containers on the same host can talk to each other via container name as hostname.
• Volumes: persist data outside the container's writable layer, so data survives container removal — critical for
databases running in Docker.
• Bind mounts vs named volumes: bind mounts map a host folder directly (useful in dev for live-reload); named
volumes are managed by Docker and are the recommended way to persist data in production.
Interview Q: If containers share the host kernel, how is one container prevented from seeing another container's
processes?
A: Through PID namespaces — each container gets its own process ID tree starting at PID 1, so process 1 inside
container A is a completely different OS-level process than PID 1 inside container B, and neither can see the other's
process list.
Interview Q: Why is an Alpine-based image preferred in production?
A: Alpine Linux is a minimal distro (~5MB base) compared to a full Ubuntu/Debian base (~100MB+), so the
resulting image is smaller, pulls/deploys faster, and has fewer installed packages that could contain vulnerabilities
— a smaller attack surface.

1.8 How to talk about Docker in your EventHub project


Even if EventHub's write-up on your resume emphasizes AWS EC2/PM2/Nginx over Docker specifically, you
should still be ready to explain how you WOULD or DID containerize the Node/Express backend and, separately,
the MongoDB layer, why you'd use docker-compose to wire the app container and a mongo container together with
a shared network, and why that beats installing MongoDB directly on the EC2 host (portability, easy version
pinning, isolation).
Module 2: Kubernetes (K8s)
2.1 Why Kubernetes exists — the problem after Docker
Docker solves 'run one container reliably.' It does not solve: what happens when a container crashes at 3am, how do
you run 10 replicas across multiple machines, how do you roll out a new version without downtime, or how do you
auto-scale under load. Kubernetes is a container orchestration platform that manages exactly this — scheduling, self-
healing, scaling, and networking across a cluster of machines.

2.2 Core architecture — draw this if asked on a whiteboard


Component Role
API Server Front door — every kubectl command and internal component talks through it
etcd Distributed key-value store holding the entire cluster's desired state
Scheduler Decides which node a new Pod should run on
Controller Manager Constantly reconciles actual state to match desired state (e.g. restarts a crashed
Pod)
kubelet (on each node) Agent that actually starts/stops containers as instructed
kube-proxy Handles network rules so Services can route traffic to the right Pods

2.3 Key objects you must know cold


• Pod — the smallest deployable unit; usually one container (sometimes a tightly-coupled sidecar too).
• Deployment — declares 'I want N replicas of this Pod spec running'; handles rolling updates and rollbacks.
• Service — a stable virtual IP/DNS name that load-balances traffic across a changing set of Pods (Pods are
ephemeral and get new IPs when recreated; Services solve that).
• Ingress — routes external HTTP(S) traffic into the cluster to different Services based on hostname/path (this is
the K8s equivalent of what Nginx does on your EC2 setup).
• ConfigMap / Secret — inject configuration and sensitive values (API keys, DB passwords) into Pods without
hardcoding them into the image.
• Namespace — a way to logically partition one cluster (e.g. dev/staging/prod).

2.4 A minimal Deployment + Service YAML


apiVersion: apps/v1
kind: Deployment
metadata:
name: eventhub-backend
spec:
replicas: 3
selector:
matchLabels: { app: eventhub }
template:
metadata: { labels: { app: eventhub } }
spec:
containers:
- name: backend
image: saranya/eventhub-backend:v1
ports: [{ containerPort: 5000 }]
resources:
requests: { cpu: "250m", memory: "256Mi" }
limits: { cpu: "500m", memory: "512Mi" }
---
apiVersion: v1
kind: Service
metadata: { name: eventhub-svc }
spec:
selector: { app: eventhub }
ports: [{ port: 80, targetPort: 5000 }]
type: ClusterIP

2.5 How self-healing and scaling actually work


The Controller Manager continuously compares desired state (from etcd, e.g. 'replicas: 3') to actual state. If a Pod
crashes or a node dies, actual state drops to 2, and the controller immediately schedules a replacement — this is why
Kubernetes is described as declarative and self-healing, versus scripts that imperatively say 'do X then Y.'
Horizontal Pod Autoscaler (HPA) watches a metric like CPU utilization and automatically increases/decreases the
replica count within limits you set — this is the mechanism behind 'auto scaling under load' that interviewers love to
ask about.

2.6 kubectl commands to know


Command Purpose
kubectl apply -f [Link] Create/update objects from a YAML file
kubectl get pods -o wide List Pods with node/IP info
kubectl describe pod <name> Debug — shows events, why a Pod is Pending/CrashLooping
kubectl logs <pod> -f Stream logs from a Pod's container
kubectl rollout status deployment/x Watch a rolling update progress
kubectl rollout undo deployment/x Roll back to the previous version instantly
kubectl scale deployment/x --replicas=5 Manually scale
Interview Q: What's the difference between a Deployment and a StatefulSet, and which would you use for
MongoDB?
A: A Deployment treats all Pod replicas as identical and interchangeable — fine for stateless app servers. A
StatefulSet gives each Pod a stable, unique network identity and stable storage that persists across restarts, which is
what a database like MongoDB needs, since replicas in a Mongo replica set are NOT interchangeable — each one
has its own data and role.
Interview Q: How does a Service know which Pods to send traffic to if Pods keep getting recreated with new IPs?
A: A Service selects Pods by label (e.g. app: eventhub), not by IP. kube-proxy watches the API server for Pods
matching that label and continuously updates the routing rules, so traffic always reaches currently-healthy Pods
regardless of how many times they've been recreated.

2.7 Honest positioning for your resume


Your resume lists Kubernetes under DevOps & Cloud skills, but EventHub's write-up doesn't explicitly show a K8s
deployment. Be ready for: 'I have hands-on Kubernetes fundamentals — Pods, Deployments, Services, and I
understand how it solves problems Docker alone can't (self-healing, scaling, zero-downtime rollouts). For EventHub
specifically I deployed with Docker + PM2 on a single EC2 instance since the scale didn't need a full cluster, but I
designed it so containerizing the services into a K8s Deployment would be a natural next step.' This is honest and
shows judgement rather than overclaiming.
Module 3: Jenkins & CI/CD Pipelines
3.1 What Jenkins is and why companies still use it
Jenkins is an open-source automation server that runs pipelines: sequences of automated steps (build, test, deploy)
triggered by events like a Git push. Even though GitHub Actions is newer and more common for GitHub-hosted
projects, Jenkins remains dominant in large enterprises because it's self-hosted (full control over infrastructure and
security), has a massive plugin ecosystem, and isn't tied to any one Git host.

3.2 Jenkins architecture


• Controller (master) — schedules jobs, serves the web UI, stores configuration.
• Agents (nodes) — separate machines/containers that actually execute the pipeline steps; lets you distribute
load and use different environments per job.
• Jenkinsfile — a text file (checked into your repo) written in Groovy-based DSL that defines the pipeline as
code — this is the modern approach over configuring jobs by hand in the UI.

3.3 A declarative Jenkinsfile — know how to read/write this


pipeline {
agent any
environment {
IMAGE = 'saranya/eventhub-backend'
}
stages {
stage('Checkout') { steps { git branch: 'main', url: '[Link] } }
stage('Install') { steps { sh 'npm ci' } }
stage('Test') { steps { sh 'npm test' } }
stage('Build Image') { steps { sh 'docker build -t $IMAGE:$BUILD_NUMBER .' } }
stage('Push') { steps { sh 'docker push $IMAGE:$BUILD_NUMBER' } }
stage('Deploy to EC2') {
steps {
sshagent(['ec2-ssh-key']) {
sh 'ssh ubuntu@$EC2_HOST "docker pull $IMAGE:$BUILD_NUMBER && pm2 restart
eventhub"'
}
}
}
}
post {
failure { echo 'Pipeline failed — notify team' }
always { echo 'Cleaning workspace' }
}
}

3.4 GitHub Actions — how it differs, and how to map EventHub's pipeline to it
GitHub Actions is GitHub's built-in CI/CD, defined in YAML files under .github/workflows/. Where Jenkins needs
you to host and maintain a server, GitHub Actions runs on GitHub-hosted (or self-hosted) runners with no
infrastructure to manage — this is almost certainly why EventHub used GitHub Actions while your internship used
Jenkins on a company-managed server.
name: Deploy EventHub
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: '18' }
- run: npm ci
- run: npm test
- name: Deploy over SSH
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_KEY }}
script: |
cd /var/www/eventhub && git pull && npm ci --production && pm2 reload
eventhub

3.5 CI vs CD vs Continuous Deployment — precise definitions


Term Meaning
Continuous Integration (CI) Every commit is automatically built and tested, so integration bugs
are caught within minutes, not weeks
Continuous Delivery Code is always in a deployable state; the final push to production is
a manual, one-click decision
Continuous Deployment Every commit that passes tests is automatically deployed to
production with no human step at all
Interview Q: What's the difference between Jenkins and GitHub Actions, and when would you choose one over the
other?
A: Jenkins is self-hosted and highly customizable via plugins, giving full control but requiring you to maintain the
server yourself — good for enterprises with existing infrastructure or complex multi-tool pipelines. GitHub Actions
is fully managed by GitHub, tightly integrated with the repo (triggers, secrets, PR checks), and needs zero server
maintenance — ideal for projects already hosted on GitHub, like EventHub. I used GitHub Actions for EventHub
because it removed the need to run and secure a separate CI server for a project of that scale.
Interview Q: How do you handle secrets like SSH keys or database passwords in a pipeline?
A: Never hardcode them. GitHub Actions has an encrypted Secrets store accessed via ${{ [Link] }};
Jenkins has a Credentials plugin that injects them at runtime without ever printing them in logs. Both mask secret
values automatically in console output.
Interview Q: What happens if a pipeline stage fails halfway through a deployment?
A: A well-designed pipeline fails fast and stops — later stages don't run, so a broken build never reaches the deploy
stage. For zero-downtime, tools like PM2's reload (vs restart) keep the old process serving traffic until the new one
is confirmed healthy, so a failed deploy doesn't cause an outage.
Module 4: AWS EC2 & Cloud Deployment
4.1 What EC2 actually is
EC2 (Elastic Compute Cloud) gives you a virtual machine in AWS's data centers that you fully control — choose
the OS, install anything, open whatever ports you need. It's Infrastructure-as-a-Service (IaaS): AWS manages the
physical hardware and virtualization layer; you manage everything from the OS upward.

4.2 Concepts you must be able to explain, not just name-drop


Concept What it means / why it matters
AMI (Amazon Machine The template (OS + preinstalled software) an EC2 instance is launched from
Image)
Instance type (e.g. [Link]) Defines vCPU/RAM/network allocated; [Link] is the free-tier default, fine for
a student project
Security Group A virtual firewall attached to the instance — you explicitly open ports (22 for
SSH, 80/443 for HTTP/HTTPS)
Elastic IP A static public IP you can attach, so your server's address doesn't change on
reboot
Key Pair Public/private key used for passwordless SSH login instead of a password
EBS Volume Persistent block storage attached to the instance, survives instance stop/start

4.3 Typical deployment flow you should narrate fluently


• Launch instance from an Ubuntu AMI, choose [Link], attach a Security Group opening ports 22/80/443,
download the .pem key pair.
• SSH in: ssh -i [Link] ubuntu@<public-ip>.
• Install Node, PM2, Nginx, Docker as needed.
• Clone repo, set environment variables (.env — never commit secrets), install dependencies.
• Start the app under PM2 so it survives crashes/reboots, then configure Nginx as a reverse proxy in front of it.
• Point a domain's DNS A record at the Elastic IP, then use Certbot for a free TLS certificate so the site serves
over HTTPS.
Interview Q: Why put Nginx in front of your Node app instead of exposing Node directly on port 80?
A: Node apps typically listen on a high port like 3000 or 5000 and running them on port 80 directly would require
root privileges and gives you none of Nginx's benefits — Nginx handles TLS termination, can serve static files
directly without hitting Node, load-balances across multiple Node processes, and shields the app from being publicly
fingerprinted as a raw Node server.
Interview Q: Your EC2 instance rebooted — will your app come back up automatically?
A: Only if PM2 is configured with `pm2 startup` (registers PM2 as a system service) and `pm2 save` (persists the
current process list) — otherwise PM2 itself won't restart after a reboot and neither will the app.
Interview Q: How would you scale EventHub beyond one EC2 instance?
A: Put an Application Load Balancer in front of multiple EC2 instances running the same app (horizontal scaling),
move MongoDB to a managed service like Atlas so app instances stay stateless, and use an Auto Scaling Group to
add/remove instances based on CPU or request-count metrics.
Module 5: Nginx & PM2
5.1 Nginx — reverse proxy fundamentals
A reverse proxy sits in front of your application server and forwards client requests to it, then returns the response
back to the client — the client never talks to Node directly.
server {
listen 80;
server_name [Link];
location / {
proxy_pass [Link]
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Why proxy_set_header matters:


Without forwarding the original headers, your Node app would see every request as coming from Nginx's local IP
([Link]) instead of the real client — breaking things like rate-limiting, logging, or geo-based logic.

5.2 PM2 — process management fundamentals


[Link] apps crash on unhandled exceptions and, by default, that ends the process entirely. PM2 is a process
manager that keeps your app alive: auto-restarts on crash, runs it in the background as a daemon, and enables load-
balancing across CPU cores.

Command Purpose
pm2 start [Link] --name eventhub Start and name a process
pm2 start [Link] -i max Cluster mode — spawns one process per CPU core, load-balanced
pm2 reload eventhub Zero-downtime reload (rolling restart, one instance at a time)
pm2 restart eventhub Hard restart — brief downtime
pm2 logs eventhub Stream logs
pm2 startup && pm2 save Persist PM2 across server reboots
Interview Q: What's the difference between `pm2 restart` and `pm2 reload`?
A: restart kills the current process and starts a new one — there's a brief gap with zero workers serving traffic.
reload (only available in cluster mode) starts new instances first and only kills old ones once the new ones are ready,
giving true zero-downtime deploys.
Module 6: Prometheus & Grafana (Monitoring)
6.1 Why monitoring is its own discipline
Deploying an app isn't the end of DevOps — you need to know if it's healthy. Prometheus + Grafana is one of the
most common open-source monitoring stacks in the industry, and it's a strong signal on your resume that you
understand observability, not just deployment.

6.2 Prometheus — how it works


• Pull-based model: Prometheus periodically scrapes (HTTP GET) a /metrics endpoint exposed by your app or
by exporters — it does not wait for apps to push data to it.
• Time-series database: every metric is stored with a timestamp and labels (key-value pairs), e.g.
http_requests_total{method="GET", status="200"}.
• PromQL: Prometheus's query language, e.g. rate(http_requests_total[5m]) to get requests-per-second averaged
over 5 minutes.
• Node Exporter: a common exporter that exposes host-level metrics (CPU, memory, disk) from your EC2
instance for Prometheus to scrape.
• Alertmanager: a companion tool that fires notifications (Slack/email) when a PromQL expression crosses a
threshold you define.

6.3 Grafana — how it works


Grafana is a visualization layer, not a data store — it connects to Prometheus (or many other data sources) as a
backend and turns PromQL queries into dashboards: line graphs for latency, gauges for CPU, tables for error counts,
with alerting rules layered on top.

6.4 How this fits your EventHub pipeline end-to-end


Your Node app (instrumented with a library like prom-client) exposes /metrics → Prometheus, running as its own
process on EC2 or in a container, scrapes that endpoint every ~15 seconds → Grafana queries Prometheus and
renders dashboards showing request rate, error rate, response latency, and CPU/memory usage of the EC2 host.
Interview Q: Why pull instead of push for metrics collection?
A: Pull-based monitoring means Prometheus itself controls the scrape schedule and can immediately tell if a target
is unreachable (a failed scrape is itself a strong signal something's wrong), and it avoids apps needing to know where
the monitoring server is or handle retries/backpressure if that server is temporarily down.
Interview Q: What's the difference between logging and monitoring?
A: Monitoring (Prometheus/Grafana) answers 'is the system healthy right now, and what's the trend' via numeric
time-series metrics. Logging captures discrete, detailed events (e.g. a specific error stack trace) for after-the-fact
debugging. They're complementary — a Grafana dashboard tells you WHEN something went wrong; logs tell you
WHY.
Module 7: Telling Your Project Story in Interviews
7.1 The 60-second EventHub pitch (memorize a version of this)
"EventHub is a campus event management system I built with a React frontend and Node/Express/MongoDB
backend. Beyond just building the app, I focused on the deployment side: I containerized and deployed it to an AWS
EC2 instance, set up a GitHub Actions pipeline so every push to main automatically tests and redeploys the app,
used PM2 to keep the Node process alive with zero-downtime reloads, and put Nginx in front as a reverse proxy
handling HTTPS. I also added a Prometheus and Grafana monitoring stack so I could watch request rates, latency,
and server health in real time instead of finding out about problems from users."

7.2 Follow-up questions to pre-prepare for


• "What was the hardest part of the deployment?" — pick ONE real decision (e.g. configuring zero-downtime
reload with PM2 cluster mode, or debugging why Nginx returned 502 because the Node process wasn't up yet)
and narrate it concretely.
• "What would you do differently at scale?" — move MongoDB to Atlas, containerize with Docker + push to
ECR, move from a single EC2 to an Auto Scaling Group behind a Load Balancer, consider Kubernetes once
you have multiple services.
• "How did you secure the deployment?" — Security Groups limiting ports, SSH key-based auth (no
passwords), secrets in GitHub Actions Secrets not in code, HTTPS via Certbot/Let's Encrypt.

7.3 What to study next


This document covers Module 1 (DevOps). Say the word and we'll go deep the same way on your next resume areas
— MERN stack internals (Java/OOPS/DBMS core CS fundamentals, or the AI/ML pieces from your other projects)
— whichever the company you're targeting weighs most heavily.

You might also like