<?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>DEV Community: Antai Okon-Otoyo</title>
    <description>The latest articles on DEV Community by Antai Okon-Otoyo (@antai).</description>
    <link>https://dev.to/antai</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%2F2798905%2F1b6cc75d-44d5-47cc-9734-dd561c4721b9.jpeg</url>
      <title>DEV Community: Antai Okon-Otoyo</title>
      <link>https://dev.to/antai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/antai"/>
    <language>en</language>
    <item>
      <title>Serverless Deployment of a Simple Item Manager</title>
      <dc:creator>Antai Okon-Otoyo</dc:creator>
      <pubDate>Thu, 21 Aug 2025 06:13:09 +0000</pubDate>
      <link>https://dev.to/antai/serverless-deployment-of-a-simple-item-manager-bic</link>
      <guid>https://dev.to/antai/serverless-deployment-of-a-simple-item-manager-bic</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This project provides a guide on how to deploy a simple item manager using a serverless architecture.&lt;/p&gt;

&lt;p&gt;At the heart of serverless computing with AWS sits the AWS Lambda, which allows you to forget about server or infrastructure management and provisioning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS Lambda&lt;/strong&gt; is a service that lets you run code without having to manage servers. So in a nutshell, AWS handles your compute processes while you provide the code.&lt;/p&gt;

&lt;p&gt;In our project, we are going to make use of the following AWS services to deploy our simple item manager application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AWS Lambda&lt;/li&gt;
&lt;li&gt;Amazon API Gateway&lt;/li&gt;
&lt;li&gt;Amazon DynamoDB&lt;/li&gt;
&lt;li&gt;AWS Amplify&lt;/li&gt;
&lt;/ol&gt;

&lt;h6&gt;
  
  
  Architecture Diagram
&lt;/h6&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0evbppq4llqwu2cnipo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0evbppq4llqwu2cnipo.png" alt="Project Architecture Diagram" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Project Steps
&lt;/h3&gt;




&lt;h4&gt;
  
  
  1. Setting up the Lambda Function
&lt;/h4&gt;

&lt;p&gt;On the AWS Management Console, you search for Lambda and then choose "Create Function"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyq436o0gh8xmn5zmuwkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyq436o0gh8xmn5zmuwkt.png" alt="Creating Lambda Function" width="800" height="312"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;&lt;br&gt;
Deploy your code in the editor provided.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flj95lq51ows6aenw3vlr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flj95lq51ows6aenw3vlr.png" alt="Lambda Code Deployed" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h4&gt;
  
  
  2. Setting up DynamoDB Table for CRUD Operations
&lt;/h4&gt;

&lt;p&gt;On the AWS Management Console, you search for DynamoDB and then choose "Create Table"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1flrgvam17n5nq3b353d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1flrgvam17n5nq3b353d.png" alt="Creating DynamoDB table" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The partition key in Amazon DynamoDB is similar to a primary key in relational databases, but not exactly the same.&lt;br&gt;
Every DynamoDB table must have a partition key, and it is used to determine the physical storage partition where the item will live (hence the name).&lt;br&gt;
Also, please note that if the sort key is not defined, then the primary key must be unique.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that the DynamoDB table has been created successfully, we need to go back to the Lambda function and grant the Lambda execution role access to DynamoDB to allow the function to perform CRUD operations.&lt;/p&gt;

&lt;p&gt;Under the Configuration tab of the Lambda function, navigate to Permissions and click on the execution role, which will redirect you to the IAM role to grant the necessary permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3z0ryc82b0wi07qutlk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3z0ryc82b0wi07qutlk.png" alt="Lambda Permissions View" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the IAM role, search for DynamoDB and select the AmazonDynamoDBFullAccess permission. Then, click "Add permissions".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In a production environment, it is important to ensure the principle of least privilege is applied when granting the necessary permissions. This would mean attaching an inline policy and granting only the permissions required by Lambda for your application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlxw8lriophfxjxf6ina.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlxw8lriophfxjxf6ina.png" alt="Add Permissions" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will also need to set an environment variable to enable our Lambda function to recognise our DynamoDB table. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhhpxe4a0b5pi23a0zh8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhhpxe4a0b5pi23a0zh8.png" alt="Environment variable set" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h4&gt;
  
  
  3. Setting up API Gateway for Lambda Function
&lt;/h4&gt;

&lt;p&gt;On the AWS Management Console, you search for and select API Gateway and then choose "Create an API".&lt;/p&gt;

&lt;p&gt;We will need to choose an API type, and for the sake of this project, we are going to be using the REST API type&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wlpl1ftdjck10vo3763.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wlpl1ftdjck10vo3763.png" alt="API Created" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create Resource paths and their respective HTTP methods that would be processed through them.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0znk4tqc80kxaoskjf2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0znk4tqc80kxaoskjf2q.png" alt="Create Resource" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs1esohkxg2vgf00vw63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs1esohkxg2vgf00vw63.png" alt="Resource Created" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9kwpd7kwp888n8tjp8p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz9kwpd7kwp888n8tjp8p.png" alt="Create Methods" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf8o9e4ntmd8gd7srypc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf8o9e4ntmd8gd7srypc.png" alt="Methods Created" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enable CORS &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtpbil104otm32a97vmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtpbil104otm32a97vmk.png" alt="Enable CORS on Resource Paths" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After setting the API resources, we now have to deploy the API and get our API Invoke URL, which we can test with and use for invoking our lambda function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr82yx9wwcgz5ihobew6e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr82yx9wwcgz5ihobew6e.png" alt="Deploy API" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Test the API to ensure the API is working as expected.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq473tbvh48g2ly037365.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq473tbvh48g2ly037365.png" alt="API Tested on Postman" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h4&gt;
  
  
  4. Setting up AWS Amplify to host our Frontend.
&lt;/h4&gt;

&lt;p&gt;AWS Amplify is a set of tools and services provided by AWS that is designed to help developers build, deploy, and manage full-stack web and mobile applications quickly and easily.&lt;br&gt;
We are going to use it in this project to quickly and easily host or deploy our item manager application.&lt;/p&gt;

&lt;p&gt;Before setting up AWS Amplify, ensure the api.ts file in the services folder of your source code is updated with your API Invoke URL received after setting up and deploying your API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o4wha8j26gkagwgu9n9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5o4wha8j26gkagwgu9n9.png" alt="Update your API Invoke URL in Source Code" width="712" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the AWS Management Console, you search for and select Amplify and then choose "Deploy an App"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxbpt5j2bf4g9lvsmwgw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faxbpt5j2bf4g9lvsmwgw.png" alt="AWS Amplify" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've not used Amplify before, it would require you to integrate with your repository for deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4k7hsevmd6yevxst38i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4k7hsevmd6yevxst38i.png" alt="Start building with Amplify" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9acvl5k8hchfuzw4v5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9acvl5k8hchfuzw4v5h.png" alt="Integrating with Github" width="800" height="747"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please note that the frontend code has already been pushed to the GitHub repository and the API Invoke URL has been included in the necessary file as a variable to be called when performing crud operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Review the deployment before saving and deploying the code.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flmx9ukbi4wjzsxuoni49.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flmx9ukbi4wjzsxuoni49.png" alt="Review Deployment" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After saving and deploying, we can confirm that the application is working as expected, as seen in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1zzyw6nqpzgnuapy2lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1zzyw6nqpzgnuapy2lu.png" alt="App Deployed and Working" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;h3&gt;
  
  
  Challenges
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lambda Function Configuration Issues&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My initial API tests returned a 502 Bad Gateway error, pointing to an issue within the Lambda function's execution. A quick review of the function's configuration revealed the problem: &lt;br&gt;
I had omitted a critical environment variable required for the function to resolve the correct DynamoDB table. This experience highlighted the importance of thorough environment variable management as a key step in the deployment and testing lifecycle.&lt;/p&gt;



&lt;h3&gt;
  
  
  Bonus Step - Terraform Migration
&lt;/h3&gt;

&lt;p&gt;After a successful deployment, I decided to experiment with Infrastructure as Code (IaC). I used Terraform to import the existing cloud resources into my Terraform state file, allowing me to manage future updates and changes through IaC.&lt;/p&gt;

&lt;p&gt;If you would like to do the same, you can follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create empty resource blocks for the resources you are trying to import.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqzgjuxg0am3q38akc7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqzgjuxg0am3q38akc7x.png" alt="Empty Resource Block" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I ran these commands (among others) to import the resources from AWS. Do the same regarding the resources being imported. The number of import statements you run is determined by the number of resources you are importing. The Terraform documentation is great and will guide you accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$ terraform import aws_dynamodb_table.items-table ItemsTable&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ terraform import aws_lambda_function.items-function ItemFunction&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ terraform import aws_api_gateway_rest_api.ItemsAPI 9lwgudjgw4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ terraform import aws_amplify_app.items-app d313k4wcghvl6q&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;terraform show&lt;/code&gt; to give you details of the resources imported so you can update your empty resource blocks as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;terraform plan&lt;/code&gt; to ensure that your configuration is fine and no extra resources are being added.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;terraform apply&lt;/code&gt; to ensure that your configuration is fine and your infrastructure is successfully and finally synced to your state file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can now check and confirm that there are no issues with your application and resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomiw1qtlz9h6582nr6iy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomiw1qtlz9h6582nr6iy.png" alt="Working after terraform migration" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Project source code can be found on my GitHub repo &lt;a href="https://github.com/AntaiKhan/serverless-amplify-frontend-itemmanager" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>serverless</category>
      <category>aws</category>
      <category>john316</category>
    </item>
    <item>
      <title>Deploying a Static Website on S3 with Terraform</title>
      <dc:creator>Antai Okon-Otoyo</dc:creator>
      <pubDate>Fri, 27 Jun 2025 21:10:06 +0000</pubDate>
      <link>https://dev.to/antai/deploying-a-static-website-on-s3-with-terraform-17b</link>
      <guid>https://dev.to/antai/deploying-a-static-website-on-s3-with-terraform-17b</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This project provides a guide on how to deploy a static website on S3 using Terraform. With Terraform, we would create an S3 bucket and make it public, along with a page for error handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Terraform?
&lt;/h3&gt;

&lt;p&gt;Terraform has proven itself to be a very useful IaC tool in the Cloud and DevOps Engineering ecosystem.&lt;/p&gt;

&lt;p&gt;The key advantage of using Terraform is that it allows for infrastructure to be managed as code, enabling automation, reusability, and collaboration across different cloud providers and environments. It simplifies the process of provisioning, managing, and updating infrastructure, making it faster and more efficient. &lt;/p&gt;

&lt;h3&gt;
  
  
  Project Pre-requisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;An active AWS account.&lt;/li&gt;
&lt;li&gt;Terraform Installation Completed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Steps
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;s3-portfolio-website/
├── index.html
├── error.html
├── terraform/
│   ├── provider.tf
│   ├── main.tf
│   ├── outputs.tf
│   └── variables.tf
└── profile.jpg  &amp;lt;-- Add your image here

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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Set Up Provider on Terraform
&lt;/h4&gt;

&lt;p&gt;The first thing we would do is set up our provider. You can run &lt;code&gt;terraform init&lt;/code&gt; after that to download the provider plugin and initialize the backend for state management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# provider.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "6.0.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Set Up S3 Bucket with Terraform
&lt;/h4&gt;

&lt;p&gt;The resource block below creates a bucket with &lt;code&gt;bucket&lt;/code&gt; as a required field specifying the name of the bucket being created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#main.tf

resource "aws_s3_bucket" "sitebucket" {
  bucket = var.bucketname
}

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;variables.tf&lt;/code&gt; file is used to define your variables instead of hard-coding them in the &lt;code&gt;main.tf&lt;/code&gt; file. This is best practice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#variables.tf

variable "bucketname" {
  default = "&amp;lt;your-bucket-name&amp;gt;"
}

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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Set Up Bucket Ownership
&lt;/h4&gt;

&lt;p&gt;This is to set ownership of the bucket and ensure no one else can claim ownership.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#main.tf

resource "aws_s3_bucket_ownership_controls" "objectOwner" {
  bucket = aws_s3_bucket.sitebucket.id

  rule {
    object_ownership = "BucketOwnerPreferred"
  }
}

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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Make S3 Bucket Publicly Accessible
&lt;/h4&gt;

&lt;p&gt;By default, AWS S3 buckets are private and restricted for public access, which follows AWS security's principle of Least Privilege. This is best practice as it minimizes the potential attack surface and reduces the risk of unauthorized access or data breaches.&lt;/p&gt;

&lt;p&gt;However, to host the site through S3 and allow our website and images to be publicly accessible, we need to make the bucket public using the resource block below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#main.tf

resource "aws_s3_bucket_public_access_block" "public" {
  bucket = aws_s3_bucket.sitebucket.id

  block_public_acls       = false
  block_public_policy     = false
  ignore_public_acls      = false
  restrict_public_buckets = false
}

resource "aws_s3_bucket_acl" "bucketacl" {
  depends_on = [
    aws_s3_bucket_ownership_controls.objectOwner,
    aws_s3_bucket_public_access_block.public,
  ]

  bucket = aws_s3_bucket.sitebucket.id
  acl    = "public-read"
}

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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Set Up Site Files and Objects
&lt;/h4&gt;

&lt;p&gt;This will upload your site files and images from your local environment to your S3 Bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#main.tf

resource "aws_s3_object" "index" {
  bucket       = aws_s3_bucket.sitebucket.id
  key          = "index.html"
  source       = "../index.html"
  acl          = "public-read"
  content_type = "text/html"

  depends_on = [ aws_s3_bucket_acl.bucketacl ]

}

resource "aws_s3_object" "error" {
  bucket       = aws_s3_bucket.sitebucket.id
  key          = "error.html"
  source       = "../index.html"
  acl          = "public-read"
  content_type = "text/html"

  depends_on = [ aws_s3_bucket_acl.bucketacl ]

}

resource "aws_s3_object" "profilepic" {
  bucket = aws_s3_bucket.sitebucket.id
  key    = "linkedin-profile-pic.jpeg"
  source = "../linkedin-profile-pic.jpeg"
  acl    = "public-read"

  depends_on = [ aws_s3_bucket_acl.bucketacl ]
}

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

&lt;/div&gt;






&lt;h4&gt;
  
  
  Enable Static Website Hosting on S3
&lt;/h4&gt;

&lt;p&gt;This resource block will help set up our website on S3, specifying the index and error files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#main.tf

resource "aws_s3_bucket_website_configuration" "website" {
  bucket = aws_s3_bucket.sitebucket.id

  index_document {
    suffix = "index.html"
  }

  error_document {
    key = "error.html"
  }

  depends_on = [ aws_s3_bucket_acl.bucketacl ]

}

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

&lt;/div&gt;



&lt;p&gt;Note: The &lt;code&gt;depends_on&lt;/code&gt; attribute is to let your code know the order in which you want your resource blocks created. In other words, it tells you the dependencies for your resource block, which means for the resource block above, the bucketacl resource must be created first before the website resource.&lt;/p&gt;

&lt;p&gt;I created an &lt;code&gt;outputs.tf&lt;/code&gt; file to return the value of my website endpoint on my terminal, as against getting it from the AWS console directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#outputs.tf

output "website_endpoint" {
  value = aws_s3_bucket.sitebucket.website_endpoint
}

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

&lt;/div&gt;



&lt;p&gt;We are now done with building the resource blocks. The next steps are to run the following commands to help us create the infrastructure in our AWS environment:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform fmt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Automatically formats your configuration files into a standard format that adheres to a predefined set of rules of indentation, spacing, and alignment across your terraform code, making it more readable and maintainable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform validate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks the Syntax and structure of your Terraform configuration files without deploying any resources.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform plan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a plan consisting of the set of changes that will make your resources match your configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;terraform apply -auto-approve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes the actions proposed in a Terraform plan to create, update, or destroy infrastructure. The &lt;code&gt;-auto-approve&lt;/code&gt; option is to automatically approve, as &lt;code&gt;terraform apply&lt;/code&gt; will always ask for confirmation of approval when it runs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe27mwre5m7w2qi5ffh92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe27mwre5m7w2qi5ffh92.png" alt="Terraform codes" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjjd4csap2pulei43bnk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnjjd4csap2pulei43bnk.png" alt="Terraform codes 2" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttm1ss5gegkgaxpe078v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttm1ss5gegkgaxpe078v.png" alt="Terraform codes 3" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;After the commands have been run, your website should be up with the endpoint made available to you on your terminal for confirmation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazatsorrx6d4zqll727r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazatsorrx6d4zqll727r.png" alt="S3 Site Deployed" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: If you come across this error: &lt;code&gt;Error: uploading object to S3 bucket : AccessControlListNotSupported: The bucket does not allow ACLs status code: 400&lt;/code&gt;, Ensure you use the &lt;code&gt;depends_on&lt;/code&gt; attribute to ensure that your bucket ACL is configured first for public-read before the files are uploaded.&lt;/p&gt;

&lt;p&gt;On a final note, you can always refer to the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs" rel="noopener noreferrer"&gt;Terraform Documentation&lt;/a&gt; to assist you build your infrastructure.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>s3</category>
      <category>devops</category>
    </item>
    <item>
      <title>Deploying a Number Classification API on AWS Lambda + API Gateway using Zappa</title>
      <dc:creator>Antai Okon-Otoyo</dc:creator>
      <pubDate>Mon, 10 Feb 2025 14:54:46 +0000</pubDate>
      <link>https://dev.to/antai/deploying-a-number-classification-api-on-aws-lambda-api-gateway-using-zappa-4gh2</link>
      <guid>https://dev.to/antai/deploying-a-number-classification-api-on-aws-lambda-api-gateway-using-zappa-4gh2</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This project is a Flask-based API that provides interesting mathematical properties of a given number. It determines whether a number is prime, perfect, or an Armstrong number, and also provides its digit sum and a fun fact.&lt;/p&gt;

&lt;p&gt;Zappa makes it super easy to build and deploy serverless, event-driven python applications(including, but not limited to, WSGI web apps) on AWS Lambda + API Gateway. Find more info about Zappa &lt;a href="https://github.com/zappa/Zappa" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that you would need an AWS CLI user setup with necessary permissions to lambda and api gateway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Determines if a number is prime, perfect, or an Armstrong number.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Computes the sum of digits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns a fun fact about the number.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports CORS for cross-origin access.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns responses in JSON format.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setup Necessary Tools and Dependencies.
&lt;/h2&gt;




&lt;p&gt;First of all, Ensure you have python installed. You can go through the python documentation to assist you.&lt;/p&gt;

&lt;p&gt;Install Flask and Zappa.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install flask flask-cors zappa&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Setup your API on app.py in your local environment
&lt;/h2&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask, request, jsonify
from flask_cors import CORS
import requests
import math

app = Flask(__name__)
CORS(app)

def is_prime(num):
    if num &amp;lt;= 1 or num % 1 != 0:
        return False
    num = int(num)
    for i in range(2, int(math.sqrt(num)) + 1):
        if num % i == 0:
            return False
    return True

def is_armstrong(num):
    if num % 1 != 0:  # Only whole numbers can be Armstrong numbers
        return False
    num = abs(int(num))
    digits = [int(digit) for digit in str(num)]
    power = len(digits)
    return sum(digit ** power for digit in digits) == num

def get_fun_fact(num):
    url = f"http://numbersapi.com/{num}/math"
    response = requests.get(url)
    return response.text if response.status_code == 200 else "No fun fact found"

@app.route('/api/classify-number', methods=['GET'])
def classify_number():
    number = request.args.get('number')

    try:
        number = float(number)
    except (ValueError, TypeError):
        return jsonify({"number": number, "error": "true"}), 400

    armstrong = is_armstrong(number)
    prime = is_prime(number)
    even = number % 2 == 0
    digit_sum = sum(map(int, str(abs(int(number)))))
    fun_fact = get_fun_fact(int(number))

    properties = []
    if armstrong:
        properties.append("armstrong")
    properties.append("even" if even else "odd")

    return jsonify({
        "number": number,
        "is_prime": prime,
        "is_perfect": False,  # No perfect number check required
        "properties": properties,
        "digit_sum": digit_sum,
        "fun_fact": fun_fact
    })

if __name__ == "__main__":
    app.run()

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

&lt;/div&gt;



&lt;p&gt;Test your API Locally&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://127.0.0.1:5000/api/classify-number?number=-100.5&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ppkk9z5p1h5oncnfo5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ppkk9z5p1h5oncnfo5g.png" alt="API Tested Locally" width="800" height="129"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Deploy API with Zappa on AWS Lambda using API Gateway
&lt;/h2&gt;




&lt;p&gt;Initialize Zappa&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zappa init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F448c9e0f-febb-44ab-b0b9-0e35c54ebde8" class="article-body-image-wrapper"&gt;&lt;img alt="image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F448c9e0f-febb-44ab-b0b9-0e35c54ebde8" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow the prompts to configure deployment settings.&lt;/p&gt;

&lt;p&gt;Deploy your Flask app to AWS Lambda using the code below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zappa deploy dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This would take a while. After deployment, a link will be shared to access your API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra30wtyy2gqy3xhra5u9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fra30wtyy2gqy3xhra5u9.png" alt="API Deployed" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you make update to your function, you can always update lambda using the code below&lt;/p&gt;

&lt;p&gt;&lt;code&gt;zappa update dev&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm4q96nmik5gmv0c8q0d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm4q96nmik5gmv0c8q0d.png" alt="API Update Redeployed" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;blockquote&gt;
&lt;p&gt;Zappa will automatically set up a regularly occurring execution of your application to keep the Lambda function warm. This helps optimize speed and produces fast response time.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;You can confirm the creation of the AWS Lambda function and API Gateway on your AWS Console and also make changes there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7eweuntpkvggvnim4zl3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7eweuntpkvggvnim4zl3.png" alt="API Created on AWS Console" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xx59vf4wcjdlatslv5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xx59vf4wcjdlatslv5z.png" alt="Lambda Function Created on AWS Console" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>zappa</category>
      <category>aws</category>
      <category>python</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Setting Up Nginx on an Amazon EC2 Instance</title>
      <dc:creator>Antai Okon-Otoyo</dc:creator>
      <pubDate>Fri, 31 Jan 2025 23:33:47 +0000</pubDate>
      <link>https://dev.to/antai/setting-up-nginx-on-an-amazon-ec2-instance-4a2p</link>
      <guid>https://dev.to/antai/setting-up-nginx-on-an-amazon-ec2-instance-4a2p</guid>
      <description>&lt;h2&gt;
  
  
  INTRODUCTION
&lt;/h2&gt;




&lt;p&gt;This document provides a step-by-step guide on how to install and configure the NGINX web server on an Amazon EC2 Instance running on Ubuntu. At the end of this guide, we should have a functional nginx web server set up that serves a custom webpage, demonstrating foundational cloud infrastructure management and web server configuration skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 0 - Prepping AWS
&lt;/h2&gt;




&lt;p&gt;We need to set up an EC2 instance. You do that by using the search bar to search for EC2 and clicking on &lt;strong&gt;Launch Instance&lt;/strong&gt;. Then follow the steps below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select a free tier Ubuntu image as the AMI (Amazon Machine Image).&lt;/li&gt;
&lt;li&gt;Select the Instance type next, I used free tier eligible t2.micro to eliminate cost.&lt;/li&gt;
&lt;li&gt;Create security key pair for secure connection to your instance (ensure to keep your .pem file very safe).&lt;/li&gt;
&lt;li&gt;Ensure you create a security group to allow SSH connection to your instance using your .pem file.&lt;/li&gt;
&lt;li&gt;You can use default settings to configure instance details.&lt;/li&gt;
&lt;li&gt;Launch Instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensure your status check shows "2/2 checks passed" as seen in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcisu1abzhpxwztsoeb6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcisu1abzhpxwztsoeb6z.png" alt="EC2 Launched" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connect to AWS EC2 Instance using code below (for SSH Client):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;chmod 400 "nginx-web.pem"&lt;/code&gt; (for MacOS Users only)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ssh -i "nginx-web.pem" ubuntu@ec2-44-243-195-121.us-west-2.compute.amazonaws.com&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: nginx-web.pem should be replaced with the name of your .pem file. AWS would also assist you with commands to run as seen below:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuwh5895kkaweegk6xq7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkuwh5895kkaweegk6xq7.png" alt="Connection to EC2" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 1  - Update Package AND Install NGINX
&lt;/h2&gt;




&lt;p&gt;Run the command below to update the list of packages in package manager.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt update&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxkpbn1af5vkqohbglkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxkpbn1af5vkqohbglkf.png" alt="Package Update" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the command below to install nginx (option &lt;code&gt;-y&lt;/code&gt; is to automatically say yes to the permission requested during installation)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo apt install nginx -y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvgo0yzxkqx5725hyzp3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvgo0yzxkqx5725hyzp3.png" alt="Nginx Installed" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After installing the nginx service, you use the command below to start the nginx service.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo systemctl start nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The enable command below is to add nginx as part of the system services and ensure that whenever you restart your instance, the nginx service is restarted along side.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo systemctl enable nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqileulvwofd7v80b8nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffqileulvwofd7v80b8nc.png" alt="Nginx Enabled" width="800" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check the status of your nginx status to ensure it is active with below&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo systemctl status nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fe2m16d4ypllm2zd4ho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fe2m16d4ypllm2zd4ho.png" alt="Nginx Status" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 2 - Create Your HTML File
&lt;/h2&gt;




&lt;p&gt;First, we will navigate to the var directory which is the root path for your HTML files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd /var/www/html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then create and write to your html file using vim with command below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo vim index.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You press "I" on your keyboard to change into insert mode and insert your code.&lt;/p&gt;

&lt;p&gt;Press the esc key to leave insert mode and :wq to write/save and quit.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r01yu70efgjn5sqxkhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1r01yu70efgjn5sqxkhu.png" alt="HTML file created" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that your index.html file is created, restart nginx for the changes to take effect.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo systemctl restart nginx&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tafl2pwy2spjm3ux0bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2tafl2pwy2spjm3ux0bj.png" alt="Nginx Restarted" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  STEP 3 - Update Security Group FOR EC2 Instance
&lt;/h2&gt;




&lt;p&gt;Under the Security tab of the EC2 Instance, Click on the security group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xlttvsfaf7z5s5yij9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9xlttvsfaf7z5s5yij9w.png" alt="Locate Security Group" width="800" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Edit inbound rules and add rule to allow port 80 to enable us access the HTML page over the internet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ecrsloytj56t3up8n65.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ecrsloytj56t3up8n65.png" alt="Security Group Updated" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now open your web browser and verify via the public IP as seen in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhg7rtqnvq32w207jeg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhg7rtqnvq32w207jeg7.png" alt="Locate Public IP" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Access the html page through your web browser.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;http://your-server-ip&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvc1uyx7n9dlv77ocing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvc1uyx7n9dlv77ocing.png" alt="Open web browser" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project Completed.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;




&lt;p&gt;-&lt;a href="https://hng.tech/hire/devops-engineers" rel="noopener noreferrer"&gt;DevOps Engineers&lt;/a&gt;&lt;br&gt;
-&lt;a href="https://hng.tech/hire/cloud-engineers" rel="noopener noreferrer"&gt;Cloud Engineers&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>tutorial</category>
      <category>aws</category>
      <category>nginx</category>
    </item>
  </channel>
</rss>
