Deploying Streamlit on EC2, with nginx for external HTTP requests
November 20, 2024
Today I'm writing a description of how I deployed Streamlit version 1.40.1 on Amazon AWS EC2, made my process run in the background using systemd and nohup, and set up nginx to forward requests to port 80 to my Streamlit app.
This is in preparation to setting up a subdomain for my app, something I won't be covering in this post however.
Amazon AWS EC2 instance
I won't get into too much detail on how to set up an EC2 instance. What I will say, is that I ended up needing more than 10GB of disk space, with an Ubuntu image and a pretty basic Streamlit app.
I wanted the app to hibernate when it's not in use, and in order to enable hibernation, I had to enable encryption of the disk.
You should generate an ssh key, or use an existing key you might have created on AWS before. With this key, you can later ssh to your instance.
Configure the inbound rules for the security group of your instance to have the following rules:
type: HTTP
protocol: TCP
Port range: 80
Source: Anywhere-IPv4
type: SSH
protocol: TCP
Port range: 22
Source: Anywhere-IPv4
type: Custom TCP
protocol: TCP
Port range: 8501
Source: Anywhere-IPv4
type: HTTPS
protocol: TCP
Port range: 443
Source: Anywhere-IPv4
You will find the Public IPv4 address in your instance details after the instance has been created. With the ssh key .pem file created during the setup of your instance, the SSH port 22 allowed, and your instance ip address, you can login to your instance with ssh:
ssh -i <path to your .pem file> ubuntu@<your ec2 instance ip>
Setting up your project on the EC2 instance
Login with ssh to your instance, clone your project from GitHub, then install the python3-venv package and create a virtual environment, in which you can install the requirements of your Streamlit app.
git clone <the web url for your Streamlit project's GitHub repo>
sudo apt update
sudo apt install python3-venv
cd <your project folder>
python3 -m venv environment
source environment/bin/activate
pip3 install -r requirements.txt
Make the Streamlit app run in the background at startup
First, we'll create a launcher script, run.sh, where we use the 'nohup' command to run your Streamlit process in the background:
#!/bin/bash
cd /home/ubuntu/<your project folder>
source environment/bin/activate
nohup streamlit run main.py
Then we'll create a systemd .service file in /etc/systemd/system/<your project name>.service:
[Unit]
Description=Streamlit Service
After=network.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/<your project folder>
ExecStart=/bin/bash /home/ubuntu/<your project folder>/run.sh
[Install]
WantedBy=multi-user.target
After which we'll reload systemd configuration to include your new .service file, launch your service and enable it for startup:
sudo systemctl daemon-reload
sudo systemctl start <your project name>
sudo systemctl enable <your project name>
You'll want to verify that the process is loaded and running:
systemctl status <your project name>
Nginx installation and config
Let's install nginx on the system and make it launch on startup:
sudo apt install nginx
sudo systemctl start nginx
sudo systemctl enable nginx
We'll add some configuration:
sudo nano /etc/nginx/sites-available/default
Make this the content of the file:
server {
listen 80;
server_name <your EC2 IP address>;
location / {
proxy_pass http://localhost:8501; # Replace the port number with your Streamlit's port
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support for Streamlit
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Then restart Nginx:
sudo systemctl restart nginx
Hope you got your app running with these instructions!