Deploying a bare-bones Python webserver
So you've prototyped a nifty Python webapp that serves a pre-built SPA client. You want to deploy it, but how?
Having done this a few times, I now have my shortest recipe to deploy a Python webapp to a bare-bones Ubuntu VM.
-
Spin up the smallest shared VM (CPU-only) for $5/month from vendors such as linode or vultr (my current one). Choose Ubuntu for ease-of-install.
-
Create a new super-user account. From your vendor, you'll get an IP.NUMBER and a root password. Ssh into your VM as root
ssh root@IP.NUMBER
Once in your VM, create the user account:
adduser myusername usermod -aG sudo myusername
Restart the VM to allow sudo to propagate, and then log in as the new super-user.
ssh myusername@IP.NUMBER
-
At this point, you'll probably want to setup ssh-keys to simplify login and file copying by skipping passwords. If you've setup
~/.ssh/id_rsa.pub
then on your local machine, you can send the keys to the VM:ssh-copy-id -i ~/.ssh/id_rsa.pub myusername@IP.NUMBER
-
Copy your webserver over to the VM. You can use sftp, rsync, cyberduck or transmit.
-
Once your files are transferred, a nice way to interact with your VM is through the Remote Explorer in Visual Studio Code. It allows editing and file management with an integrated terminal. The best feature is AUTOMATIC PORT MAPPINGS where VS Code will open your local webbrowser directly from the VM terminal with port mapping. But if you're happy with sftp and ssh, that's fine too.
-
Ubuntu comes with python3 installed (Ubuntu23 -> python3.11) but missing a few crucial libraries. You'll want to install venv to manage a nice Python environment:
sudo apt install python3.11-venv
-
Hopefully your Python web-server is stored in a directory, say
/home/myusername/webapp
with eitherpyproject.toml
orsetup.py
specifying all your dependencies and python tooling. Let's install them into a Python.venv
sub-directory:python3 -m venv .venv source .venv/bin/activate pip3 install -e .
This will provide a new
python3
that has access to the environment with all your depedencies installed. The location of thispython3
is:/home/myusername/webapp/.venv/bin/python3
-
Check that your webserver is working on the correct port (let's say 9023). If you're on VSCode, open the browser on the port directly and check the SPA client.
-
Now let's set up a background task manager
supervisord
for your webapp where the logs will be written in the directory/var/log/webapp
sudo apt install supervisor mkdir /var/log/webapp
Create a supervsior task for our webapp
/etc/supervisor/conf.d/webapp.conf
. In our case the python command iscli.py
in the~/webapp/server
directory:[program:webapp] directory=/home/myusername/webapp/server command=/home/myusername/webapp/.venv/bin/python3 cli.py run --port 9023 autostart=true user=myusername autorestart=true stopasgroup=true killasgroup=true stderr_logfile=/var/log/webapp/errors stdout_logfile=/var/log/webapp/logs
To make it easy to edit this file, let's chown it:
sudo chown myusername /etc/supervisor/conf.d/webapp.conf
Restart supervisor with our new
webapp.conf
job:sudo service supervisor restart sudo supervisorctl status webapp
-
Install
nginx
to simply pass on all external http requests on port 80 directly to our port 9023 (or whatever port you want):sudo apt install nginx
Open the default Ubuntu firewall for http access:
sudo ufw allow 'Nginx HTTP'
Create a server block for nginx
/etc/nginx/sites-enabled/webapp
that will accept data from any url on port 80 (http) and send the data to port 9023:server { listen 80; server_name ~^(.+)$; location / { proxy_pass http://0.0.0.0:9023; } }
Take control of the file for easier editing:
sudo chown myusername /etc/nginx/sites-enabled/fastapi
Restart nginx to expose our webapp:
sudo systemctl restart nginx
-
Check your webapp on a browser from
http://IP.NUMBER
.