Hanwool Codes RSS Tag Admin Write Guestbook
Web Development (2)
2025-04-16 04:25:02

If you’re running a Next.js application on an Ubuntu server, you probably want a clean workflow to update your production app every time you push to GitHub. In this guide, we’ll walk through setting up GitHub webhooks, a small server to receive them, and a deployment script that builds and restarts your app with PM2.


✅ Prerequisites

  • A public or private Ubuntu server
  • Node.js, npm, and PM2 installed
  • A running Next.js app managed by PM2
  • Your app hosted on GitHub (private or public)
  • SSH access to your server

Step 1: Generate SSH Key for GitHub (if needed)

On your Ubuntu server, generate an SSH key so the server can authenticate with GitHub and pull code automatically:

ssh-keygen -t rsa -b 4096 -C "your-github-email@example.com"

Press Enter to accept the default path (~/.ssh/id_rsa).
Now, copy the public key:

cat ~/.ssh/id_rsa.pub

Go to GitHub > Settings > SSH and GPG keys > New SSH key, and paste it in.
Test the connection:

ssh -T git@github.com

You should see a “You’ve successfully authenticated” message.


Step 2: Clone Your Repository

Pick a directory for your app and clone your GitHub repo:

cd /var/www
git clone git@github.com:your-username/your-repo.git
cd your-repo

Install dependencies and build the project:

npm install
npm run build

Start the app with PM2:

pm2 start npm --name "your-app-name" -- start
pm2 save

Step 3: Create the Deployment Script

Create a shell script that will handle updates:

nano ~/deploy.sh

Add this content:

#!/bin/bash

cd /var/www/your-repo

echo "Pulling latest changes..."
git pull origin main

echo "Installing dependencies..."
npm install

echo "Building the app..."
npm run build

echo "Restarting app with PM2..."
pm2 restart your-app-name

echo "Deployment complete!"

Make it executable:

chmod +x ~/deploy.sh

Step 4: Set Up a Webhook Listener

Create a simple Express server that listens for GitHub webhooks:

mkdir ~/webhook && cd ~/webhook
nano server.js

Paste the following code:

const express = require("express");
const { exec } = require("child_process");

const app = express();
app.use(express.json());

app.post("/webhook", (req, res) => {
  const payload = req.body;

  if (payload.ref === "refs/heads/main") {
    console.log("Push to main detected. Starting deployment...");
    exec("bash ~/deploy.sh", (err, stdout, stderr) => {
      if (err) {
        console.error(`Deployment error: ${err.message}`);
        return res.status(500).send("Deployment failed.");
      }
      console.log(stdout);
      console.error(stderr);
      res.status(200).send("Deployment complete.");
    });
  } else {
    res.status(200).send("Push ignored (not main branch).");
  }
});

const PORT = 4000;
app.listen(PORT, () => {
  console.log(`Webhook server listening on port ${PORT}`);
});

Initialize and install dependencies:

npm init -y
npm install express

Start the server using PM2:

pm2 start server.js --name webhook
pm2 save

Step 5: Open the Webhook Port (Optional)

If your firewall is active, allow the webhook port:

sudo ufw allow 4000

Step 6: Set Up GitHub Webhook

In your GitHub repo:

  1. Go to Settings > Webhooks > Add webhook
  2. Payload URL:
    http://your-server-ip:4000/webhook
  3. Content type:
    application/json
  4. Leave secret empty (or handle it in code if using)
  5. Events: Just the push event
  6. Save webhook

Step 7: Test the Deployment Flow

Make a small commit to the main branch:

git add .
git commit -m "Test auto-deploy"
git push origin main

Then monitor the webhook log:

pm2 logs webhook

You should see output indicating that the deployment script was triggered, the app was rebuilt, and restarted via PM2.


What Are the Advantages of Using This Webhook Setup?

  1. Hands-Free Deployment
    Every time you push to the main branch, your app automatically updates — no need to SSH into the server, pull manually, or restart services.

  2. Fast Feedback Loop
    Code changes go live in seconds, keeping development and production in sync. This is especially useful for small teams or solo developers.

  3. No External CI/CD Needed
    You don’t need to rely on tools like GitHub Actions, Jenkins, or CircleCI. Everything runs locally on your own server, which is great for simplicity and control.

  4. Customizable Deployment Logic
    You have full control over the deployment process. Want to run tests, update environment variables, or notify Slack? Just add it to your deploy.sh.

  5. Lightweight & Resource-Friendly
    Unlike full CI/CD tools that require containers or background jobs, this setup runs with minimal overhead — just a simple Express server and PM2.

  6. Works with Private Repos
    Since you're using SSH keys to authenticate with GitHub, this works equally well with private repositories.

  7. Secure by Design
    You can lock down access to the webhook port, use GitHub IP whitelisting, and add secret token verification for even more security.

  8. Great for VPS and Self-Hosted Environments
    Whether you're using DigitalOcean, Hetzner, Linode, or your own machine, this approach is ideal for traditional Ubuntu-based deployments.

'Web Development' 카테고리의 다른 글

Fixing JS and CSS Not Loading in Next.js on GitHub Pages  (0) 2025.04.10
2025-04-10 04:45:54

If you're deploying your Next.js 13+ app to GitHub Pages and running into issues where your JavaScript and CSS aren't loading, you're not alone. This issue usually comes down to how GitHub Pages handles static files — especially those in folders that start with an underscore like /_next.

Let me walk you through how to fix it step-by-step. 👇

 


 

🧠 The Problem

 

By default, GitHub Pages uses Jekyll, which ignores folders starting with _, like:

/_next/static/...

 

This means your app's static assets (JS, CSS) won't be served — resulting in a broken site with missing styles and scripts. 😵

 


 

The Solution

 

1. Add .nojekyll file

This file disables Jekyll processing on GitHub Pages.

You can add this manually in the out folder after next export, or automatically via a script:

 

touch out/.nojekyll

 

Or use shx to make it cross-platform compatible (for Windows users):

npm install --save-dev shx

 

2. Install gh-pages

 

You’ll need the gh-pages package to deploy the out folder to your GitHub Pages branch.

Install it with:

npm install --save-dev gh-pages

 

This tool will handle publishing your static site to the correct branch (typically gh-pages or main).

 

3. Update next.config.js

 

Configure your app for static export:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'export', // Static export for GitHub Pages
  basePath: '',     // Leave empty for username.github.io
};

module.exports = nextConfig;

 

If you're deploying to a project page (e.g., username.github.io/my-app), set:

basePath: '/my-app',
assetPrefix: '/my-app',

 

 

4. Update your package.json scripts

"scripts": {
  "dev": "next dev",
  "build": "next build",
  "export": "next export",
  "postexport": "shx touch out/.nojekyll",
  "deploy": "next build && npm run postexport && gh-pages -d out --nojekyll --cname https://yourusername.github.io"
}

 

📝 Replace https://yourusername.github.io with your GitHub URL.

 

 


 

🏁 Deployment Command

npm run deploy

 

Boom 💥 — your Next.js site should be live and functional!

 


 

🔄 GitHub Pages Branch Setup

  1. Go to GitHub → Settings → Pages
  2. Source: Deploy from branch
  3. Branch: gh-pages, folder: / (root)
  4. Save ✅

 

🔗 Bonus Tips

  • Use --cname for custom domains
  • Use proper basePath if using a project subfolder
  • Automate deploys with GitHub Actions

📦 Example Repo

 

Check out: https://github.com/sky4689524/sky4689524.github.io

 

GitHub - sky4689524/sky4689524.github.io

Contribute to sky4689524/sky4689524.github.io development by creating an account on GitHub.

github.com


 

🧰 Tools Used

 



Hanwool Codes. Designed by 코딩재개발.