Zum Inhalt springen

How I Automated My Next.js Deployments to cPanel with GitHub Actions (and All the Debugging That Came With It)

From FileZilla frustration to smooth, automated deployments — this is a full walkthrough of how I connected GitHub Actions to my cPanel hosting to deploy a Next.js site via FTP. Along the way, I hit some common roadblocks, and I’ll show you how I solved them.

💡 The Problem: Manual Deployments Were Driving Me Nuts

As a web developer managing multiple sites, I’ve always preferred fast, reliable workflows. But when working with clients who host on shared hosting with cPanel, deployment always ended up like this:

  • Build the site locally
  • Open FileZilla
  • Drag and drop the build folder into public_html
  • Hope nothing breaks

That workflow might work for basic static HTML, but I was building modern sites with React and later Next.js. And I knew I needed something more reliable.

So I asked myself:

„Can I connect my GitHub repo directly to cPanel and let it auto-deploy via FTP?“

Turns out — yes. But it took some debugging.

🔧 Step 1: Choose the Deployment Approach

After researching a few methods, I settled on:

GitHub Actions + FTP (via SamKirkland’s FTP-Deploy-Action)

This combo works well if:

  • You’re on shared hosting (no SSH/SFTP access)
  • You want to deploy from main branch
  • You can generate a static site (like from Create React App or exported Next.js)

🏗️ Step 2: Setting Up the Next.js App for Static Hosting

This part depends heavily on whether you’re using React (CRA) or Next.js.

🟢 If You’re Using Create React App (CRA)

You’re in luck. Just run:

npm run build

It creates a build/ folder — this is what you’ll upload via FTP.

🔵 If You’re Using Next.js (like me)

Here’s where things get tricky. Next.js doesn’t generate static files by default — it expects a Node.js server to render pages.

To make it work on cPanel (which doesn’t run Node.js), you must export the app statically:

Step-by-step:

  1. Edit next.config.js:
const nextConfig = {
  output: 'export',
  trailingSlash: true,
};
module.exports = nextConfig;
  1. In package.json, update your build script:
"build": "next build && next-sitemap"

❌ Don’t use next export directly. As of Next 15, next export is deprecated when using App Router.

  1. Now running npm run build will generate an out/ folder — the folder we’ll deploy via FTP.

🐛 Issue I Faced

Initially, I used next export like I did in older Next.js projects. That caused this error:

Error: `next export` has been removed in favor of output: 'export' in next.config.js

✅ Solution: Just define output: 'export' and run next build.

🔐 Step 3: Set Up Secrets in GitHub

Go to your repo > Settings > Secrets > Actions > New Secret:

You’ll need these:

  • FTP_SERVER → Use your server IP (not the domain, unless it resolves correctly)
  • FTP_USERNAME → FTP user (e.g., deployment@yourdomain.com)
  • FTP_PASSWORD → FTP password
  • FTP_SERVER_DIR → The path where you want files deployed

🐛 Issue I Faced

I initially set FTP_SERVER to ftp.afrojazzfestivalnigeria.com, but got this error:

getaddrinfo ENOTFOUND ftp.afrojazzfestivalnigeria.com

✅ Solution: Use your server IP address instead.

Another gotcha:

Error: server-dir should be a folder (must end with /)

✅ Solution: Always make sure FTP_SERVER_DIR ends with a /, e.g. /public_html/

Later, I found out my FTP account was already scoped to the addon domain folder, so I could just use:

FTP_SERVER_DIR=/

⚙️ Step 4: GitHub Actions Workflow File

Here’s my final working .github/workflows/deploy.yml:

name: 🚀 Deploy to cPanel via FTP

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: 📥 Checkout
        uses: actions/checkout@v3

      - name: 🧱 Install Dependencies
        run: npm install

      - name: 🛠️ Build App
        run: npm run build

      - name: 📤 Deploy via FTP
        uses: SamKirkland/FTP-Deploy-Action@v4.3.4
        with:
          server: ${{ secrets.FTP_SERVER }}
          username: ${{ secrets.FTP_USERNAME }}
          password: ${{ secrets.FTP_PASSWORD }}
          server-dir: ${{ secrets.FTP_SERVER_DIR }}
          local-dir: out/

🧪 Final Test — and It Worked!

After pushing to main, I watched the GitHub Actions tab light up:

  • ✅ Dependencies installed
  • ✅ App built to out/
  • ✅ FTP deploy complete

Logged into cPanel — the files were there. Opened the domain in my browser — live site.

🧠 Lessons Learned

  • Next.js requires **output: 'export'**** for static builds**
  • You cannot use **"use client"**** with *generateStaticParams()* in the same file** — split client/server components
  • Use your IP instead of ftp.domain.com if DNS isn’t resolving
  • Always end your server-dir with a /
  • Don’t overthink it — once it works, you can reuse it everywhere

💬 Closing Thoughts

This whole process turned a frustrating manual task into a smooth developer experience. Now I just push to GitHub and let Actions do the rest.

I hope this guide saves you a few hours of trial and error.

If it helped, leave a ⭐ on SamKirkland’s action and let me know how yours went!

🔗 Want to see the site? Visit afrojazzfestivalnigeria.com

📬 Got questions? Reach out on LinkedIn or leave a comment on my post!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert