Skip to main content

Building CI/CD Pipeline with GitHub actions

  • Containerize the application with docker
  • Prepare action scripts – Workflows
  • Push application to docker hub using action runner
  • Pull the application from the docker to your Linux environment
  • Prepare action runner scripts in your Linux environment
  • Install nginx server
  • Install letsencrypt
  • Enable firewall

Create docker files for (Frontend, Backend, Database)

Docker file for frontend

# Stage 1: Build the React.js application
FROM node:20-alpine AS builder

# Accept build argument for VITE_APP_API
ARG VITE_APP_API

# Set environment variable for Vite
ENV VITE_APP_API=${VITE_APP_API}

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Build the application
RUN npm run build

# Stage 2: Serve the built app with Nginx
FROM nginx:stable-alpine

# Remove default Nginx static assets
RUN rm -rf /usr/share/nginx/html/*

# Copy built files from the builder stage
COPY --from=builder /app/dist /usr/share/nginx/html

# Copy your custom server configuration to conf.d
COPY default.conf /etc/nginx/conf.d/default.conf

# Expose port 80
EXPOSE 80

# Start Nginx in the foreground
CMD ["nginx", "-g", "daemon off;"]

Docker file for backend API

# Stage 1: Build the Express.js application
FROM node:18-alpine AS builder

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose the port the app runs on
EXPOSE 5000

# Define the command to run the application
CMD ["node", "index.js"]

Create docker compose file

services:
api:
build:
context: ./track-backend
dockerfile: Dockerfile
ports:
- "8080:5000"
depends_on:
mongodb:
condition: service_healthy
environment:
MONGODB_URI: mongodb://mongodb:27017/mydatabase

portal:
build:
context: ./admin-dashboard
dockerfile: Dockerfile
args:
VITE_APP_API: http://api:5000
ports:
- "8081:80"
depends_on:
- api

mongodb:
image: mongo:6.0
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5

volumes:
mongo-data:

Create Github Actions workflows

Create workflow file in the .github/workflows/prod.yml [script should be here]

Now, go the girepository you're hosting The following should be added in your actions under the secrets & variables in the github repo you’re hosting the code i. DOCKER_USERNAME ii. DOCKER_PASSWORD iii. DATABASE_URL (MongoDB URL in this case) iv. DATABASE_USERNAME v. DATABASE_PASSWORD 4. Ssh to your server a. Using Username & Password i. ssh username@ipaddress ii. Enter your password b. Using SSH keys i. Ssh username@hostname c. Using SSH Config i. ssh name

Update and upgrade the server


sudo apt upgrade && sudo apt update

List users in your linux server

cat /etc/passwd

Add user



adduser [OPTIONS] USERNAME
sudo adduser server

OR

useradd [OPTIONS] USERNAME
sudo useradd username





Del user

userdel username

Add user to suders

sudo usermod -a -G sudo <username>

Enable Firewall

ufw app list #check available apps
ufw allow OpenSSH # allow ssh
ufw enable # enable firewall
sudo ufw allow 443 # enable https for your website


Disable rootlogin


/etc/ssh/sshd_config
PermitRootLogin no #change to no

install and configure nginx

sudo apt install nginx
sudo ufw allow 'Nginx HTTP' # allow nginx ports 80 / 443

Install Docker

sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release

# Add Docker’s official GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 1. Use the following command to set up the **stable** repository. To add the **nightly** or **test** repository, add the word `nightly` or `test` (or both) after the word `stable` in the commands below. [Learn about **nightly** and **test** channels](https://docs.docker.com/engine/install/).


echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine

sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Docker User Permissions


sudo groupadd docker
# Give user to docker permission
sudo gpasswd -a $USER docker
# sometimes the above method does not work
sudo chmod 666 /var/run/docker.sock


Install Docker Compose



sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo mv /usr/local/bin/docker-compose /usr/bin/docker-compose
sudo chmod +x /usr/bin/docker-compose


Install Github Actions

Go to your github account and navigate to the repository you want to add github actions runner and click create self-hosted runner. there will be all the scripts to run

Download GIhutb actions



# Create a folder
$ mkdir actions-runner && cd actions-runner# Download the latest runner package
$ curl -o actions-runner-linux-x64-2.295.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.295.0/actions-runner-linux-x64-2.295.0.tar.gz # Optional: Validate the hash
$ echo "1bde3f2baf514adda5f8cf2ce531edd2f6be52ed84b9b6733bf43006d36dcd4c actions-runner-linux-x64-2.291.1.tar.gz" | shasum -a 256 -c# Extract the installer
$ tar xzf ./actions-runner-linux-x64-2.291.1.tar.gz


Cconfighure github actions


# Create the runner and start the configuration experience
$ ./config.sh --url https://github.com/AsalSolutions/MEAL__CRM --token ADFAMIZOMEXYOUVVCDBJBKLCRODEM# Last step, run it!
$ ./run.sh



Using your self-hosted runner

# Use this YAML in your workflow file for each job
runs-on: self-hosted

Run svc.sh for github actions automation

sudo ./svc.sh help
sudo ./svc.sh install
sudo ./svc.sh status
sudo ./svc.sh start




Install Nginx

Node app deploy with nginx & SSL · GitHub

sudo apt install nginx
sudo systemctl status nginx
sudo systemctl nginx start

OR


sudo apt install nginx-core # version 1.18.0-0ubuntu1.6, or
sudo apt install nginx-extras # version 1.18.0-0ubuntu1.6
sudo apt install nginx-full # version 1.18.0-0ubuntu1.6
sudo apt install nginx-light

Configure Nginx


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


   location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}

Sample Nginx File

server {
root /var/www/html;
# Add index.php to the list if you are using PHP

index index.html index.htm index.nginx-debian.html;

      server_name <domain> www.<domain>;



    location / {

        proxy_pass http://localhost:8000; #whatever port your app runs on
        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;

    }

location /api {

        proxy_pass http://localhost:5000/api; #whatever port your app runs on

        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;

    }

location /graphql {

        proxy_pass http://localhost:5000/graphql; #whatever port your app runs on

        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;

    }

sudo nginx -t # check nginx config

sudo cp default crm.feedback.so

#change server name to server_name crm.feedback.so www.crm.feedback.so;

sudo ln -s /etc/nginx/sites-available/mealcrm.dev.asal.so /etc/nginx/sites-enabled/


sudo apt install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python3-certbot-nginx

sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
sudo certbot --nginx -d crm.feedback.so -d www.crm.feedback.so

Instructions on using install.py script

Make sure you have python 3.9 or higher to run the script, since we're using type hints.

sudo apt update && sudo apt upgrade -y

Update the python version

sudo apt-get install python3.10

Actions setup in github

Go to your repo -> settings -> acitons -> runner -> new runner -> [runner name]

You will get a script to run in your linux server. just follow the steps and you will be good to go.

Run svc.sh for github actions automation

sudo ./svc.sh help
sudo ./svc.sh install
sudo ./svc.sh status
sudo ./svc.sh start