<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Vijeth Simha</title>
    <description>The latest articles on Forem by Vijeth Simha (@vijeth-simha).</description>
    <link>https://forem.com/vijeth-simha</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F514537%2Fc8ce4ef9-5bea-4ff1-9ca7-f5d17acdc619.jpg</url>
      <title>Forem: Vijeth Simha</title>
      <link>https://forem.com/vijeth-simha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/vijeth-simha"/>
    <language>en</language>
    <item>
      <title>Serving Dynamic Images in Node.js with Typescript : A Simple Guide</title>
      <dc:creator>Vijeth Simha</dc:creator>
      <pubDate>Thu, 01 Feb 2024 10:33:35 +0000</pubDate>
      <link>https://forem.com/vijeth-simha/serving-dynamic-images-in-nodejs-with-typescript-a-simple-guide-11ce</link>
      <guid>https://forem.com/vijeth-simha/serving-dynamic-images-in-nodejs-with-typescript-a-simple-guide-11ce</guid>
      <description>&lt;p&gt;While working on a Node.js project with TypeScript, I encountered a fascinating challenge regarding serving static and dynamic image assets. Everything functioned flawlessly in the development environment, with static and dynamic assets residing in the public folder. However, upon deploying to production, an unexpected issue arose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Issue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The development setup seamlessly served static and dynamic images from the public folder. The complication emerged during the deployment process to the production environment. Here's what happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;As part of the deployment, the TypeScript codebase was transpiled to JavaScript. This step also involved copying all static assets from the public folder to a designated production folder.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The static images, being part of the pre-defined assets, were successfully transferred to the production environment. They continued to load without any issues, just as they did in the development environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The real problem surfaced with dynamic assets. Despite the initial setup working in development, the dynamic images failed to display in production. This was perplexing, as the deployment process didn't inherently account for assets created post-build — those dynamic images generated on the fly and intended to be served from the same public folder.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The crux of the issue lies in the deployment strategy for the TypeScript application. The build process, designed to prepare the production application, inadvertently overlooked the nature of dynamically generated assets. These assets, unlike their static counterparts, weren't part of the initial asset copying to the production folder. Consequently, when new dynamic images were created, they were not accessible in the structured production environment, leading to the observed issue of missing images.&lt;/p&gt;

&lt;p&gt;The above problem could have been easily addressed by saving the images in external storage like S3 or Firebase storage but I wanted to solve it in the existing architecture itself. &lt;/p&gt;

&lt;p&gt;So this is how is solved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To address the challenge of serving dynamic assets in production, I implemented a strategy that ensures both static and dynamic images are accessible, regardless of the environment. Here's how I tackled the issue:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The first step was recognizing that the deployment process did not accommodate dynamically generated images. While static assets were copied to the production directory during the build process, dynamic assets created at runtime were not being served from the expected directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To ensure dynamic assets were accessible, I decided to serve them from a directory outside the build output (dist). This approach prevents dynamic assets from being overwritten or missed during the build process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I configured the Express server to serve static files from two directories: one for the pre-existing static assets and another for dynamic assets. Here's an example of how I set it up in Express:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import express from 'express';
import path from 'path';

const app = express();

var env = process.env.NODE_ENV || 'development';

if(env === "development") {
  // In development, serve static files from 'public'
  app.use('/static', express.static(path.join(__dirname, "public")));
} else {
  // In production, serve dynamic files from 'dynamic', located outside of 'dist'
  app.use('/dynamic', express.static(path.join(__dirname, '..', "dynamic")));
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key Aspects of the Solution:&lt;/p&gt;

&lt;p&gt;Environment-Aware Configuration: By leveraging the NODE_ENV environment variable, the server dynamically adjusts its behavior based on the current environment—development or production. This ensures that the correct set of assets is served in each context.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In the development environment, the server serves static assets from the public directory. This setup is straightforward and aligns with the typical Express.js configuration for handling static files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I needed a way to access the dynamic directory, which resides outside &lt;code&gt;dist&lt;/code&gt;. By employing path.join(__dirname, '..', 'dynamic'), I effectively directed the server to step out of the dist directory and into the dynamic directory to serve the runtime-generated assets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Directory Navigation with '..': The '..' in the path plays a crucial role, instructing the server to navigate up one directory level from its current location (dist) and then into the dynamic directory. This ensures that dynamic assets generated post-deployment are accessible, without being constrained by the build output directory structure.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Finally
&lt;/h3&gt;

&lt;p&gt;As you embark on this journey, feel free to use my &lt;a href="https://github.com/vijeth-simha/education-documents-organizer"&gt;project&lt;/a&gt; as a practical example to follow along with the steps outlined above.&lt;/p&gt;

&lt;p&gt;Should you encounter any challenges or have questions during the process, please don't hesitate to leave a comment below.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/vijeth_simha"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/vijeth-simha/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vijeth-simha"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>The Essential Guide to Domain Setup and SSL Security</title>
      <dc:creator>Vijeth Simha</dc:creator>
      <pubDate>Fri, 19 Jan 2024 08:59:42 +0000</pubDate>
      <link>https://forem.com/vijeth-simha/the-essential-guide-to-domain-setup-and-ssl-security-1m27</link>
      <guid>https://forem.com/vijeth-simha/the-essential-guide-to-domain-setup-and-ssl-security-1m27</guid>
      <description>&lt;p&gt;Thank you for taking the time to read this post.&lt;/p&gt;

&lt;p&gt;In my last &lt;a href="https://dev.to/vijeth-simha/nodejs-with-typescript-the-ultimate-guide-to-automated-deployment-on-digitalocean-using-github-actions-4i74"&gt;post&lt;/a&gt;,  I discussed automating the deployment process using GitHub CI/CD. Building on that topic, this post will delve into how to connect your domain and attach SSL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before proceeding, I highly recommend checking the previous articles in the deployment series, as this post is a continuation of the previous two.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With that said, let's dive in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of contents&lt;/strong&gt; &lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Attach Domain&lt;/li&gt;
&lt;li&gt;Attach SSL&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Attach Domain &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The first step is to edit the existing Nginx configuration file. You can do this by opening the file in a text editor, such as nano, with the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/nginx/sites-available/&amp;lt;&amp;lt;YOUR_PROJECT_NAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: For the following step to work, you must point your domain to the DigitalOcean IP address, or else the domain connection won't work.&lt;/p&gt;

&lt;p&gt;Add your domain to the configuration as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;
    server_name &amp;lt;&amp;lt;your_domain_name&amp;gt;&amp;gt;;

    location / {
        proxy_pass http://localhost:&amp;lt;&amp;lt;YOUR_NODE_JS_PORT&amp;gt;&amp;gt;;
        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;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;&amp;lt;your_domain_name&amp;gt;&amp;gt;&lt;/code&gt; with your domain name  and &lt;code&gt;&amp;lt;&amp;lt;YOUR_NODE_JS_PORT&amp;gt;&amp;gt;&lt;/code&gt; with the port number where your Node.js app is running.&lt;/p&gt;

&lt;p&gt;You can test the configuration by running below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you encounter an error, reopen the server block file and carefully review it for any typos or missing characters. After ensuring that your configuration file's syntax is correct, you should reload Nginx to apply the new configuration by running below command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Attach SSL &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The first step in using Let’s Encrypt to obtain an SSL certificate is to install the Certbot software on your server. Execute the following command to do so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install certbot python3-certbot-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a firewall enabled, you'll need to adjust its settings to allow HTTPS traffic. Fortunately, Nginx registers several profiles with UFW (Uncomplicated Firewall) upon installation. You can check the current firewall status with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To allow HTTPS traffic, enable the 'Nginx Full' profile, which covers both HTTP and HTTPS. This step makes the separate 'Nginx HTTP' profile redundant, so you can remove it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After these changes, verify the updated firewall status by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The status should now show as 'active', similar to the example in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivv7gud64r6g4io34o6v.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivv7gud64r6g4io34o6v.PNG" alt="Image description" width="531" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Certbot offers several methods to obtain SSL certificates, facilitated by its plugins. The Nginx plugin, in particular, is designed to automatically reconfigure Nginx and reload its configuration as needed. To utilize this plugin, enter the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo certbot --nginx -d &amp;lt;&amp;lt;your_domain_name&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure you replace &lt;code&gt;&amp;lt;&amp;lt;your_domain_name&amp;gt;&amp;gt;&lt;/code&gt; with your actual domain name.&lt;/p&gt;

&lt;p&gt;When you run this command, Certbot will prompt you for several pieces of information:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Email Address: For important notifications related to your SSL certificate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terms and Conditions Acceptance: You'll need to agree to the Let's Encrypt terms of service.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redirection Details: Certbot will ask whether you want to redirect HTTP traffic to HTTPS, effectively enforcing a secure connection.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s Encrypt's certificates have a validity period of ninety days. This relatively short duration is intentional, aimed at encouraging users to automate the process of certificate renewal.&lt;/p&gt;

&lt;p&gt;Fortunately, the &lt;code&gt;certbot&lt;/code&gt; package, which we've already installed, simplifies this process. It adds a &lt;code&gt;systemd&lt;/code&gt; timer to your system, configured to run twice daily. This timer automatically renews any certificate that's within thirty days of expiration.&lt;/p&gt;

&lt;p&gt;You can query the status of the timer with &lt;code&gt;systemctl&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl status certbot.timer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will get output as the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1fpca9b00vnia6p4qj1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff1fpca9b00vnia6p4qj1.PNG" alt="Image description" width="702" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To test the renewal process without making any actual changes, you can perform a dry run with &lt;code&gt;certbot&lt;/code&gt; using the following command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo certbot renew --dry-run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the dry run completes without any errors, you're all set. Certbot will handle the renewal of your certificates and will ensure that Nginx is reloaded to apply the changes. &lt;/p&gt;

&lt;p&gt;In the event that the automated renewal process encounters an issue, Let’s Encrypt will send a notification to the email address you provided. This notification will serve as a warning, alerting you when your certificate is nearing its expiration date.&lt;/p&gt;

&lt;p&gt;That's it for this guide.&lt;/p&gt;

&lt;p&gt;Thank you so much for reading through to the end!.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Finally
&lt;/h3&gt;

&lt;p&gt;As you embark on this journey, feel free to use my &lt;a href="https://github.com/vijeth-simha/education-documents-organizer"&gt;project&lt;/a&gt; as a practical example to follow along with the steps outlined above.&lt;/p&gt;

&lt;p&gt;Should you encounter any challenges or have questions during the process, please don't hesitate to leave a comment below.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/vijeth_simha"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/vijeth-simha/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vijeth-simha"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to top&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Node.js with TypeScript: The Ultimate Guide to Automated Deployment on DigitalOcean Using GitHub Actions</title>
      <dc:creator>Vijeth Simha</dc:creator>
      <pubDate>Fri, 12 Jan 2024 20:12:28 +0000</pubDate>
      <link>https://forem.com/vijeth-simha/nodejs-with-typescript-the-ultimate-guide-to-automated-deployment-on-digitalocean-using-github-actions-4i74</link>
      <guid>https://forem.com/vijeth-simha/nodejs-with-typescript-the-ultimate-guide-to-automated-deployment-on-digitalocean-using-github-actions-4i74</guid>
      <description>&lt;p&gt;Thank you for taking the time to read this post.&lt;/p&gt;

&lt;p&gt;In my last &lt;a href="https://dev.to/vijeth-simha/from-beginner-to-pro-deploying-typescript-applications-with-nodejs-postgresql-on-digitalocean-91k"&gt;post&lt;/a&gt;, I discussed deploying code to DigitalOcean. Building on that, this post delves into automating the deployment process using GitHub Actions. &lt;/p&gt;

&lt;p&gt;We'll explore the steps and benefits of this method, ensuring a seamless and efficient deployment experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of contents&lt;/strong&gt; &lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Github secret keys&lt;/li&gt;
&lt;li&gt;Automate the deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create Github secret keys &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To begin, we need to generate secret keys that will securely store our &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt; credentials.&lt;/p&gt;

&lt;p&gt;First, log in to your GitHub account. Once logged in, navigate to your repository and look for the settings icon. This is typically found in the upper right corner, represented by a gear symbol. Click on this icon to access your repository settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NO-RlOZH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgs4h8s5wbflftenwsfw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NO-RlOZH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cgs4h8s5wbflftenwsfw.PNG" alt="Image description" width="800" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, navigate to the 'Security' section. Here, you'll find the 'Secrets and Variables' option. Click on this to proceed. Next, select 'Actions' to access the area where you can manage your secret keys. This is illustrated in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2j8CtR9Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/luaoa8vu1eax97itn1g1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2j8CtR9Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/luaoa8vu1eax97itn1g1.png" alt="Image description" width="330" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's essential to create secrets for &lt;code&gt;SSH_PASSWORD&lt;/code&gt;, &lt;code&gt;SSH_USER&lt;/code&gt;, and &lt;code&gt;DROPLET_IP&lt;/code&gt;. These represent the SSH login password, username, and IP address of your DigitalOcean droplet, respectively.&lt;/p&gt;

&lt;p&gt;To add a new secret, click on the 'New Repository Secret' button. This can be found at the top right of the 'Secrets and Variables' section, as shown in the first image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_DZd72Xd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jldkignq6w7i9a9fi1b4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_DZd72Xd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jldkignq6w7i9a9fi1b4.png" alt="Image description" width="773" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you'll need to enter the necessary credentials. In the fields provided, add the respective values for each secret key. This step is illustrated in the second image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yPJOQ2nY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbx1er0hp4koq43b0obz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yPJOQ2nY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbx1er0hp4koq43b0obz.png" alt="Image description" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Automate the deployment &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To begin automating deployment, start by creating a &lt;code&gt;.github/workflows&lt;/code&gt; folder in your project's root directory.&lt;/p&gt;

&lt;p&gt;Next, create a YAML file within this folder. You can name it as you prefer, such as &lt;code&gt;deployment.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Follow the below steps.&lt;/p&gt;

&lt;p&gt;The first step in configuring the pipeline is to name it, as shown below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CI/CD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to trigger the CI/CD Pipeline by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;on:
  push:
    branches:
      - main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;on: push&lt;/code&gt; specifies that the instructions will execute whenever code is pushed to the repository.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;branches: - main&lt;/code&gt; indicates that these actions will trigger only for pushes to the 'main' branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next step is to define the Job Definition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build-and-deploy:&lt;/code&gt; This is the name of the job. It's a set of tasks that will be executed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;runs-on: ubuntu-latest:&lt;/code&gt;  This line ensures the job runs on the latest Ubuntu version, a widely-used operating system for server environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following this, we define the individual steps within the job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Deploy
        run: |
          sshpass -p ${{ secrets.SSH_PASSWORD }} ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.DROPLET_IP }} &amp;lt;&amp;lt; EOF
            cd &amp;lt;&amp;lt;YOUR_CODE_REPOSITORY_NAME&amp;gt;&amp;gt;/
            git pull origin main
            npm install
            npm run build
            pm2 reload all
          EOF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above section involves four steps.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Checkout Code&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;uses: actions/checkout@v2:&lt;/code&gt; This is a GitHub Action to check out the code from the repository, making it available to subsequent steps in the job.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install Dependencies&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;run: npm install:&lt;/code&gt; This command installs all the dependencies required for the project, as defined in a file usually called package.json.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Build&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;run: npm run build:&lt;/code&gt; This command builds the project. Depending on how it's set up, this might involve converting TypeScript code to JavaScript code, minifying files, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Deploy&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a multi-line script that automates the deployment of the code to a remote server.&lt;/li&gt;
&lt;li&gt;It uses &lt;code&gt;sshpass&lt;/code&gt; to log in to the remote server using SSH without needing to enter a password manually. The password and other details are stored in GitHub secrets for security.&lt;/li&gt;
&lt;li&gt;The script then changes the directory to &lt;code&gt;&amp;lt;&amp;lt;YOUR_CODE_REPOSITORY_NAME&amp;gt;&amp;gt;&lt;/code&gt;, pulls the latest changes from the master branch, installs any new dependencies, builds the project on the server, and finally, reloads all processes managed by pm2, which is a process manager for Node.js applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're already familiar with the process or prefer to skip the detailed explanations, you can simply copy the code snippet provided below and paste it into your deployment.yml file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: CI/CD

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Deploy
        run: |
          sshpass -p ${{ secrets.SSH_PASSWORD }} ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.DROPLET_IP }} &amp;lt;&amp;lt; EOF
            cd &amp;lt;&amp;lt;YOUR_CODE_REPOSITORY_NAME&amp;gt;&amp;gt;/
            git pull origin main
            npm install
            npm run build
            pm2 reload all
          EOF

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is it now push the code to your main branch.&lt;/p&gt;

&lt;p&gt;This completes the setup! Now, go ahead and push your code to the main branch. If everything is configured correctly, you should see a green checkmark indicating a successful deployment, as illustrated in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mle8X7FK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djio91qw1oykpnrpngb4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mle8X7FK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/djio91qw1oykpnrpngb4.PNG" alt="Image description" width="107" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This signifies that your automated deployment pipeline is functioning as expected.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Finally
&lt;/h3&gt;

&lt;p&gt;As you embark on this journey to automate your deployment to DigitalOcean feel free to use my &lt;a href="https://github.com/vijeth-simha/education-documents-organizer"&gt;project&lt;/a&gt; as a practical example to follow along with the steps outlined above.&lt;/p&gt;

&lt;p&gt;Should you encounter any challenges or have questions during the process, please don't hesitate to leave a comment below.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/vijeth_simha"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/vijeth-simha/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vijeth-simha"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to top&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>devops</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>From Beginner to Pro: Deploying TypeScript Applications with Node.js &amp; PostgreSQL on DigitalOcean</title>
      <dc:creator>Vijeth Simha</dc:creator>
      <pubDate>Sun, 31 Dec 2023 19:33:00 +0000</pubDate>
      <link>https://forem.com/vijeth-simha/from-beginner-to-pro-deploying-typescript-applications-with-nodejs-postgresql-on-digitalocean-91k</link>
      <guid>https://forem.com/vijeth-simha/from-beginner-to-pro-deploying-typescript-applications-with-nodejs-postgresql-on-digitalocean-91k</guid>
      <description>&lt;p&gt;When I first started with NodeJS there were tons of resources to deploy NodeJs with on &lt;a href="https://www.digitalocean.com/"&gt;Digital Ocean&lt;/a&gt; droplet with managed database solutions.&lt;/p&gt;

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

&lt;p&gt;I could have moved ahead with a managed database solution but I didn't want to pay just for the POC:)&lt;/p&gt;

&lt;p&gt;Although there is Digital Ocean documentation for hosting PostgreSQL, it didn't work for my needs, possibly due to outdated information.&lt;/p&gt;

&lt;p&gt;Let's dive straight into the topic.&lt;/p&gt;

&lt;p&gt;This guide could serve as a reference therefore a table of contents is necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Table of contents&lt;/strong&gt; &lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a DigitalOcean Droplet&lt;/li&gt;
&lt;li&gt;Deploying Node.js&lt;/li&gt;
&lt;li&gt;Deploying PostgreSQL&lt;/li&gt;
&lt;li&gt;Verifying the Database Connection from Ubuntu Root Folder(optional)&lt;/li&gt;
&lt;li&gt;Verifying PostgreSQL Connection with Node.js&lt;/li&gt;
&lt;li&gt;NGINX&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creating a DigitalOcean Droplet &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The first step is to create your account on &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After signing up or logging in, you will be directed to the droplets page on &lt;a href="https://www.digitalocean.com/"&gt;DigitalOcean&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here, you can create a new droplet by clicking the 'Create' button, as illustrated in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E3gRH5t9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cxpss4tdpfijvlm6rp4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E3gRH5t9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4cxpss4tdpfijvlm6rp4.png" alt="Image description" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select your preferred region and data center as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--48KV2U-s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nay1qn7hfrou08sb516l.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--48KV2U-s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nay1qn7hfrou08sb516l.PNG" alt="Image description" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose the OS image as 'Ubuntu' as we are using the Ubuntu server throughout this article as depicted in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jYR0y2bR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6882qhad2rvqqi0i965b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jYR0y2bR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6882qhad2rvqqi0i965b.png" alt="Image description" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose 'Password' as the authentication method as it helps you start quickly as depicted in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x4xssgHU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9c90zlyek4zf7znlswn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x4xssgHU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q9c90zlyek4zf7znlswn.png" alt="Image description" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the Droplet type and CPU options as regular as depicted in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aBpX-uQ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gxa1quf2pc9k8vlim61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aBpX-uQ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gxa1quf2pc9k8vlim61.png" alt="Image description" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the final step, set the hostname for your droplet as depicted in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YiMyN9hj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdwdj2oaev9hwx4bs5u3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YiMyN9hj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdwdj2oaev9hwx4bs5u3.png" alt="Image description" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally. click on the 'Create Droplet' button. Voila!, your droplet is ready.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying Node.js &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Log in to your droplet using SSH with the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh root@your_droplet_ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command initiates a secure connection to your Ubuntu server.&lt;/p&gt;

&lt;p&gt;Once you have logged in, it's good practice to update your system's package index. Enter the command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;sudo apt update&lt;/code&gt; command refreshes the list of available packages and their versions, but it doesn't install or upgrade any packages.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sudo apt upgrade&lt;/code&gt; command is used to install the newest versions of all packages currently installed on the system.&lt;/p&gt;

&lt;p&gt;The next step is to install Node.js and npm(Node Package Manager) on your Ubuntu server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nodejs &amp;amp;&amp;amp; sudo apt install npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the above command installs Node.js, the JavaScript runtime, and npm, which is used to manage Node.js packages.&lt;/p&gt;

&lt;p&gt;Next, clone your GitHub repository by using the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone &amp;lt;&amp;lt;YOUR_GITHUB_REPO_LINK&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;&amp;lt;YOUR_GITHUB_REPO_LINK&amp;gt;&amp;gt;&lt;/code&gt; with the actual link to your GitHub repository.&lt;/p&gt;

&lt;p&gt;After cloning, navigate to your project repository by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd into &amp;lt;&amp;lt;YOUR_PROJECT_NAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;&amp;lt;&amp;lt;YOUR_PROJECT_NAME&amp;gt;&amp;gt;&lt;/code&gt; with the name of your project directory.&lt;/p&gt;

&lt;p&gt;Now, install your project dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, install the production process manager for Node.js applications, using the command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install pm2 -g
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PM2 helps in managing and keeping your application online. I'll explain more about the importance of the PM2 package shortly.&lt;/p&gt;

&lt;p&gt;As we are talking about the TypeScript. We need to compile the TypeScript code into JavaScript. Hence we need to run the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This process sets up the Node.js server to the DigitalOcean droplet.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying PostgreSQL &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now, let's deploy PostgreSQL on the same droplet.&lt;/p&gt;

&lt;p&gt;First, install &lt;code&gt;postgresql&lt;/code&gt; and &lt;code&gt;postgresql-contrib&lt;/code&gt; by the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install postgresql postgresql-contrib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;postgresql-contrib&lt;/code&gt; package includes additional utilities and functionality that are not part of the standard PostgreSQL distribution. You can check &lt;a href="https://www.postgresql.org/docs/current/contrib.html"&gt;here&lt;/a&gt; for more info. &lt;/p&gt;

&lt;p&gt;Next, switch from the current user context to the &lt;code&gt;postgres&lt;/code&gt; context by running the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo -i -u postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: &lt;code&gt;-i&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;P.S. I invested a lot of time at the start without adding &lt;code&gt;-i&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;Once you execute the above command you will see like below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postgres@&amp;lt;&amp;lt;YOUR_SSHNAME&amp;gt;&amp;gt;:~$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, connect to the PostgreSQL command line interface(CLI) by running the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;psql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon successful connection, you'll be presented with the PostgreSQL CLI, as shown in the accompanying image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--x5aQ8MYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1p1j9772orcd2c1nzha.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--x5aQ8MYf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1p1j9772orcd2c1nzha.PNG" alt="Image description" width="349" height="64"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, we need to create the user role in the database. Execute the following command, replacing &lt;code&gt;&amp;lt;&amp;lt;USERNAME_YOU_LIKE&amp;gt;&amp;gt;&lt;/code&gt; with your desired username and &lt;code&gt;&amp;lt;&amp;lt;PASSWORD_YOU_LIKE&amp;gt;&amp;gt;&lt;/code&gt; with a secure password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER &amp;lt;&amp;lt;USERNAME_YOU_LIKE&amp;gt;&amp;gt; WITH PASSWORD '&amp;lt;&amp;lt;PASSWORD_YOU_LIKE&amp;gt;&amp;gt;';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: It's crucial to enclose the password within single quotes &lt;code&gt;' '&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After setting up the user, the next step is to create a database. Use this command, replacing &amp;lt;&amp;gt; with your chosen database name and &amp;lt;&amp;gt; with the username you created in the previous step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE &amp;lt;&amp;lt;DATABASE_NAME&amp;gt;&amp;gt; OWNER '&amp;lt;&amp;lt;USERNAME&amp;gt;&amp;gt;';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note:  Ensure that &lt;code&gt;&amp;lt;&amp;lt;USERNAME&amp;gt;&amp;gt;&lt;/code&gt; matches the username you've just created.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To verify your database has been created successfully, run the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\l
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be able to see your new database on the list.&lt;/p&gt;

&lt;p&gt;To quit the PostgreSQL command line interface. run the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\q
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, to leave the Postgres user context and return to the Ubuntu root folder, type&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;exit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it! We've successfully set up a user and a database in PostgreSQL on our Ubuntu server.&lt;/p&gt;

&lt;p&gt;Uff.. It's been quite a journey, but we're making great progress.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifying the Database Connection from Ubuntu Root Folder(optional)  &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now let's verify if we can connect to the newly created database from the Ubuntu server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo adduser &amp;lt;&amp;lt;USERNAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;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.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To open the PostgreSQL shell as the &lt;code&gt;&amp;lt;&amp;lt;USERNAME&amp;gt;&amp;gt;&lt;/code&gt;, run the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo -u &amp;lt;&amp;lt;USERNAME&amp;gt;&amp;gt; psql -d &amp;lt;&amp;lt;DATABASE_NAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once logged in, check the connection details with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\conninfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is set up correctly, you will see a message similar to:&lt;br&gt;
&lt;code&gt;You are connected to database &amp;lt;&amp;lt;DATABASE_NAME&amp;gt;&amp;gt; as user &amp;lt;&amp;lt;USERNAME&amp;gt;&amp;gt; via socket in "/var/run/postgresql" at port "5432".&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This confirmation indicates a successful connection to your PostgreSQL database from the Ubuntu server.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;
&lt;h3&gt;
  
  
  Verifying PostgreSQL Connection with Node.js ### &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now we'll verify the database that we set up is successfully connected to the Node.js server.&lt;/p&gt;

&lt;p&gt;Navigate to your project repository by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd into &amp;lt;&amp;lt;YOUR_PROJECT_NAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once in your project directory, start your Node.js application to check the database connection&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Now, exit the project by pressing &lt;code&gt;ctrl+c&lt;/code&gt; and navigate to Ubuntu root server by running the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Back to top&lt;/p&gt;

&lt;h3&gt;
  
  
  NGINX &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Now we have come to the last bit, exposing the project to the internet.&lt;/p&gt;

&lt;p&gt;We will use the internet's favorite(also my personal favorite) &lt;a href="https://www.nginx.com/"&gt;NGINX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You could ask me why NGINX.&lt;/p&gt;

&lt;p&gt;Here are my top 3 reasons.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nginx efficiently handles static files and a large number of simultaneous connections, offloading this work from Node.js.&lt;/li&gt;
&lt;li&gt;Nginx acts as a security layer, shielding your Node.js application from direct exposure to the internet.&lt;/li&gt;
&lt;li&gt;Nginx can manage SSL/TLS encryption, simplifying the setup of HTTPS for your Node.js app.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that said let's start.&lt;/p&gt;

&lt;p&gt;Install NGINX by running the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/nginx/sites-available/&amp;lt;&amp;lt;YOUR_PROJECT_NAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see the empty editor like the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRgFRT_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/584fisp5ijuts9gmbgx3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRgFRT_K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/584fisp5ijuts9gmbgx3.PNG" alt="Image description" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let us add the below code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    listen 80;
    server_name &amp;lt;&amp;lt;your_domain_or_IP&amp;gt;&amp;gt;;

    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;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &amp;lt;&amp;gt; with your domain name or IP address and YOUR_NODE_JS_PORT with the port number where your Node.js app is running.&lt;/p&gt;

&lt;p&gt;This configuration does the following&lt;/p&gt;

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

&lt;p&gt;After adding the code save the file by pressing &lt;code&gt;Ctrl+O&lt;/code&gt;, then press &lt;code&gt;Enter&lt;/code&gt;, and exit the editor with &lt;code&gt;Ctrl+X&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next test the NGINX configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the test is successful, create a symbolic link to enable your site configuration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ln -s /etc/nginx/sites-available/&amp;lt;&amp;lt;YOUR_PROJECT_NAME&amp;gt;&amp;gt;  
 /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart the NGINX server to apply the changes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to the project root by running the command below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd &amp;lt;&amp;lt;PROJECT_NAME&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, start your Node.js server permanently with PM2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pm2 start dist/index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Back to top&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://dev.to/vijeth-simha/nodejs-with-typescript-the-ultimate-guide-to-automated-deployment-on-digitalocean-using-github-actions-4i74"&gt;post&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Finally
&lt;/h3&gt;

&lt;p&gt;As you embark on this journey of deploying your Node.js application with PostgreSQL on DigitalOcean and configuring NGINX, feel free to use my &lt;a href="https://github.com/vijeth-simha/education-documents-organizer"&gt;project&lt;/a&gt; as a practical example to follow along with the steps outlined above.&lt;/p&gt;

&lt;p&gt;Should you encounter any challenges or have questions during the process, please don't hesitate to leave a comment below.&lt;/p&gt;

&lt;p&gt;Feel free to reach out to me on&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/vijeth_simha"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/vijeth-simha/"&gt;Linkedin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vijeth-simha"&gt;Github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back to top&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>deployment</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
