Deploying your project from GitHub to VPS using Jenkins for CI/CD
Introduction
In this quick tutorial, I’ll show you how I implemented CI/CD in my Nextjs 14 project on my new VPS server. This blog post is also valid for react projects or applications using nodejs. So you might want to ask, what is Jenkins or CI/CD? So you have pushed your fancy little project to your new VPS server, but you need a way to continually push updates/fixes to your application, that is where Jenkins come in for Continuous Integration/Continuous Delivery (CI/CD).
HEADS UP: An ideal hardware requirement for this is a VPS with at least 2gb of ram. Anything lower than that? you may run into memory issues during build processes. This is a step by step tutorial, please follow religiously.
Getting a VPS server
If you are yet to purchase a VPS, you can quickly purchase from one these cloud providers. But I would recommend getting one (here). It’s cheap and very easy to get started. After signing up, your new VPS credentials (ip address and login) will be sent to your email address.
Initial Server Setup
First, SSH into your server
ssh root@your_server_ip
Create a New User
You may want to create a new user, if you prefer.
adduser your_username
Add user to sudo group
usermod -aG sudo your_username
Switch to the new user
su - your_username
Basic Security Setup
Update system packages
sudo apt update & upgrade -y
Install git and setup firewall
sudo apt install -y curl git ufw
Configuring the firewall to allow some ports we’ll need
sudo ufw allow OpenSSH sudo ufw allow 80 sudo ufw allow 8080 sudo ufw allow 443 sudo ufw enable
Install Node and PM2
We’ll be using nodejs for our Next.js deployment) and PM2 for production process management, you can read more about pm2 here
# Install Node.js using nvm (Node Version Manager) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash source ~/.bashrc # Install Node.js LTS version nvm install --lts # Install PM2 globally npm install -g pm2
Install & Configure Nginx
# Install Nginx sudo apt install nginx -y # Start Nginx sudo systemctl start nginx sudo systemctl enable nginx
Let’s create nginx configuration for your app
sudo nano /etc/nginx/sites-available/your-app
Add this to the configuration (replace your-domain.com with your actual domain name):
server { listen 80; server_name your-domain.com www.your-domain.com; 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; } }
Enable this configuration
sudo ln -s /etc/nginx/sites-available/your-app /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl restart nginx
Setup Jenkins
Now let’s install Jenkins and other dependencies
sudo apt update sudo apt upgrade -y
Install Java (It’s a Jenkins requirement)
sudo apt install openjdk-17-jre-headless -y
Install Jenkins
# Add Jenkins repository curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \ /usr/share/keyrings/jenkins-keyring.adk > /dev/null echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.adk] \ https://pkg.jenkins.io/debian-stable binary/ | sudo tee \ /etc/apt/sources.list.d/jenkins.list > /dev/null # Install Jenkins sudo apt update sudo apt install jenkins -y
Start and enable Jenkins
sudo systemctl start jenkins sudo systemctl enable jenkins
Now we need to login to jenkins
-
Access Jenkins at
http://your_server_ip:8080
-
Retrieve initial admin password:
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
-
Install recommended plugins
-
Create an admin user
-
Create a file name called
Jenkinsfile
at the root in your GitHub repository and paste the below in it.
pipeline { agent any tools { nodejs "NodeJS" } stages { stage('Checkout') { steps { checkout scm } } stage('Install Dependencies') { steps { sh 'npm install' } } stage('Build') { steps { sh 'npm run build' } } stage('Deploy') { steps { sh ''' pm2 delete app_name|| true pm2 start npm --name "app_name" -- start ''' } } } }
Configure GitHub Webhook
-
In your GitHub repository settings, go to Webhooks
-
Add a new webhook:
-
Payload URL:
http://your_server_ip:8080/github-webhook/
-
Content type:
application/json
-
Select events: Push and Pull Request events
Configure Jenkins Installation
For setting up Jenkins for our Next.js project, you'll need to configure several key components/plugins
-
Go to
http://your_server_ip:8080
. On you Jenkins dashboard, Go to "Manage Jenkins" > "Plugins" -
Install NodeJS Plugin
-
To configure the nodejs installation, From the dashboard Go to "Manage Jenkins" > "Tools"
-
Name it (e.g., "NodeJS")
-
Choose a recent Node.js version
-
Check "Install automatically"
-
-
For other plugins to Install, navigate to "Manage Jenkins" > "Plugins":
-
Install these:
-
GitHub Integration Plugin
-
SSH Agent Plugin (for deployment)
-
-
Create a New Pipeline Job
-
Click "New Item"
-
Choose "Pipeline"
-
Configure:
-
Select “Pipeline"
-
Choose "Pipeline Script from SCM"
-
Select “SCM”
-
Choose “git”
-
Enter Repository URL
-
For Credentials, click “add” button
-
Enter your giithub username
-
The password should be your github token. see how to create one here (Ensure you check webhook while creating your token): (https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
-
Specify your production branch (main/master/production), whatever works for you.
-
Apply changes and save
-
-
-
Once you are sure everything is set up, now click on “build now”. This is will execute everything you have in the
Jenkinsfile
. You can check the “Console Output” for the steps it run.
Starting the Application
To view the Jenkins cloned project
cd /var/lib/jenkins/workspace # View it's content ls -1
Start the application
pm2 start npm --name "your_app_name"
Voila! Your app is now running and can be accessed at http://your_server_ip:3000
Conclusion
Thank you for reading to this point, I hope you were able to successfully configure and deploy your application. Keep building and deploying. Until next time, happy coding. ✌🏼
If you have questions, please feel free to drop them in the comments, I’ll do my best to send a response ASAP