Deploy Next.js on EC2

Intermediate
⏱️ 13 min read
📚 Updated: Aug 2025
Next.js / PM2 / Ubuntu

What you’ll learn

Run a Next.js production server on Ubuntu EC2 using next start behind PM2. You scaffold the app locally, upload sources (not node_modules), install and build on the server, then start with a small pm2.config.js.

This is the stock hosting path recommended by Next.js for a single Node process; it avoids a custom Express wrapper unless you need one.

Prerequisites

AWS account and EC2
An AWS account with access to EC2.
Running EC2 instance
An EC2 instance (Ubuntu recommended) reachable over SSH.
Elastic IP (recommended)
An Elastic IP for a stable public address.
FileZilla
FileZilla (or SFTP) for uploads.
PuTTY or SSH
PuTTY or OpenSSH for shell access.
Node.js and npm
Node.js and npm on the instance.

Create the Next.js app locally

  1. Create the app (replace my-nextjs-app if you prefer another name):

    Terminal (local)
    npx create-next-app@latest my-nextjs-app
    Terminal (local)
    cd my-nextjs-app
  2. Start the dev server:

    Terminal (local)
    npm run dev

    Open http://localhost:3000/.

    Default Next.js app on localhost
    Browser
  3. Edit the starter page in your editor:

    • App Router: src/app/page.tsx or app/page.tsx
    • Pages Router: pages/index.tsx or pages/index.js

    Standard Next.js templates do not use a src/App folder; that path in older tutorials was incorrect.

  4. Add pm2.config.js in the project root (next to package.json):

    pm2.config.js
    module.exports = {
      apps: [
        {
          name: 'next-app',
          script: 'npm',
          args: 'start',
          instances: 1,
          exec_mode: 'fork',
          env: {
            NODE_ENV: 'production',
            PORT: 80,
          },
        },
      ],
    };

    PM2 runs npm start, which maps to next start after a production build. When you run PM2 from the project directory, the working directory is correct.

Deploy on EC2

  1. Confirm the instance is running; note public DNS or Elastic IP.

    EC2 instance running with Elastic IP
    Amazon EC2
  2. SSH with PuTTY or ssh.

    PuTTY session to Ubuntu EC2
    PuTTY
  3. Verify Node and npm.

    Node and npm versions on Ubuntu
    Ubuntu
  4. Create a deploy directory and give ownership to your user:

    Terminal (EC2)
    sudo mkdir -p /home/ubuntu/nextjs-website
    sudo chown ubuntu:ubuntu /home/ubuntu/nextjs-website
  5. Optional short-term permission for FileZilla demos only:

    Terminal (EC2)
    sudo chmod 777 /home/ubuntu/nextjs-website
    nextjs-website folder on EC2
    Ubuntu
  6. Upload the project with FileZilla. Exclude .git, node_modules, and usually .next so you rebuild on the server.

    FileZilla uploading Next.js project to EC2
    FileZilla
  7. Install PM2 globally:

    Terminal (EC2)
    sudo npm i -g pm2

    PM2 documentation

    Global PM2 install on Ubuntu
    Ubuntu
  8. Install dependencies and build (from the uploaded project folder):

    Terminal (EC2)
    cd /home/ubuntu/nextjs-website
    npm install
    NODE_ENV=production npm run build

    Prefer fixing file ownership over habitual sudo npm install.

  9. Start with PM2 using your config (port 80 usually requires sudo):

    Terminal (EC2)
    cd /home/ubuntu/nextjs-website
    sudo pm2 start pm2.config.js

    Allow inbound TCP 80 on the security group. Optionally run sudo pm2 save and sudo pm2 startup so the app restarts after reboot.

    PM2 starting Next.js with pm2.config.js
    Ubuntu
  10. Open http://<public-dns-or-ip>/ in a browser.

    Next.js app served from EC2 public address
    Browser

    If it fails, check sudo pm2 logs, confirm npm run build succeeded, and verify the security group.

Key takeaways

1

next build then npm start (via PM2) is the standard production path for a single EC2 host.

2

Install dependencies on the server; skip uploading node_modules from your laptop.

3

Add HTTPS and a reverse proxy when you move beyond a lab setup.

Frequently asked questions

After a successful build, npm start runs the production server (next start) defined by your Next.js version.
PM2 supervises the Node process, survives SSH disconnects, and can integrate with OS startup for reboots.
On small instances, start with one process. Clustering multiple Node workers without load testing can hurt performance more than it helps.

Need a custom HTTP layer?

When you must attach middleware in Node before Next handles the request, use the Express + Next pattern.

Next.js on EC2 with Express →
Did you know?

This flow uses the built-in next start command (via npm start). If you need a custom Node HTTP layer in the same process, see Next.js on EC2 with Express.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

7 people found this page helpful