dev-resources.site
for different kinds of informations.
From Code to Cloud: Builds Next.js on GitHub Actions, straight to production
By maintaining, the CI/CD pipelines for build, test, and deployment processes, teams can ensure faster and more reliable releases, reduce the chance of human error, and minimize downtime.
We'll explore how to create a simple CI/CD pipeline to build a Next.js application with GitHub Actions and deploy the built files to an AWS EC2 instance.
Why Build Locally on GitHub Actions?
Traditionally, teams might clone and build their Next.js applications directly on the production server. However, this approach can create several issues:
- Long Build Times: Running the build process on the server can increase CPU usage, slowing down other processes running on the production instance.
- Error Prevention: If the build fails in production, it can lead to partial or broken deployments.
- Wasted Resources: Production servers are often optimized to run applications rather than handle heavy builds or compute tasks.
- Isolation: Keeps the build process separate from the production environment, reducing the risk of server instability.
Moving the build process to GitHub Actions lets you offload compute-intensive tasks to GitHub’s cloud infrastructure. That means your production server only receives fully built and tested files.
Setting Up the GitHub Actions Workflow
Below is the sample file .github/workflows/build-and-deploy.yml
that you can place in your project to automate your Next.js app deployment using github action.
name: Build and Deploy Next.js in AWS EC2 Instance
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
# 1. Check out code
- name: Check out repository
uses: actions/checkout@v3
# 2. Set up Node.js 22 environment
- name: Use Node.js 22
uses: actions/setup-node@v3
with:
node-version: 22
# 3. Install dependencies
- name: Install dependencies
run: npm install
# 4. Create .env file (if you need environment variables at build time)
- name: Create .env file
run: |
echo "AUTH_SECRET=${{ secrets.AUTH_SECRET }}" >> .env
echo "DOMAIN=${{ secrets.DOMAIN }}" >> .env
echo "BASE_URL=${{ secrets.BASE_URL }}" >> .env
# 5. Build your Next.js application
- name: Build
run: npm run build
# 6. Configure SSH (add host key, set up private key)
- name: Configure SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan ${{ secrets.EC2_HOST }} >> ~/.ssh/known_hosts
# 7. Transfer the .next folder to EC2 using SCP
- name: Deploy to EC2
run: |
# 1. Remove the old .next folder on the remote server
ssh -o StrictHostKeyChecking=no ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} \
"rm -rf /home/${{ secrets.EC2_USER }}/app/.next"
# 2. Copy the new .next folder from your Actions workspace to the remote server
scp -o StrictHostKeyChecking=no -r .next ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }}:/home/${{ secrets.EC2_USER }}/app
# 8. Restart the Node.js server
- name: Restart PM2 with pm2.json
run: |
# SSH into the server, navigate to the project directory and restart using pm2.json
ssh -o StrictHostKeyChecking=no ${{ secrets.EC2_USER }}@${{ secrets.EC2_HOST }} \
"cd /home/${{ secrets.EC2_USER }}/app && pm2 stop pm2.json || true && pm2 start pm2.json"
Explanation of Each Step
Check out Repository: Uses actions/checkout@v3 to pull down the code from GitHub so the workflow can run your scripts.
Set up Node.js 22: Ensures the build environment uses Node.js version 22, aligning with your Next.js requirements.
Install Dependencies: Installs all npm packages required for your Next.js application.
Create .env File: Dynamically injects secrets (e.g., AUTH_SECRET, DOMAIN, etc.) into a .env file for the build step. GitHub encrypts these secrets at rest, protecting them from unauthorized access. Add keys as per your project's requirements.
Build Next.js App: Runs npm run build to produce the optimized production build, generating the .next folder.
Configure SSH: Adds your private key to the SSH agent and updates the known hosts. It ensures that your workflow can securely connect to the EC2 instance.
Deploy to EC2: Removes any existing .next folder on the remote server (housekeeping), and Securely transfers the newly built .next folder via scp.
Restart PM2: Stops the existing PM2 process if running, then restarts it using a preconfigured pm2.json to apply updates with minimal downtime.
Configuring SSH
To securely deploy your Next.js application to an AWS EC2 instance using GitHub Actions, you need to establish a secure SSH connection between GitHub and your EC2 server. This involves locally generating an SSH key pair, adding the public key to your EC2 instance's authorized_keys, and storing the private key securely in GitHub Secrets.
1. Generate an SSH Key Pair Locally
First, create an SSH key pair on your local machine. This key pair will authenticate GitHub Actions with your EC2 instance.
# In Terminal (Linux)
ssh-keygen
(Follow the instructions provided)
2. Add the Public Key to EC2 Instance
To allow GitHub Actions to SSH into your EC2 instance, you need to add the generated public key to the authorized_keys file on your server.
# Access Your EC2 Instance
ssh [USER]@[EC2_PUBLIC_IP]
# Create the .ssh Directory (If It Doesn't Exist)
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Add the Public Key to authorized_keys
vi ~/.ssh/authorized_keys
# paste the key into the authorized_keys
cat
~/.ssh/id_rsa.pub
on your local machine. Copy the output and paste it into the authorized_keys file on your EC2 instance. Save and exit the editor.
3. Add the Private Key to GitHub Secrets
On your local machine, copy the contents of the private key cat ~/.ssh/id_rsa
, Navigate to your github
repository and follow the steps:
- Click on the
Settings
tab then Click onSecrets and variables
>Actions
- Click on the
New repository secret
button, Name the secretEC2_SSH_KEY
, paste the copied private key into value, and click on Add Secret
Same as above, add
EC2_USER
andEC2_HOST
for ssh and required .env keys.
Implementing a CI/CD pipeline with GitHub Actions for your Next.js application provides a streamlined, automated, and reliable process from code push to production deployment. By building in GitHub Actions and transferring the final artifacts to your AWS EC2 instance, you reduce the computational overhead on your production server and mitigate the risk of failed builds causing downtime or broken deployments.
If you're new to next.js deployment, I've written a detailed guide on Deploying Next.js App in AWS EC2 with Nginx and PM2.
Featured ones: