Hoc blog est pessimus

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!