Launching a Rocket REST API on AWS

A step-by-step process using the web framework for Rust

Caleb Bender
Better Programming

--

Photo by Hello I'm Nik on Unsplash

Rocket.rs is the most well-known web framework for Rust that allows developers to easily create performant and type-safe web applications. In this article, we will walk through how to deploy your very own Rocket REST API onto AWS!

Prerequisites

Before I walk you through the steps to launch your very own Rocket REST API onto AWS, you will need a few things:

  • A basic understanding of the Rust programming language
  • A basic understanding of shell commands on Linux
  • An AWS account
  • A basic understanding of AWS Elastic Compute Cloud (EC2) and networking

What Are We Deploying?

In this tutorial, we are going to deploy a very simple Rocket REST API with two routes: / and /sort. The first route is the index and upon a GET request will send the text “Hello from Rocket REST API!”. The second route is a POST route that given an unsorted array of integers and a sort order, the app will return the correctly sorted array. Here is an example of a valid POST request sent to /sort:

request JSON body: {
"array": [2,6,1,5,3,4],
"sort_order": "descending"
}

response JSON: {
"sorted_array": [6,5,4,3,2,1]
}

The array must be of integers and the sort order can either be “ascending” or “descending”. If an invalid request is made, this response is sent back:

request JSON body: {
"array": [4.5, 1.2, 6.56, 3.709],
"sort_order": "random"
}

response JSON: {
"message": "The JSON posted is invalid. Make sure the 'array' field is an array of integers and 'sort_order' is either 'ascending' or 'descending'."
}

The app is extremely simple for good reason; the steps you will follow below to deploy this app can be applied to any Rocket app no matter the number of features or complexity.

Now let’s lift off!

A picture of a rocket launching into the sky
Source: https://img.freepik.com/premium-photo/take-off-space-rocket-background-blue-sky-sun-elements-this-image-were-furnished-by-nasa_496756-8629.jpg?w=2000

Launching Our EC2 Instance

First, login to your AWS account. You’ll need an account that has full access to EC2 to continue. Then, select the region you want to launch the EC2 instance in. Finally, go to the EC2 console and click “Launch instance”:

Picture of EC2 dashboard

Once the EC2 “Launch an instance” menu is in view, name your instance and select the Amazon Linux 2 AMI:

Picture of EC2 “Launch an instance” menu

Also, make sure to leave the number of instances as 1. Next, select the t2.micro instance type which is free tier eligible and one of the cheapest instance types. Also, we will be connecting to our EC2 via SSH, so either create/select a key pair or use EC2 instance connect in later steps.

Picture of instance type selection and key pair selection on “Launch an instance” menu

For now, select the default security group (we’ll create a custom one after we launch the EC2 instance). Also, leave the Elastic Block Store (EBS) set to the defaults of 8 GB of gp2 SSD memory.

network and storage settings in “Launch an instance” menu

Lastly, skip the advanced details and click “Launch instance”.

Picture of “Launch an instance” menu

Now navigate to the “Instances” menu on the left-hand panel. After a moment, you should see that your EC2 instance is running.

Using a Better Security Group

Now let’s create a security group that is more restrictive than the default security group we assigned it. Head to “Security Groups” under “Network & Security” on the left panel. Then click on “Create security group” to create a new group for our EC2 instance. Once you get to the “Create security group” menu, give the group a name and description.

Picture of name and description fields in “Create security group” menu

Then add the following inbound rules:

Inbound rules for Rocket security group

and the following outbound rules:

Outbound rules for Rocket security group

Then, create the security group! After, it has successfully been created, navigate to the “Instances” menu on the left panel and select your instance. Then under actions, change the security groups:

Picture of “Change security groups” setting

Once in the “Change security groups” menu, remove the default security group and add the security group we just created. Then, hit save.

Picture of “Change security groups” menu

Accessing Our Instance Via SSH

In order to set up our instance to run the Rocket app, we need to connect to it via SSH. Head to the instances menu, select the instance, and click connect.

Picture of connect button in EC2 instances menu

If you added an SSH key pair for the instance you can connect through the command line on your machine. Otherwise, use instance connect inside your browser.

Once you have connected to your EC2 instance, you should see the following:

Picture of EC2 access via SSH

Installing Dependencies

First things first, we’ll need to install git to clone the repository. Run the following command using the yum package manager:

~]$ sudo yum install git -y 

Once git has installed, also install gcc using yum. We will need this to build the rust binary.

~]$ sudo yum install gcc -y

Finally, you’ll need to install Rust and Cargo (Rust’s package manager). Run the following command to install Rust and Cargo:

~]$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Enter 1 for the default installation, no need to complicate things. Then run this command to refresh the shell so it recognizes those commands/binaries:

~]$ exec bash

Great! Now you’re ready to clone the repository!

Cloning the Rocket Project

Run the following command to clone the git repository into the /home/ec2-user directory:

~]$ git clone https://github.com/caleb-bender/rocket-rest-api-demo.git

Then, cd into the project.

~]$ cd rocket-rest-api-demo

Building the Project for Production

Now we need to build the Rocket app for production in order to run it on our instance. Run the following command in your shell:

~]$ cargo build --release

This command will take a while because all crates have to be fetched and built. Once the command finishes, we need to do one last thing before we run the Rocket app.

Rocket uses a .toml file for configuring different environments (i.e., default, debug, release).

This allows us to specify things like the port we want to run the app on and the scope of the address (public or private). In order to configure the Rocket app properly, create a Rocket.toml file in the /home/ec2-user/rocket-rest-api-demo directory and add the following:

[debug]
port = 8000

[release]
address = "0.0.0.0"
port = 8000

The address field is very important, as by default Rocket will run locally. By specifying "0.0.0.0" , we tell Rocket we want the app to be able to be accessed publicly. For more info about Rocket.toml files, go here. Now, run the following command to launch Rocket!

~]$ cargo run --release

If the command executed successfully, you should see the following in your terminal:

Picture of text in terminal stating that Rocket is running

Open a tab/window in your browser and paste either the public IPv4 address or the public IPv4 DNS in the browser url field. Also make sure the port is set to 8000. Here is an example:

http://13.57.226.189:8000/

Press enter and you should then see the following message:

A picture of the message from the Rocket app on the route “/”

Additionally, if you have Postman or curl, you can send a POST request to the /sort route. Here is a curl command that will get you a response back on your machine:

~]$ curl --header "Content-Type: application/json" \
--request POST \
--data '{"array":[5,6,1,3,2,4],"sort_order":"ascending"}' \
http://13.57.226.189:8000/sort

Here’s the response from the above curl request:

Picture of response from curl request

This is cool and all, but once we close the connection to the EC2 instance via SSH, the Rocket app will stop. How can we get this app to run in the background, even when we are not connected to the instance?

Creating a systemd service

Systemd is a service manager on Linux that allows us to create/run/manage different services. In order to run our Rocket app as a service, we need to create a systemd service file.

Once we do this and configure it, we can keep our Rocket app running and we can even have it automatically restart when we reboot our instance. To get started, run the following command:

~]$ sudo touch /etc/systemd/system/Rocket.service

Now use vim (prefix with sudo) to open the file and paste the following text inside the file:

[Unit]
Description=Rocket
After=network-online.target

[Service]
ExecStart=/home/ec2-user/.cargo/bin/cargo run --manifest-path /home/ec2-user/rocket-rest-api-demo/Cargo.toml --release
KillSignal=SIGINT
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=Rocket
User=ec2-user
Environment="ROCKET_ADDRESS=0.0.0.0"

Let’s briefly go through the contents of the file. The After field below [Unit] tells systemd that we want the network up and running before this service can be started.

In the [Service] section, we specify the command to be executed when we start the service. ExecStart is essentially executing cargo run --release but with the absolute paths of the command and the location of the Cargo.toml file.

In the Environment field, we make the Rocket address global. We must do this because systemd is unaware of our Rocket.toml file that we created earlier. For more information on systemd, go here. Now, save and exit vim.

Running our Rocket systemd service

Before we can run our Rocket app using systemd, we must refresh the daemon so that it recognizes the service we just created. To do this, run the following command:

~]$ sudo systemctl daemon-reload

Now run this command to view the status of our Rocket service:

~]$ sudo systemctl status Rocket

The output should say that the service is loaded but inactive. To start the service, run the following command:

~]$ sudo systemctl start Rocket

Now if you check the status again, it should show it as running! To prove that your app is running in the background, terminate your SSH connection to the instance and try to access the / path in your browser (remember it’s running on port 8000). You should still see the greeting from our Rocket app!

Additional Service Commands

Connect back to your EC2 instance via SSH and run the following command:

~]$ sudo systemctl enable Rocket

This tells systemd to automatically start Rocket on boot along with any other services it manages. This is useful if we needed to bring our EC2 instance offline temporarily and then restart it.

To stop the service from starting on boot, run the following:

~]$ sudo systemctl disable Rocket

This will tell systemd that we don’t want Rocket starting automatically when the instance boots. To stop the service from running altogether, run the following:

~]$ sudo systemctl stop Rocket

This will terminate our Rocket app, and this can be verified by checking the status of our service once more.

Cleaning Up Our Instance

In order to prevent incurring excessive charges, you will want to either stop or terminate your EC2 instance eventually. Stopping it is like turning a computer off; you can start the instance again and everything we saved still exists.

When we stop the instance, only the EBS volume will incur charges at an extremely slow rate. However, exercise caution when terminating the instance, as once you do this, everything we set up in this guide will be lost, because both the instance and the EBS volume will no longer exist.

To stop/terminate the instance, go to the instances menu, select your instance, and under “Instance state” select the relevant option.

Picture of “instance state” dropdown for EC2 instance

Closing Notes

The purpose of this tutorial was to give you a step-by-step process on how to deploy a Rocket Rust app onto AWS. The method we chose is incomplete for a real production-ready app, as an API is typically accessed via HTTP/HTTPS on ports 80/443 respectively, and not on port 8000.

This falls outside the scope of this tutorial, however, if you were to deploy a real Rocket production app, you would want to either set up a load balancer or a reverse proxy using nginx so that end users can access the app from standard HTTP ports.

The Rocket app can still run on port 8000, but having a load balancer or nginx forward HTTP requests behind the scenes would be best. Moreover, creating an Auto Scaling group for our EC2 instance would also be beneficial, as it would better scale with fluctuations in network traffic.

I hope you found this guide helpful and thank you for reading!

--

--