How to Create a Subdomain in Amazon Route 53?


In this post, I will show you how to set up a new subdomain using Route 53 in 4 easy steps. The setup is straightforward and will take less than 2 minutes to have your subdomain up and running.¬†ūüôā

Step 1: Make a hosted zone for your original domain

Make sure that you have already created a hosted zone for your original domain. If you need guidance, you can refer to this blog post, where I set up a hosted zone for aloudapp.in.

View at Medium.com

Step 2: Create a new hosted zone for your subdomain

Click on Create Hosted Zone to create a new hosted zone. Enter the domain name as api.aloudapp.in and enter anything you want in the comment section. Set the type as Public Hosted Zone and click Create.

Create a new hosted zone

Step 3: Create a new NS record set for your original domain

  1. Click into your hosted zone, and select the recordset with type NS.

2. Copy the nameservers in the value box on the right.

Copy the value of the NS recordset.

3. Go back to your original hosted zone and click on Create Record Set.

4. Create a new NS record set with the name same as your subdomain and the value that you just copied. Click on Create to create it.

Create a new NS recordset in your original hosted zone.

Step 4: Create an A record set for your subdomain

Return to your subdomain’s hosted zone and click on Create Record Set to create a new recordset. Leave the name empty and set the type as A. In the value field, you can enter any IP address that you want it to point to. Click on Create to create it.

Create an A recordset mapping it to some IP address.

That‚Äôs it. Your subdomain should be up and running.¬†ūüôā


Make sure you give this post 50 claps and follow me if you enjoyed this post and want to see more!

How to install FFMPEG on EC2 running Amazon Linux?


Recently, I needed to install ffmpeg on my EC2 instance and I struggled quite a bit to set it up. The issue was that my EC2 instance is running Amazon Linux based AMI which is probably based on some version of CentOS. For Debian and Ubuntu distributions, ffmpeg is available as a apt-get package but for other distributions you have to manually compile it. To be fair ffmpeg has provided a compilation guide for CentOS but for lazy people, it is too much of an effort.¬†ūüôā

Finally, I found a solution that worked perfectly so I thought of sharing it here. Here’s the step by step guide.

Step 1: SSH into your instance and become root

sudo su -

Step 2: Go to the /usr/local/bin directory

cd /usr/local/bin

Step 3: Inside the /usr/local/bin directory, create an ffmpeg directory and go inside it.

mkdir ffmpeg && cd ffmpeg

Step 4: Download a static build of ffmpeg

Go to the following link and download a static build relevant for your system.

https://www.johnvansickle.com/ffmpeg/

To check if your system is 32-bit or 64-bit you can execute the following command:

uname -a

It will output something like:

Linux ip-172-31-1-100 4.9.62-21.56.amzn1.x86_64 #1 SMP Thu Nov 16 05:37:08 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

Note: That last i386 indicates that it’s 32-bit; x86_64 indicates 64-bit.

Also, by hit and trial, I found out that the processor is AMD and not ARM. Inside the /usr/local/bin/ffmpeg folder run this command to download the static binaries.

wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz

Step 5: Unzip the binaries

Use the following command to unzip the binaries.

tar -xf ffmpeg-release-amd64-static.tar.xz

This will create a folder named ffmpeg-4.2.1-amd64-static . Go inside this folder to check if ffmpeg has been installed successfully or not.

./ffmpeg -version

It should output something like:

ffmpeg version 4.2.1-static https://johnvansickle.com/ffmpeg/  
.
.
.
.
Hyper fast Audio and Video encoder

Now we will move to the outer folder.

cp -a /usr/local/bin/ffmpeg/ffmpeg-4.2.1-amd64-static/ . /usr/local/bin/ffmpeg/

Step 6: Create a symlink to use ffmpeg from any location

Next, go ahead and create a symlink so that ffmpeg can be run from any location.

ln -s /usr/local/bin/ffmpeg/ffmpeg /usr/bin/ffmpeg

Note: The first part /usr/local/bin/ffmpeg/ffmpeg is where the file is located after I untarred the file. The second part /usr/bin/ffmpeg is where we want the symlink to go

That’s it. You are done with the installation.

I found this solution on AWS forums and have shared it here so that it is easier to find. Here’s a link to the forum post.

https://forums.aws.amazon.com/thread.jspa?messageID=332091

Setting up Text To Speech Application using Amazon Polly

Long back we used AWS to set up a PHP and MYSQL application. This weekend will work Amazon Polly to deploy our own TTS application.

Amazon Polly is a Text-to-Speech service that uses advanced deep learning technologies to synthesize speech that sounds like a human voice.

This article is heavily based on the guide on AWS. Our application architecture looks as below:

Source Link

Lets start building the application where we will set up a few lambda functions, SNS and S3 bucket to finally result in RESTful APIs that can convert text to speech for us.

Create a DynamoDB Table

Create a DynamoDB table to store text and corresponding audio files.

Creating an AloudStory table

Create an S3 Bucket

Create an S3 bucket that will hold all the audio files for you. Go through the Create bucket wizard to complete the process.

Creating a S3 bucket

Create a SNS Topic

The work of converting a text file to an audio output would be done by 2 Lambda functions. Let’s create a new SNS topic from the SNS console.

Creating a new SNS topic for new posts

Create a New Role

Create a new Role in the IAM Console.

Choose the Lambda service for this role

After choosing the service that will use this role, go ahead and give this Role a name and click on Create Role.

Give the role a name and description

After the Role is created, click on Add inline policy under the Permissions tab.

Click on Add inline policy

Copy paste the following policy, which provides Lambda with access to the services included in the architecture diagram

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"polly:SynthesizeSpeech",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"sns:Publish",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetBucketLocation",
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"*"
]
}
]
}

After adding the JSON, review the policy and name it.

Create policy after reviewing it

Creating a New Post Lambda Function

Create a Lambda function fore new posts

Copy paste the following code for it:

import boto3
import os
import uuid
def lambda_handler(event, context):

recordId = str(uuid.uuid4())
voice = event["voice"]
text = event["text"]
print('Generating new DynamoDB record, with ID: ' + recordId)
print('Input Text: ' + text)
print('Selected voice: ' + voice)

#Creating new record in DynamoDB table
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['DB_TABLE_NAME'])
table.put_item(
Item={
'id' : recordId,
'text' : text,
'voice' : voice,
'status' : 'PROCESSING'
}
)

#Sending notification about new post to SNS
client = boto3.client('sns')
client.publish(
TopicArn = os.environ['SNS_TOPIC'],
Message = recordId
)

return recordId

Use the following environment variables for the DynamoDB table and the SNS topic.

  • SNS_TOPIC‚Ää‚ÄĒ‚Ääthe Amazon Resource Name (ARN) of the SNS topic we created
  • DB_TABLE_NAME‚Ää‚ÄĒ‚Ääthe name of the DynamoDB table (in our case, it‚Äôs posts)

Assign the IAM role that we created for the Lambda functions.

Select the role for execution

Add a New Test in the wizard to test if the function is working.

{   "voice": "Joanna",   "text": "This is working!" }

Now you test your function by clicking on Test.


Create a Convert to Audio Lambda function

Again use the same wizard to create a new Lambda function, PostReader_ConvertToAudio.

Create a lambda function to convert to audio

Configure an SNS trigger so that this function is executed whenever a new post comes in.

Configuring trigger for the lambda function

Copy paste the following code to this lambda function editor. Take care of your indentations, its python.¬†ūüėÄ

import boto3
import os
from contextlib import closing
from boto3.dynamodb.conditions import Key, Attr
def lambda_handler(event, context):
postId = event["Records"][0]["Sns"]["Message"]

print "Text to Speech function. Post ID in DynamoDB: " + postId

#Retrieving information about the post from DynamoDB table
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['DB_TABLE_NAME'])
postItem = table.query(
KeyConditionExpression=Key('id').eq(postId)
)
text = postItem["Items"][0]["text"]
voice = postItem["Items"][0]["voice"]

rest = text

#Because single invocation of the polly synthesize_speech api can
# transform text with about 1,500 characters, we are dividing the
# post into blocks of approximately 1,000 characters.
textBlocks = []
while (len(rest) > 1100):
begin = 0
end = rest.find(".", 1000)
if (end == -1):
end = rest.find(" ", 1000)

textBlock = rest[begin:end]
rest = rest[end:]
textBlocks.append(textBlock)
textBlocks.append(rest)
#For each block, invoke Polly API, which will transform text into audio
polly = boto3.client('polly')
for textBlock in textBlocks:
response = polly.synthesize_speech(
OutputFormat='mp3',
Text = textBlock,
VoiceId = voice
)

#Save the audio stream returned by Amazon Polly on Lambda's temp
# directory. If there are multiple text blocks, the audio stream
# will be combined into a single file.
if "AudioStream" in response:
with closing(response["AudioStream"]) as stream:
output = os.path.join("/tmp/", postId)
with open(output, "a") as file:
file.write(stream.read())
s3 = boto3.client('s3')
s3.upload_file('/tmp/' + postId,
os.environ['BUCKET_NAME'],
postId + ".mp3")
s3.put_object_acl(ACL='public-read',
Bucket=os.environ['BUCKET_NAME'],
Key= postId + ".mp3")
location = s3.get_bucket_location(Bucket=os.environ['BUCKET_NAME'])
region = location['LocationConstraint']

if region is None:
url_begining = "https://s3.amazonaws.com/"
else:
url_begining = "https://s3-" + str(region) + ".amazonaws.com/"

url = url_begining
+ str(os.environ['BUCKET_NAME'])
+ "/"
+ str(postId)
+ ".mp3"
#Updating the item in DynamoDB
response = table.update_item(
Key={'id':postId},
UpdateExpression=
"SET #statusAtt = :statusValue, #urlAtt = :urlValue",
ExpressionAttributeValues=
{':statusValue': 'UPDATED', ':urlValue': url},
ExpressionAttributeNames=
{'#statusAtt': 'status', '#urlAtt': 'url'},
)

return

Use the following environment variables and values:

  • DB_TABLE_NAME‚Ää‚ÄĒ‚ÄäThe name of the DynamoDB table (in our case, it‚Äôs posts )
  • BUCKET_NAME‚Ää‚ÄĒ‚ÄäThe name of the S3 bucket that we created to store MP3 files

Update the execution time settings for this lambda function.


Go ahead and retest the PostReader_NewPost function. It will add an entry to your database table and a mp3 file to the S3 bucket.

Create a Lambda function to get Audio

Now, we just need to create another lambda function, PostReader_GetPost that retrieves information from the database.

Get post lambda function
import boto3
import os
from boto3.dynamodb.conditions import Key, Attr
def lambda_handler(event, context):

postId = event["postId"]

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['DB_TABLE_NAME'])

if postId=="*":
items = table.scan()
else:
items = table.query(
KeyConditionExpression=Key('id').eq(postId)
)

return items["Items"]

This function needs just one environment variable ie. DB_TABLE_NAME.

To test function add a New Test as below:

{   "postId": "*" }

Exposing the Lambda function as an API

Next, we need to expose our application logic as a RESTful web service. Choose to Create API option in the API Gateway console to get started.

Fill in the details to create an API

After the API is created, choose Create Method from the menu.


The POST method invokes the PostReader_NewPost Lambda function. For the GET method, our API invokes the PostReader_GetPost Lambda function.

Next, enable CORS to enable calling these methods from a different domain.

Enable CORS

Now, modify the GET method to add a postId query param to it.


The lambda function expects a JSON input so we need to add a mapping in the Integration Request section.


Similarly, you can configure your POST method to accept a JSON input. Go to the Models section and create a new model.


{
"$schema" : "http://json-schema.org/draft-04/schema#",
"title" : "AloudStory",
"type" : "object",
"properties" : {
"voice" : { "type" : "string" },
"text" : { "type" : "string" }
}
}

Deploying the API

Now that you have configured the methods, go ahead and deploy it.


Choose a deployment stage

Choose a deployment stage

That’s it your APIs are up and running. The AWS console will show you the invocation URL for it.


Make sure you give this post 50 claps and follow me if you enjoyed this post and want to see more!

Web Hosting using PHP and MySQL on AWS


It’s was a Sunday and I was bored. Then I came across a custom URL shortener service, YOURLS that I had previously used in my college days. It was very simple to set it up with my GoDaddy shared web hosting. I no longer have a web hosting package on GoDaddy so I decided to try out AWS cloud instead.

AWS is cheap and easy to get started. Our goal is to get our own custom URL shortener service up and running on http://aloudapp.in.

Before we deep dive into the details of setting up everything, here are our broader goals.

  • Setup an EC2 instance for cloud hosting
  • Setup a hosting zone and configure DNS
  • Setup a load balancer for the EC2 instance.
  • Install a LAMP web server on the EC2 instance.
  • Configure YOURLS on the web server.

This article will cover everything up to setting up the LAMP web server.

Create an EC2 instance

An EC2 instance is a virtual server in Amazon’s Elastic Compute Cloud (EC2) for running applications on the Amazon Web Services (AWS) infrastructure.

Launch an EC2 instance

Click on Launch Instance to create a new instance.

Create an EC2 instance

Run a Linux machine

Choose Amazon Linux from the listed options for machine images.

Choose Amazon Linux image

Choose an Instance Type

We will go for a t2.micro free instance for the purpose of this example.

Choose t2.micro free instance

Review your EC2 instance

All done! Review your settings.

Review your settings

Create Key Pair

Create a public-private key pair if you desire. This is an optional step but we recommend that you create a key pair and download it. We will be using it later on in the article to SSH into our EC2 instance.

View Launch Status

Good Going! Your instance is up and running.


Edit Security Group

Edit security group settings to allow SSH inbound traffic from your IP address.

Edit Inbound Traffic for your instance

Add a custom rule

Whitelist your IP

Domain Mapping

Next, you need to create a Hosting Zone where you would configure your DNS settings for the domain name. Here are the steps.

Create a Hosting zone

Click on Create Hosting Zone to get started.

Create a hosted zone

Setup Your Domain

Fill in your Domain Name to create a new hosted zone.

Put in your domain name

Edit Namespace for your Domain

Once you have created a Hosted zone, you will be able to see associated namespace records for it. Edit these NS records for your domain. I purchased the domain from GoDaddy, so I had to go and edit these records in DNS settings for the domain on GoDaddy’s admin panel.

Edit namespace on GoDaddy

Add a A Record

Coming back to your Hosted Zone, create a new A record. Leave the Name field empty if you don’t want to configure just for a particular subdomain.


That’s it. Your Hosted Zone is now set up. You can also set up a subdomain in 4 easy steps by following this step by step guide.

View at Medium.com

Create a Load Balancer

Next, you need to create a Load Balancer for your EC2 instance. As described by Wikipedia,

In computing, load balancing improves the distribution of workloads across multiple computing resources, such as computers, a computer cluster, network links, central processing units, or disk drives.

Create a Classic Load Balancer

Choose a Classic Load balancer which is used for HTTP, HTTPS and TCP traffic.

Click on Create Load Balancer

Choose a Classic Load Balancer

Follow the wizard to complete the Load Balancer settings.

Define Load Balancer Properties

Define its name and protocol as depicted in the section below.

Load balancer settings

Assign Security Groups

Assign security groups to the load balancer. Create a new security group for your load balancer that allows traffic from any IP address.

Create a new Security group for load balancer

Set Load balancer’s security group to the newly created one.


Setup Health Checks

Setup health checks. Again you and go ahead with the default options as of now. We can revisit these settings later.

Default health check settings

Map with an EC2 instance

Choose the EC2 instance that you created earlier for the load balancer.

Map with your EC2 instance

Create tags

Tags are optional and help to identify your resources.

Optional tags

All done! Your load balancer is now set up.

Edit Inbound Rules for EC2 instance

Go back to your EC2 instance and add a new inbound rule for it. This will allow all traffic from the load balancer.

Edit security rules for EC2

Now your EC2 instance, hosting zone, and load balancer are all setup. We will go ahead and install a LAMP web server on our EC2 instance.

Connect to your Instance

  • Open an SSH client
  • Locate your private key file and provide permissions
chmod 400 amazon_ec2_key.pem
  • Connect to your EC2 instance
ssh -i "amazon_ec2_key.pem" ec2-user@ec2-13-127-42-0.ap-south-1.compute.amazonaws.com

Install a LAMP webserver

  • Check if software packages are up to date.
sudo yum update -y
  • Install the packages for php and mysql.
sudo yum install -y httpd24 php70 mysql56-server php70-mysqlnd
  • Start the http server
sudo service httpd start
  • Create a health.html file in cd/var/www/html¬†. Put any content in the file and save it.
nano health.html
  • Edit health check settings for your load balancer.

Change health check settings

Now you should be able to see the test page when you hit the domain.

http://aloudapp.in


Set File Permissions for your User

Run the following commands to set file permissions.

sudo usermod -a -G apache ec2-user
sudo chown -R ec2-user:apache /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} ;
find /var/www -type f -exec sudo chmod 0664 {} ;

Run these commands to give permissions to your user

Test your LAMP server

Create a PHP file in Apache document root.

echo "<?php phpinfo(); ?>" > /var/www/html/phpinfo.php

Open http://aloudapp.in/phpinfo.php to test it.

Secure the MySQL server

  • Start MySQL server.
sudo service mysqld start
  • Run mysql_secure_installation and set root password, remove anonymous user accounts, disable remote root login, remove the test database, reload the privilege tables.
sudo mysql_secure_installation

Install phpMyAdmin

Run the following commands to setup phpMyAdmin.

sudo yum install php70-mbstring.x86_64 php70-zip.x86_64 -y
sudo service httpd restart
cd /var/www/html
wget https://www.phpmyadmin.net/downloads/phpMyAdmin-latest-all-languages.tar.gz
tar -xvzf phpMyAdmin-latest-all-languages.tar.gz
mv phpMyAdmin-4.7.6-all-languages phpMyAdmin
sudo service mysqld start

Special thanks to Chetan Gulati who helped me set it up.

All done! Now your web server is up and running. We will cover the configuration of YOURLS on this web server in the next story.


Make sure you give this post 50 claps and follow me if you enjoyed this post and want to see more!

Bitnami