Launching a Rocket REST API on AWS
A step-by-step process using the web framework for Rust
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!
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”:
Once the EC2 “Launch an instance” menu is in view, name your instance and select the Amazon Linux 2 AMI:
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.
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.
Lastly, skip the advanced details and click “Launch instance”.
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.
Then add the following inbound rules:
and the following outbound rules:
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:
Once in the “Change security groups” menu, remove the default security group and add the security group we just created. Then, hit save.
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.
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:
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:
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:
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:
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.
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!