From Beginner to Pro: Deploying TypeScript Applications with Node.js & PostgreSQL on DigitalOcean
Tags: webdev, deployment, javascript, beginners
Published: 2023-12-31 19:33:00

When I first started with NodeJS there were tons of resources to deploy NodeJs with on [Digital Ocean](https://www.digitalocean.com/) droplet with managed database solutions.

However, I found a gap in resources when it came to hosting both the database and the Node.Js application on the same droplet.

I could have moved ahead with a managed database solution but I didn't want to pay just for the POC:)

Although there is Digital Ocean documentation for hosting PostgreSQL, it didn't work for my needs, possibly due to outdated information.

Let's dive straight into the topic.

This guide could serve as a reference therefore a table of contents is necessary.

**Table of contents** <a name="table-content"></a>

 * [Creating a DigitalOcean Droplet](#create-droplet)
 * [Deploying Node.js](#node-js)
 * [Deploying PostgreSQL](#postgres)
 * [Verifying the Database Connection from Ubuntu Root Folder(optional)](#optional)
 * [Verifying PostgreSQL Connection with Node.js](#verify-connection)
 * [NGINX](#nginx)


### Creating a DigitalOcean Droplet <a name="create-droplet"></a>

The first step is to create your account on [DigitalOcean](https://www.digitalocean.com/).

After signing up or logging in, you will be directed to the droplets page on [DigitalOcean](https://www.digitalocean.com/).

Here, you can create a new droplet by clicking the 'Create' button, as illustrated in the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cxpss4tdpfijvlm6rp4.png)

Next, select your preferred region and data center as shown in the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nay1qn7hfrou08sb516l.PNG)

Choose the OS image as 'Ubuntu' as we are using the Ubuntu server throughout this article as depicted in the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6882qhad2rvqqi0i965b.png)

Choose 'Password' as the authentication method as it helps you start quickly as depicted in the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9c90zlyek4zf7znlswn.png)

Select the Droplet type and CPU options as regular as depicted in the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gxa1quf2pc9k8vlim61.png)

In the final step, set the hostname for your droplet as depicted in the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdwdj2oaev9hwx4bs5u3.png)

Finally. click on the 'Create Droplet' button. Voila!, your droplet is ready.

[Back to top](#table-content)

### Deploying Node.js <a name="node-js"></a>

Log in to your droplet using SSH with the below command.

```
ssh root@your_droplet_ip
```
The above command initiates a secure connection to your Ubuntu server.

Once you have logged in, it's good practice to update your system's package index. Enter the command below

```
sudo apt update && sudo apt upgrade
```
The `sudo apt update` command refreshes the list of available packages and their versions, but it doesn't install or upgrade any packages.

The `sudo apt upgrade` command is used to install the newest versions of all packages currently installed on the system.

The next step is to install Node.js and npm(Node Package Manager) on your Ubuntu server

```
sudo apt install nodejs && sudo apt install npm
```
the above command installs Node.js, the JavaScript runtime, and npm, which is used to manage Node.js packages.


Next, clone your GitHub repository by using the command below.

```
git clone <<YOUR_GITHUB_REPO_LINK>>
```
Replace `<<YOUR_GITHUB_REPO_LINK>>` with the actual link to your GitHub repository.

After cloning, navigate to your project repository by

```
cd into <<YOUR_PROJECT_NAME>>
```
Replace `<<YOUR_PROJECT_NAME>>` with the name of your project directory.

Now, install your project dependencies.

```
npm install
```

Next, install the production process manager for Node.js applications, using the command below

```
npm install pm2 -g
```
PM2 helps in managing and keeping your application online. I'll explain more about the importance of the PM2 package shortly.

As we are talking about the TypeScript. We need to compile the TypeScript code into JavaScript. Hence we need to run the command below.

```
npm run build
```
This process sets up the Node.js server to the DigitalOcean droplet.

[Back to top](#table-content)

### Deploying PostgreSQL <a name="postgres"></a>

Now, let's deploy PostgreSQL on the same droplet.

First, install `postgresql` and `postgresql-contrib` by the command below.

```
sudo apt install postgresql postgresql-contrib
```
`postgresql-contrib` package includes additional utilities and functionality that are not part of the standard PostgreSQL distribution. You can check [here](https://www.postgresql.org/docs/current/contrib.html) for more info. 

Next, switch from the current user context to the `postgres` context by running the command below.

```
sudo -i -u postgres
```
Note: `-i` flag is very important without it certain environment variables, including those set in the login shell's startup scripts will not be reset or executed. In short, we can't create new users or a new database.

P.S. I invested a lot of time at the start without adding `-i` flag.

Once you execute the above command you will see like below.

```
postgres@<<YOUR_SSHNAME>>:~$
```
Now, connect to the PostgreSQL command line interface(CLI) by running the command below.

```
psql
```
Upon successful connection, you'll be presented with the PostgreSQL CLI, as shown in the accompanying image.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1p1j9772orcd2c1nzha.PNG)

> Caution: When setting up your PostgreSQL database, it's crucial to ensure consistency between your local environment and production settings. Specifically, the database name and password you use while creating your PostgreSQL database on the DigitalOcean droplet should match those specified in your Node.js application's configuration files. This alignment is essential for successful database connection and operation, both in development and production environments.

> If there's a mismatch in these credentials, your Node.js application might encounter connection issues, leading to potential downtime or functionality problems. Always double-check these details to ensure a smooth deployment process.

Next, we need to create the user role in the database. Execute the following command, replacing `<<USERNAME_YOU_LIKE>>` with your desired username and `<<PASSWORD_YOU_LIKE>>` with a secure password

```
CREATE USER <<USERNAME_YOU_LIKE>> WITH PASSWORD '<<PASSWORD_YOU_LIKE>>';
```
_Note: It's crucial to enclose the password within single quotes `' '`_

After setting up the user, the next step is to create a database. Use this command, replacing <<DATABASE_NAME>> with your chosen database name and <<USERNAME>> with the username you created in the previous step.

```
CREATE DATABASE <<DATABASE_NAME>> OWNER '<<USERNAME>>';
```
_Note:  Ensure that `<<USERNAME>>` matches the username you've just created._

To verify your database has been created successfully, run the command below.

```
\l
```
You should be able to see your new database on the list.


To quit the PostgreSQL command line interface. run the command below.

```
\q
```
Then, to leave the Postgres user context and return to the Ubuntu root folder, type

```
exit
```
And there you have it! We've successfully set up a user and a database in PostgreSQL on our Ubuntu server.

Uff.. It's been quite a journey, but we're making great progress.

[Back to top](#table-content)

### Verifying the Database Connection from Ubuntu Root Folder(optional)  <a name="optional"></a>

Now let's verify if we can connect to the newly created database from the Ubuntu server.

```
sudo adduser <<USERNAME>>
```
_Note: This command will prompt you to create a new password for the system user and fill in some additional details. You can opt to keep these details at their default values._

To open the PostgreSQL shell as the `<<USERNAME>>`, run the below command.

```
sudo -u <<USERNAME>> psql -d <<DATABASE_NAME>>
```

Once logged in, check the connection details with

```
\conninfo
```
If everything is set up correctly, you will see a message similar to:
`You are connected to database <<DATABASE_NAME>> as user <<USERNAME>> via socket in "/var/run/postgresql" at port "5432".`

This confirmation indicates a successful connection to your PostgreSQL database from the Ubuntu server.

[Back to top](#table-content)

### Verifying PostgreSQL Connection with Node.js ### <a name="verify-connection"></a>

Now we'll verify the database that we set up is successfully connected to the Node.js server.

Navigate to your project repository by

```
cd into <<YOUR_PROJECT_NAME>>
```

Once in your project directory, start your Node.js application to check the database connection

```
npm start 
```

If the database connection is properly configured in your application, you should not encounter any error messages related to the database. Successful execution without errors indicates that your Node.js server is correctly connected to your PostgreSQL database.

Now, exit the project by pressing `ctrl+c` and navigate to Ubuntu root server by running the command below.

```
cd
```

[Back to top](#table-content)

### NGINX <a name="nginx"></a>

Now we have come to the last bit, exposing the project to the internet.

We will use the internet's favorite(also my personal favorite) [NGINX](https://www.nginx.com/)

You could ask me why NGINX.

Here are my top 3 reasons.
* Nginx efficiently handles static files and a large number of simultaneous connections, offloading this work from Node.js.
* Nginx acts as a security layer, shielding your Node.js application from direct exposure to the internet.
* Nginx can manage SSL/TLS encryption, simplifying the setup of HTTPS for your Node.js app.

With that said let's start.

Install NGINX by running the command below.

```
sudo apt install nginx
```

Next, we'll create a configuration file for your project in the /etc/nginx/sites-available/ directory. This file is crucial for directing internet traffic to your Node.js application

```
sudo nano /etc/nginx/sites-available/<<YOUR_PROJECT_NAME>>
```
You will see the empty editor like the image below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/584fisp5ijuts9gmbgx3.PNG)

Now let us add the below code.

```
server {
    listen 80;
    server_name <<your_domain_or_IP>>;

    location / {
        proxy_pass http://localhost:YOUR_NODE_JS_PORT;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
```
Replace <<your_domain_or_IP>> with your domain name or IP address and YOUR_NODE_JS_PORT with the port number where your Node.js app is running.

This configuration does the following

* Listens on port 80, the default port for HTTP.
* `server_name` specifies the domain name or IP address NGINX responds to.
* `proxy_pass` directs requests to your Node.js app.
* Additional `proxy_set_header` settings ensure proper handling of connections and upgrades (important for WebSocket support).

After adding the code save the file by pressing `Ctrl+O`, then press `Enter`, and exit the editor with `Ctrl+X`.


Next test the NGINX configuration.

```
sudo nginx -t
```

If the test is successful, create a symbolic link to enable your site configuration

```
sudo ln -s /etc/nginx/sites-available/<<YOUR_PROJECT_NAME>>  
 /etc/nginx/sites-enabled/
```

Restart the NGINX server to apply the changes

```
sudo systemctl restart nginx
```
Navigate to the project root by running the command below.

```
cd <<PROJECT_NAME>>
```

Finally, start your Node.js server permanently with PM2:

```
pm2 start dist/index.js
```
PM2 not only helps keep your Node.js application running efficiently but also provides a suite of features beneficial for application monitoring, logging, and performance optimization, especially in a production environment.

[Back to top](#table-content)


If you're interested in further streamlining your workflow, I have good news for you! In my next post, I delve into the intricacies of fully automating this deployment process. Check out my upcoming [post](https://dev.to/vijeth-simha/nodejs-with-typescript-the-ultimate-guide-to-automated-deployment-on-digitalocean-using-github-actions-4i74)

###Finally###


As you embark on this journey of deploying your Node.js application with PostgreSQL on DigitalOcean and configuring NGINX, feel free to use my [project](https://github.com/vijeth-simha/education-documents-organizer) as a practical example to follow along with the steps outlined above.

Should you encounter any challenges or have questions during the process, please don't hesitate to leave a comment below.

Feel free to reach out to me on

* [Twitter](https://twitter.com/vijeth_simha)
* [Linkedin](https://www.linkedin.com/in/vijeth-simha/)
* [Github](https://github.com/vijeth-simha)

[Back to top](#table-content)