Site icon hostingxp.com

Guide To Deploying Next.js to Cloudways with GitHub Actions

Guide to Deploying Next.js to Cloudways with GitHub Actions

In modern web development, speed and reliability are paramount. Manually deploying a Next.js application, especially one optimized for SEO, can be a tedious and error-prone process. The ideal solution is an automated “push-to-deploy” system where your application updates itself every time you push code to your repository.

This guide provides a comprehensive walkthrough on how to create a powerful, automated CI/CD pipeline. We will leverage the strengths of Next.js for building high-performance, SEO-friendly applications, the simplicity and power of Cloudways managed hosting, and the flexibility of GitHub Actions to tie it all together. By the end of this article, you will have a production-ready workflow that deploys your Next.js project to Cloudways automatically and securely.

Interactive Guide: Deploying Next.js to Cloudways with GitHub Actions

Cloudways + Next.js + GitHub Actions

A Comprehensive Guide to Deploying a Next.js Application on Cloudways with GitHub Actions

From code commit to live production, master the art of automated deployments. This guide details a powerful CI/CD pipeline integrating Next.js, Cloudways, and GitHub Actions for a seamless "Git push to deploy" experience.

Strategic Overview

The Modern Web Deployment Triad

The successful deployment of modern web applications hinges on a robust and efficient architecture. This report details a powerful deployment strategy that integrates three core components: Next.js, a leading React framework; Cloudways, a managed cloud hosting platform; and GitHub Actions, a flexible CI/CD engine. This combination provides development velocity, hosting stability, and deployment reliability.

The "Git Push to Deploy" Workflow

1. Git Push

Developer commits code to `main` branch.

2. Build & Test

GitHub Actions builds the Next.js app.

3. Secure Transfer

`rsync` build artifacts to server via SSH.

4. Deploy & Restart

PM2 restarts the app with zero downtime.

Preparing the Next.js App

The 'Standalone' Output: A Critical Optimization

For self-hosted environments like Cloudways, the single most important optimization is to configure the Next.js build to produce a standalone output. This drastically reduces the size of the deployment artifact.

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
};

module.exports = nextConfig;

Build Output Comparison

Default Build

~250MB+

Includes ALL dependencies from `node_modules`, including `devDependencies`.

'Standalone' Build

~25MB

Traces and includes ONLY production dependencies. Lean and fast.

Final Build Step: Including Static Assets

To ensure all necessary assets are part of the final build artifact, the `build` script in `package.json` should be modified to copy the `public` and `.next/static` directories.

{
  "scripts": {
    "build": "next build && cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/"
  }
}

Provisioning the Cloudways Server

Launch a new server using the "Custom App" option. This provides a clean environment ideal for Node.js. Once active, connect via SSH and install Node.js and the PM2 process manager.

# Install Node.js (e.g., version 18.x)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs

# Install the PM2 process manager globally
sudo npm install pm2@latest -g

Architecting Secure Access

Principle of Least Privilege

For CI/CD automation, never use Master credentials. Always create a dedicated, restricted SFTP/SSH user for each application to limit potential security risks.

Credential Security Model

RISKY

Master Credentials

  • ✗ Grants access to ALL applications on the server.
  • ✗ A single key compromise affects the entire server.
  • ✗ Violates principle of least privilege.
SECURE

Dedicated App User

  • Access is restricted to a single application.
  • A key compromise is contained and limited.
  • Follows security best practices.

Storing Credentials in GitHub Secrets

All sensitive credentials must be stored as encrypted secrets in GitHub. They should never be hardcoded into the workflow file.

Secret Name Value Source from Cloudways
CW_HOST Server's Public IP
CW_USER Dedicated deployment username (e.g., `deployer`)
CW_SSH_PRIVATE_KEY Content of the private key file (`deploy_key`)
CW_TARGET_PATH Full path to the application directory

Constructing the GitHub Actions Workflow

The workflow file, `deploy.yml`, defines the entire CI/CD pipeline. It is triggered on a push to the `main` branch, checks out the code, sets up Node.js, builds the application, and finally deploys it.

name: Deploy Next.js to Cloudways

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '18'
          cache: 'npm'

      - name: Install dependencies & Build
        run: |
          npm ci
          npm run build

      - name: Deploy to Cloudways
        uses: easingthemes/ssh-deploy@main
        env:
          SSH_PRIVATE_KEY: ${{ secrets.CW_SSH_PRIVATE_KEY }}
          REMOTE_HOST: ${{ secrets.CW_HOST }}
          REMOTE_USER: ${{ secrets.CW_USER }}
          REMOTE_PORT: ${{ secrets.CW_PORT }}
          SOURCE: ".next/standalone/"
          TARGET: ${{ secrets.CW_TARGET_PATH }}
          SCRIPT_AFTER: |
            echo "Deployment successful. Running post-deployment script..."
            cd ${{ secrets.CW_TARGET_PATH }}
            npm install --production
            # The following line is corrected to prevent syntax errors.
            # It now correctly uses '||' to fall back to 'pm2 start' if 'pm2 reload' fails.
            pm2 reload my-nextjs-app || pm2 start server.js --name my-nextjs-app
            pm2 save
            echo "Deployment complete."

PM2 Command Cheatsheet

PM2 is a powerful process manager for Node.js. Here are the key commands used in a CI/CD context and for debugging.

Command Purpose in Workflow
pm2 reload <name> Performs a zero-downtime reload. The primary command for updates.
pm2 start Starts a new process. Used as a fallback for the initial deployment.
pm2 save Essential for production. Saves the process list to restore on server reboot.
pm2 logs <name> Crucial for debugging. Displays real-time application logs on the server.
pm2 monit Displays a real-time dashboard of CPU and Memory usage.

Interactive Troubleshooting

Deployment pipelines can sometimes fail. Click on a common error below to see the likely causes and solutions.

Error: "Permission denied (publickey)"

Cause: This indicates an SSH authentication failure. The `CW_SSH_PRIVATE_KEY` secret in GitHub may be incorrect, the public key may not be on Cloudways, or server file permissions are wrong.

Solution: Carefully verify the private key is correctly copied into the GitHub secret. Confirm the public key is associated with the correct application user on Cloudways. Test the connection manually from your local machine to isolate the issue.

Error: "Connection timed out"

Cause: The runner cannot connect to the server. This is likely an incorrect server IP (`CW_HOST`) or a firewall rule on Cloudways blocking the GitHub Actions runner's IP.

Solution: Double-check the `CW_HOST` and `CW_PORT` secrets. Check the firewall settings in your Cloudways panel under **Security → Shell Access**.

GitHub Action Fails on `npm install` or `npm run build`

Cause: A common cause is a mismatch between the Node.js version in the GitHub Actions runner and the version your project requires.

Solution: Ensure the `node-version` in the `actions/setup-node` step of your workflow matches your project's requirement (e.g., from `.nvmrc` or `package.json`). Use `npm ci` for more reliable builds in CI environments.

PM2 Process Fails to Start or Enters a Crash Loop

Cause: This is an application-level issue, not a deployment issue. It's typically an error in your code, a missing environment variable on the server, or an incorrect start command.

Solution: SSH into the Cloudways server and use `pm2 logs my-nextjs-app` to view the real-time error logs. The logs will reveal the specific runtime error causing the crash.

HostingXP.com

© 2024 HostingXP.com. All Rights Reserved.

Your trusted partner in cloud deployment solutions.

Exit mobile version