back to top
More

    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 NameValue Source from Cloudways
    CW_HOSTServer's Public IP
    CW_USERDedicated deployment username (e.g., `deployer`)
    CW_SSH_PRIVATE_KEYContent of the private key file (`deploy_key`)
    CW_TARGET_PATHFull 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.

    CommandPurpose in Workflow
    pm2 reload <name>Performs a zero-downtime reload. The primary command for updates.
    pm2 startStarts a new process. Used as a fallback for the initial deployment.
    pm2 saveEssential 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 monitDisplays 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.