Daily DevOps Log

Table of contents
- Task:
- Brief
- Step 1: Gaining Access to the Remote Server
- Step 2: Stopping the Previous Application
- Step 3: Cleaning Up Previous Files
- Step 4: Cloning and Installing New App
- Using PM2 for Process Management
- Step 6: Setting Up NGINX for Reverse Proxy
- Step 7: Linking and Reloading NGINX
- Step 8: Final Testing
- Challenges Faced & How I Solved Them
- Summary:
- Part 2: Pulling Backend Changes & Redeploying with PM2
- Part 3: CI/CD Pipeline with GitHub Actions for NestJS (info-website)

Task:
Set up and deploy a new Node.js (NestJS) application on a shared GCP server using NGINX and PM2.
Brief
Today’s task was a hands-on experience in real-world server management — precisely the kind of challenge I’m eager to tackle as I advance in my DevOps journey. I was tasked with replacing an existing Node.js (NestJS) application running on a shared Google Cloud Platform (GCP) server. The objective was not only to deploy the new application but also to effectively expose it using NGINX and manage its process efficiently with PM2.
Step 1: Gaining Access to the Remote Server
I was granted access to a shared GCP server via SSH.
Credentials provided:
Private SSH key saved in (
.pem
file)Public IP address
Username
I saved the private key file (e.g.,
gcp-access.pem
inside a keys folder on my desktop) and ran:
chmod 400 ~/Desktop/keys/gcp-access.pem
ssh -i ~/Desktop/keys/gcp-access.pem username@<PUBLIC_IP>
Successfully accessed the server.
Step 2: Stopping the Previous Application
The server was already running another app on port 3000.
I identified the running app by:
sudo netstat tunlp | grep 3000
Got the PID and stopped the app:
kill -9 <PID>
Step 3: Cleaning Up Previous Files
- I removed the old application from the server's home directory:
rm -rf ~/old-app
- Also removed its NGINX config if any reference existed.
Step 4: Cloning and Installing New App
- Cloned the new NestJS app from GitHub:
git clone https://github.com/your-org/info-website.git
cd info-website
npm install
But got:
Error: Port 3000 already in use.
Resolved this by killing the previous process as mentioned above.
Using PM2 for Process Management
- Installed PM2:
npm install -g pm2
Started the app with:
pm2 start npm --name info-website -- start
This allowed me to:
Keep the app alive after SSH logout
View logs and process stats
Easily restart if needed
Step 6: Setting Up NGINX for Reverse Proxy
- Created a new NGINX config file:
sudo vim /etc/nginx/sites-available/info-website
server {
listen 80;
server_name <YOUR_PUBLIC_IP>;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Explanation:
listen 80;
: Listens on HTTP port.server_name
: Sets the server’s domain or IP address.location /
: All requests are passed to port3000
where the app runs.proxy_pass
: Forwards traffic to Node.js backend.proxy_set_header
: Preserves headers like Host and Upgrade (useful for WebSocket support).proxy_cache_bypass
: Ensures the app doesn't serve cached responses when it shouldn’t.
Step 7: Linking and Reloading NGINX
- Linked the config:
sudo ln -s /etc/nginx/sites-available/info-website /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
NGINX config is now live.
Step 8: Final Testing
- Tested app from the server:
curl http://localhost:3000
Then from browser:
http://<PUBLIC_IP>
App loaded successfully.
Challenges Faced & How I Solved Them
Issue | Solution |
Port 3000 in use | Identified with netstat and killed the PID |
App not accessible | Installed and used PM2 to manage app |
NGINX not serving app | Configured new proxy file, tested with nginx -t and reloaded |
Summary:
Learned to SSH into GCP with a
.pem
file.Replaced and deployed a new Node.js app.
Used
netstat
,pm2
, andnginx
to manage processes and expose the app.Now accessible via public IP through NGINX.
In conclusion, today's task provided a valuable hands-on experience in server management and deployment, reinforcing key DevOps skills. By successfully setting up and deploying a new Node.js (NestJS) application on a shared GCP server, I gained practical knowledge in using SSH for server access, managing processes with PM2, and configuring NGINX for reverse proxy. Overcoming challenges such as port conflicts and ensuring application accessibility further enhanced my problem-solving abilities. This experience not only strengthened my technical expertise but also boosted my confidence in handling real-world DevOps scenarios.
Part 2: Pulling Backend Changes & Redeploying with PM2
Task: Update Backend to Reflect New CORS Changes for Frontend Integration
Today, I was tasked with updating the live backend API (NestJS app) deployed on our shared GCP server. The goal was to ensure the frontend team could access the new API endpoints and interact seamlessly — thanks to newly adjusted CORS settings pushed by the backend developers.
Step-by-Step Process
Step 1: SSH into the Server
I accessed the GCP server using the .pem
file:
ssh -i ~/Desktop/keys/gcp-access.pem username@<PUBLIC_IP>
This gave me access to the server's terminal environment, where the info-website
app is running.
Step 2: Navigate to the Project
Once in, I navigated to the app’s directory:
cd ~/info-website
Step 3: Pull the Latest Code
To reflect the updated CORS settings, I pulled the latest commit from the main
branch of our GitHub repository:
git checkout main
git pull origin main
This ensured my server copy matched the developer’s push.
Step 4: Install New Dependencies (if any)
Though no new packages were added in this case, I always run:
npm install
To stay on the safe side in case of any package.json
changes.
Step 5: Restart App with PM2
Using PM2, I restarted the app to load the new changes:
pm2 restart info-website
I confirmed the process with:
pm2 list
Step 6: Final Verification
Tested with
curl -i
http://localhost:3000
to verify server response.Accessed
http://<PUBLIC_IP>
on a browser — the backend is live and responding with the updated CORS headers.Outcome
The backend is now fully updated, and the frontend developers can proceed with integrating the new API endpoints without CORS issues. The process reinforced my knowledge in live patching and restarting server-side Node.js applications with PM2.
Part 3: CI/CD Pipeline with GitHub Actions for NestJS (info-website)
Objective
Automate backend deployment steps like testing, linting, and builds using GitHub Actions. This ensures every push to main
runs a clean workflow to catch errors before manual redeployment.
Subscribe to my newsletter
Read articles from Adesokan Yusuf Segun directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Adesokan Yusuf Segun
Adesokan Yusuf Segun
Hey there! I'm Adesokan Yusuf Segun, a passionate DevOps Engineer and Entrepreneur with a deep love for technology, automation, and innovation. My journey into tech has been a thrilling ride from starting out in fashion entrepreneurship to diving deep into cloud computing and DevOps. I thrive on solving problems, optimizing workflows, and helping businesses scale efficiently. Whether it's CI/CD pipelines, containerization, cloud infrastructure, or automation, I’m always exploring new ways to enhance efficiency and reliability. Beyond tech, I run a self-motivation blog and a YouTube channel, where I inspire young professionals to push beyond limitations, build careers, and embrace financial independence. My blog serves as a guide to navigating digital skills, personal growth, and leveraging AI for success. Here, I share insights on DevOps, cloud computing, automation tools, freelancing, and productivity hacks. My goal is to document my learning journey, mentor aspiring tech professionals, and provide practical, real-world solutions for tech enthusiasts. If you’re passionate about DevOps, cloud computing, remote work, or digital transformation, let’s connect and grow together!