Deploying Your Project on an Ubuntu VPS with Nginx, GitHub Actions, and SSL Certification

03 February, 2024

Introduction: After successfully connecting to your VPS, let's perform some basic setup steps on our Ubuntu VPS. This guide will walk you through updating packages, installing Nginx, creating a user with appropriate permissions, configuring Nginx, setting up firewall rules, obtaining SSL certification, and deploying your project using GitHub Actions.


Updating and Upgrading Packages: First, ensure your system is up to date by running:

sudo apt update
sudo apt upgrade

Installing Nginx: Install Nginx using the following command:

sudo apt install nginx

Creating a User and Setting Permissions: Create a new user and grant it sudo permissions:

sudo adduser [your_user_name]
sudo usermod -aG sudo [your_user_name]

Grant permissions for the user to create folders and write files:

sudo chmod -R 777 [your_directory_path]

for me it's [your_directory_path] is /var/www, this sudo chmod -R 777 is the command to provide permission to write or create folder as user, inside square bracket you need to put directory path,after that you have to switch to that user


Creating Project Directory and Switching Users: Switch to the newly created user and set up your project directory: Here you will have to create a folder where you will do your necessary work, for me i'll work as name streaming, you need to navigate to your directory where you want to create folder, for me it's /var/www, and this directory only available after nginx install.

su - [your_user_name]
cd /var/www
mkdir streaming
cd streaming

Configuring GitHub Actions: Create a GitHub repository and configure GitHub Actions to deploy your project automatically. i've already created a repository name streaming. go to your repository setting and find action, you will see a option call runner, click that and you will see a option call add runner, click that and after that click self-hosted runner, here you will see differen os option, choose linux and follow the instruction.

Image description Image description

At very last step you need to install some packgae to make your runner active all the time. if you run ./run.sh, it will stay active for momentary but if exit it will be in offline. Sohere we have install a packgae to make it active all the time

sudo ./svc.sh install

after that run it

sudo ./svc.sh start

It will be active all the time, and you can see it in your repository setting, runner option.

Environment(.env) Setup

It's important step to add environment variable in your project before deploying it automatically, you can add environment variable in your repository setting, go to your repository setting and find secret,

Image description Image description

Installing Node.js and PM2: Install Node.js LTS version and PM2 for running your project in the background:

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
npm install -g pm2@latest

You may encounter an error while downloading this package as a user. To avoid this, you can switch to the root user by running the exit command, then proceed with the installation. After that, we'll configure Nginx. You can perform these steps as a root user or as a regular user. For this guide, I'll be executing these steps as a root user. To switch to the root user, use the command cd /root.

node -v
npm -v

Configuring Nginx: Edit the default Nginx configuration file to proxy requests to your application:

sudo nano /etc/nginx/sites-available/default

you'll see default file now let's edit this default file Add the following configuration:

 location / {
            proxy_pass http://localhost:5000;
            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;
        }

**proxy_pass http://localhost:5000 **: This command tells Nginx to forward requests it receives to http://localhost:5000, which is the address of the application you're running. Replace 5000 with the port number your application is running on.

proxy_http_version 1.1: This command sets the version of the HTTP protocol that will be used for the proxy request. In this case, it's HTTP/1.1.

proxy_set_header Upgrade $http_upgrade: This command sets the Upgrade HTTP header to the value of the $http_upgrade variable. This is used for handling WebSocket connections.

proxy_set_header Connection 'upgrade': This command sets the Connection HTTP header to the value 'upgrade'. This is also used for handling WebSocket connections.

proxy_set_header Host $host: This command sets the Host HTTP header to the value of the $host variable. This is used to pass the original host header to the proxied server.

proxy_cache_bypass $http_upgrade: This command tells Nginx to bypass the cache when the $http_upgrade variable is set. This is useful for WebSocket connections, which should not be cached.

N.B: You can replaced localhost:5000 with your port number

Then, restart Nginx:

sudo systemctl restart nginx

Firewall Configuration: Configure the firewall using UFW:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Domain Setting

If you have custom domain and you want to use that domain for your project, you need to add your domain name in the default file, you can find this file in /etc/nginx/sites-available/default, open this file and add your domain name as server_name and save it.

     server_name api.reely.tech;

        location / {
            proxy_pass http://localhost:5000;
            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;
        }

SSL Certification: First Make sure that Nginx Full rule is available

ufw status

Install SSL certification using Let's Encrypt:

sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com

Adjusting Nginx Configuration for File Upload: Edit the Nginx configuration file to allow larger file uploads:

sudo nano /etc/nginx/nginx.conf

Add the following line inside the http block:

client_max_body_size 100M;

Reload Nginx:

sudo systemctl reload nginx

GitHub Actions Deployment: Set up GitHub Actions by creating a .github/workflows/main.yml file in your repository with the provided configuration.

Github Actions

Now we are going to use github actions to deploy our project automatically. so let's go to our github repository and create a folder name .github and inside that folder create a folder name workflows and inside that folder create a file name main.yml. so the path will be .github/workflows/main.yml. now let's copy and paste this code in main.yml file

name: Node.js CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
        build:
        runs-on: self-hosted
        strategy:
        matrix:
                node-version: [14.x]
        steps:
        - uses: actions/checkout@v2
        - name: Use Node.js ${{ matrix.node-version }}
                uses: actions/setup-node@v1
                with:
                node-version: ${{ matrix.node-version }}
        - name: npm install, build, and test
                run: |
                npm install
                npm run build --if-present
                npm run test --if-present
        - name: Deploy to VPS
                pm2 start npm --name "streaming" -- start

configure githbu actions according to your need. This one is for very important cause it will deploy your project automatically after push to master branch. so don't forget to configure it according to your need.,


Conclusion: By following these steps, you can set up and deploy your project on an Ubuntu VPS with Nginx, GitHub Actions, SSL certification, and proper firewall configuration. This comprehensive guide ensures a smooth deployment process for your web application.


Keywords: Ubuntu VPS, Nginx, GitHub Actions, SSL Certification, Firewall Configuration, Node.js, PM2, Deployment, Let's Encrypt, File Upload, Configuration, GitHub Repository.

Got Any ideas to work on?