Run Python applications with uWSGI
This article explains how to run Python apps on Nine's managed servers with uWSGI in userspace.
If you want to run your application in a container, please refer to Podman as a Managed Service.
A container keeps your application consistent across environments. Containers also make dependency management easier and help you scale your application by isolating it from other processes on the system.
Requirements
For the example below, we assume that your application supports wsgi. If you use Django or Flask, this is already the case.
1. Install Python
Your managed server already comes with Python pre-installed, but the available version is fixed based on the Ubuntu version.
Ubuntu | Python |
---|---|
18.04 (Bionic) | 3.6.* |
20.04 (Focal) | 3.8.* |
22.04 (Jammy) | 3.10.* |
If you require a different version, we recommend the use of pyenv
.
If this is your first pyenv
installation on this managed server, please reach out to us at so we can install all required dependencies.
-
Execute their install script with the following command:
curl https://pyenv.run | bash
-
Run the following command to extend your
~/.bashrc
:cat << 'EOF' >> ~/.bashrc
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init --path)"
eval "$(pyenv virtualenv-init -)"
EOF -
Reload your shell:
source .bashrc
-
Install the desired Python version:
pyenv install 3 # install latest v3
pyenv global 3 # set as default
2. Setup Virtual Environment (venv
)
To separate your Python applications from each other, it's best practice to use virtual environments or short, venv
.
-
Create and activate a new environment:
mkdir ~/exampleapp/ && cd ~/exampleapp/
python -m venv .venv -
Install uWSGI inside the virtual environment:
source .venv/bin/activate
(.venv) pip install uwsgi
3. Application Deployment
Deploying your application is different for each project. With Django, for example, you'll need to install the Django package, then upload all files to the server and install the dependencies:
-
Install the Django CLI:
(.venv) pip install Django
-
Copy the application files to your server:
rsync -Hav --delete --exclude='node_modules/*' --exclude='logs/*' --exclude='.git/*' --exclude='.venv/*' ./local_project www-data@server.nine.ch:exampleapp/
-
Install your dependencies:
(.venv) pip install -r requirements.txt
4. Run Application as a Service
To ensure a service keeps running after an application crash or system reboot, we highly recommend using a systemd user service. The configuration for such a systemd unit depends on your application. The above example assumes that you’re running a Django app.
-
Create the service file in
~/.config/systemd/user/exampleapp.service
:[Unit]
Description=exampleapp
[Service]
WorkingDirectory=%h/exampleapp
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
Environment=PYTHON_VERSION=3.9.11
Environment=PATH=%h/.pyenv/versions/$PYTHON_VERSION/bin:$PATH
EnvironmentFile=%h/exampleapp/.env
ExecStart=%h/exampleapp/.venv/bin/uwsgi \
--module=exampleapp.wsgi:application \
--master \
--http=127.0.0.1:3000 \
--enable-threads \
--threads=2 \
--processes=4 \
--harakiri=20 \
--max-requests=5000 \
--vacuum \
--home=%h/exampleapp/.venv
[Install]
WantedBy=default.targetThese settings will vary depending on your system and application. We suggest consulting the official documentation for the configuration parameters and best practices.
-
Start the service:
touch ~/exampleapp/.env # ensure environment file exists
systemctl --user daemon-reload
systemctl --user enable exampleapp.service
systemctl --user start exampleapp.service
systemctl --user status exampleapp.service
Troubleshooting
- Ensure the
.bashrc
is sourced properly. - Check if the service is running
systemctl --user status app.service
- Check the logs using
journalctl --user -f
.
More information about how to use Systemd is available in the following support article.
5. Configure Webserver
This makes you application should be accessible via http
. To add https
support, please use the proxy_letsencrypt_https
as documented in nine-manage-vhosts with Let's Encrypt.
The application is now running on a local port. To reach the application via http
and https
, the webserver needs to proxy these requests to the local port.
There are already two nine-manage-vhost templates for this use case pre-installed on your managed server: proxy
and proxy_letsencrypt
.
Create a new vHost and set the local port of the applications via template variable:
$ sudo nine-manage-vhosts virtual-host create example.com --template proxy --template-variable PROXYPORT=3000 --webroot ~/exampleapp/static
Virtual Host created: example.com
example.com
===========
DOMAIN: example.com
USER: www-data
WEBROOT: /home/www-data/exampleapp/static
TEMPLATE: proxy
TEMPLATE VARIABLES: PROXYPORT
3000
ALIASES: www.example.com
example.com.server.nine.ch
You can now test the connection by accessing http://example.com.server.nine.ch
.