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.NUMBEROnce in your VM, create the user account:
adduser myusername usermod -aG sudo myusernameRestart 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.pubthen 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/webappwith eitherpyproject.tomlorsetup.pyspecifying all your dependencies and python tooling. Let's install them into a Python.venvsub-directory:python3 -m venv .venv source .venv/bin/activate pip3 install -e .This will provide a new
python3that has access to the environment with all your depedencies installed. The location of thispython3is:/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
supervisordfor your webapp where the logs will be written in the directory/var/log/webappsudo apt install supervisor mkdir /var/log/webappCreate a supervsior task for our webapp
/etc/supervisor/conf.d/webapp.conf. In our case the python command iscli.pyin the~/webapp/serverdirectory:[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/logsTo make it easy to edit this file, let's chown it:
sudo chown myusername /etc/supervisor/conf.d/webapp.confRestart supervisor with our new
webapp.confjob:sudo service supervisor restart sudo supervisorctl status webapp -
Install
nginxto simply pass on all external http requests on port 80 directly to our port 9023 (or whatever port you want):sudo apt install nginxOpen the default Ubuntu firewall for http access:
sudo ufw allow 'Nginx HTTP'Create a server block for nginx
/etc/nginx/sites-enabled/webappthat 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/fastapiRestart nginx to expose our webapp:
sudo systemctl restart nginx -
Check your webapp on a browser from
http://IP.NUMBER.