Login to AWS and navigate to EC2. Create a new instance:

New EC2 Instance

 

Select AWS Linux 2 AMI (Free Tier):

New EC2 Instance

New EC2 Instance

 

Create a new key pair and download it:

New EC2 Instance

 

Move the private key file to ~/.ssh:

New EC2 Instance

 

Change the permissions on the private key file to 700:

chmod 700 ~/.ssh/demo.pem

 

SSH in from Terminal:

ssh -i ~/.ssh/demo.pem ec2-user@ec2-34-201-151-8.compute-1.amazonaws.com

New EC2 Instance

 

Install Node:

sudo yum install -y gcc-c++ make
curl -sL https://rpm.nodesource.com/setup_12.x | sudo -E bash -
sudo yum install -y nodejs

Make a directory and package.json file:

mkdir node-api-postgres
cd node-api-postgres
vim package.json

And paste in:

{
  "name": "node-api-postgres",
  "version": "1.0.0",
  "description": "RESTful API with Node.js, Express, and PostgreSQL",
  "main": "index.js",
  "license": "MIT"
}

Install Postgres

amazon-linux-extras install postgresql10 vim epel -y
sudo yum install -y postgresql-server postgresql-devel

Init a new Postgres database

sudo /usr/bin/postgresql-setup --initdb

Start the Postgres services

sudo systemctl enable postgresql
sudo systemctl start postgresql

Create your user and database in Postgres

sudo -u postgres createuser -s ec2-user
sudo -u postgres createdb ec2-user

Create a database user for Postgres

psql
CREATE ROLE me WITH LOGIN PASSWORD 'secure';
ALTER ROLE me CREATEDB;

Adjust the security type for logins Find the pg_hba.conf file.

sudo vim /var/lib/pgsql/data/pg_hba.conf

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            ident
# IPv6 local connections:
host    all             all             ::1/128                 ident

Adjust the method to md5

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
# IPv6 local connections:
host    all             all             ::1/128                 md5

Restart Postgres

sudo systemctl restart postgresql

Login to Postgres with new user

psql -d postgres -U me

postgres=> CREATE DATABASE api;
CREATE DATABASE

postgres=> \c api
You are now connected to database "api" as user "me".

postgres=> CREATE TABLE users (
  ID SERIAL PRIMARY KEY,
  name VARCHAR(30),
  email VARCHAR(30)
);
CREATE TABLE

postgres=> INSERT INTO users (name, email)
  VALUES ('Jerry', 'jerry@example.com'), ('George', 'george@example.com');

postgres=> \q

Install Express

npm i express pg

Create a queries.js file

sudo vim queries.js

const Pool = require('pg').Pool
const pool = new Pool({
  user: 'me',
  host: 'localhost',
  database: 'api',
  password: 'secure',
  port: 5432,
})

const getUsers = (request, response) => {
  pool.query('SELECT * FROM users ORDER BY id ASC', (error, results) => {
    if (error) {
      throw error
    }
    response.status(200).json(results.rows)
  })
}

const getUserById = (request, response) => {
  const id = parseInt(request.params.id)

  pool.query('SELECT * FROM users WHERE id = $1', [id], (error, results) => {
    if (error) {
      throw error
    }
    response.status(200).json(results.rows)
  })
}

const createUser = (request, response) => {
  const { name, email } = request.body

  pool.query('INSERT INTO users (name, email) VALUES ($1, $2)', [name, email], (error, results) => {
    if (error) {
      throw error
    }
    response.status(201).send(`User added with ID: ${result.insertId}`)
  })
}

const updateUser = (request, response) => {
  const id = parseInt(request.params.id)
  const { name, email } = request.body

  pool.query(
    'UPDATE users SET name = $1, email = $2 WHERE id = $3',
    [name, email, id],
    (error, results) => {
      if (error) {
        throw error
      }
      response.status(200).send(`User modified with ID: ${id}`)
    }
  )
}

const deleteUser = (request, response) => {
  const id = parseInt(request.params.id)

  pool.query('DELETE FROM users WHERE id = $1', [id], (error, results) => {
    if (error) {
      throw error
    }
    response.status(200).send(`User deleted with ID: ${id}`)
  })
}

module.exports = {
  getUsers,
  getUserById,
  createUser,
  updateUser,
  deleteUser,
}

Create an index.js file

sudo vim index.js

const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const db = require('./queries')
const port = 3000

app.use(bodyParser.json())
app.use(
  bodyParser.urlencoded({
    extended: true,
  })
)

app.get('/', (request, response) => {
  response.json({ info: 'Node.js, Express, and Postgres API' })
})

app.get('/users', db.getUsers)
app.get('/users/:id', db.getUserById)
app.post('/users', db.createUser)
app.put('/users/:id', db.updateUser)
app.delete('/users/:id', db.deleteUser)

app.listen(port, () => {
  console.log(`App running on port ${port}.`)
})

Redirect 80 to port 3000:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

Also redirect whenever the server reboots:

sudo vim /etc/rc.local and add a new line to that file:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

Open port 80 to yourself in AWS:

New EC2 Instance

Start the application:

node index.js

New EC2 Instance New EC2 Instance

 

We now have a functioning REST API with Express, Node and Postgres.

MIT License.