Deploy Express.js on an EC2 instance

Intermediate
⏱️ 14 min read
📚 Updated: Aug 2025
Node.js / Ubuntu / PM2

What you’ll learn

Deploying an Express.js application on Amazon EC2 is a common way to host Node APIs and small websites. EC2 gives you a Linux server where you install Node, copy your project, and run it under a process manager such as PM2.

This walkthrough uses Ubuntu on EC2, PuTTY for SSH, FileZilla for file transfer, and a minimal two-file Express sample.

Prerequisites

Before you begin, you should have the following in place:

AWS account and EC2
An AWS account with permission to use EC2.
Running EC2 instance
An EC2 instance running Ubuntu (or similar) and reachable over SSH.
Elastic IP (recommended)
An Elastic IP associated with the instance so the public address does not change after stop/start.
FileZilla
FileZilla configured for SFTP to the instance (key-based auth).
PuTTY (Windows) or SSH
PuTTY or another SSH client to run shell commands.
Node.js and npm
Node.js and npm installed on the instance.

Minimal Express.js sample

Create two files locally: index.js (the server) and hello-world.html (a static page). The sample serves static files from a public folder and defines a route that returns HTML from the project root.

index.js
const express = require('express');
const path = require('path');

const app = express();
const port = 80;

app.use(express.static(path.join(__dirname, 'public')));

app.get('/', (req, res) => {
  res.send('Hello, this is the root route!');
});

app.get('/hello-world', (req, res) => {
  res.sendFile(path.join(__dirname, 'hello-world.html'));
});

app.listen(port, () => {
  console.log(`Server is running at http://localhost:${port}`);
});

Place any static assets under public/. The GET /hello-world route serves hello-world.html from the app directory.

hello-world.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
</head>
<body>
    <h1>Hello, World!</h1>
    <p>This page is served by Express.js.</p>
</body>
</html>

Before upload, run npm init -y and npm install express in the same folder on your laptop if you want to test locally; on the server you will run the same commands after upload (see below).

Deploy on EC2

After prerequisites are satisfied, follow these steps on the instance.

  1. Confirm the instance is running in the EC2 console and note the public DNS or IP.

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

    PuTTY SSH session to Ubuntu EC2
    PuTTY
  3. Verify Node and npm: node -v and npm -v. If missing, follow Install Node.js and npm on Ubuntu EC2.

    Terminal showing node and npm versions
    Ubuntu
  4. Create a project directory (example under the default Ubuntu user):

    Terminal
    sudo mkdir -p /home/ubuntu/express-website
    sudo chown ubuntu:ubuntu /home/ubuntu/express-website
    Creating express-website directory on EC2
    Ubuntu
  5. If you still need world-writable mode for a quick FileZilla demo only:

    Terminal
    sudo chmod 777 /home/ubuntu/express-website

    Some terminals colour the directory name differently after permissions change. Tighten permissions again after uploads.

    Folder permissions after chmod on EC2
    Ubuntu
  6. Upload index.js, hello-world.html, and a public folder (if any) with FileZilla.

    FileZilla uploading project files to EC2
    FileZilla
  7. Install PM2 globally so the process survives logouts:

    Terminal
    sudo npm i -g pm2

    See PM2 for documentation.

    npm global install of PM2 on Ubuntu
    Ubuntu
  8. Install Express in the project folder (not globally):

    Terminal
    cd /home/ubuntu/express-website
    npm init -y
    npm install express

    This creates package.json and node_modules so require('express') works. Refer to the Express installation guide for details.

  9. Start the app with PM2. Binding to port 80 usually requires elevated privileges:

    Terminal
    cd /home/ubuntu/express-website
    sudo pm2 start index.js
    PM2 start index.js on EC2
    Ubuntu

    Ensure the instance security group allows inbound TCP 80 from your test client (or use a high port and update index.js for a non-root setup).

    You can close PuTTY; PM2 keeps the process running.

  10. Open a browser to http://<Public IPv4 DNS> or http://<Elastic IP>. You should see the root message or /hello-world HTML depending on the path.

    Browser showing Express app served from EC2
    Browser

    If the page does not load, recheck the security group, PM2 status (sudo pm2 status), and that nothing else is bound to port 80.

Key takeaways

1

Install dependencies with npm install express inside the project directory; do not rely on a global Express install for require('express').

2

PM2 runs your app after SSH disconnects; pair it with proper firewall / security group rules.

3

For production, add HTTPS, a reverse proxy, monitoring, and least-privilege file permissions.

Frequently asked questions

PM2 keeps your Node process running when you disconnect from SSH and can restart the process on failure.
Install Express locally with npm in your project folder. That populates node_modules so require works predictably and versions are pinned per app.
On Linux, ports below 1024 are privileged. Either run the listener with appropriate capabilities, use sudo for the process manager, or listen on a high port and reverse-proxy from Nginx on 80/443.

Put a CDN in front

Once the app is stable, consider CloudFront or a load balancer for TLS termination, caching, and scaling.

AWS CloudFront →
Did you know?

PM2 keeps your Node process running after you disconnect SSH and can restart it on failure. For production, also configure log rotation, reverse proxy (for example Nginx), and HTTPS instead of exposing Node directly on port 80.

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