Deploy Express.js on an EC2 instance

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.
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.
<!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.
Confirm the instance is running in the EC2 console and note the public DNS or IP.

Amazon EC2 Connect with PuTTY or
ssh.
PuTTY Verify Node and npm:
node -vandnpm -v. If missing, follow Install Node.js and npm on Ubuntu EC2.
Ubuntu Create a project directory (example under the default Ubuntu user):
Terminalsudo mkdir -p /home/ubuntu/express-website sudo chown ubuntu:ubuntu /home/ubuntu/express-website
Ubuntu If you still need world-writable mode for a quick FileZilla demo only:
Terminalsudo chmod 777 /home/ubuntu/express-websiteSome terminals colour the directory name differently after permissions change. Tighten permissions again after uploads.

Ubuntu Upload
index.js,hello-world.html, and apublicfolder (if any) with FileZilla.
FileZilla Install PM2 globally so the process survives logouts:
Terminalsudo npm i -g pm2See PM2 for documentation.

Ubuntu Install Express in the project folder (not globally):
Terminalcd /home/ubuntu/express-website npm init -y npm install expressThis creates
package.jsonandnode_modulessorequire('express')works. Refer to the Express installation guide for details.Start the app with PM2. Binding to port 80 usually requires elevated privileges:
Terminalcd /home/ubuntu/express-website sudo pm2 start index.js
Ubuntu Ensure the instance security group allows inbound TCP 80 from your test client (or use a high port and update
index.jsfor a non-root setup).You can close PuTTY; PM2 keeps the process running.
Open a browser to
http://<Public IPv4 DNS>orhttp://<Elastic IP>. You should see the root message or/hello-worldHTML depending on the path.
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
Install dependencies with npm install express inside the project directory; do not rely on a global Express install for require('express').
PM2 runs your app after SSH disconnects; pair it with proper firewall / security group rules.
For production, add HTTPS, a reverse proxy, monitoring, and least-privilege file permissions.
Frequently asked questions
Put a CDN in front
Once the app is stable, consider CloudFront or a load balancer for TLS termination, caching, and scaling.
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.
7 people found this page helpful
