Skip to main content

Run Python applications with uWSGI

This article explains how to run Python apps on Nine's managed servers with uWSGI in userspace.

Container Deployment

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.

UbuntuPython
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.

Dependencies

If this is your first pyenv installation on this managed server, please reach out to us at so we can install all required dependencies.

  1. Execute their install script with the following command:

    curl https://pyenv.run | bash
  2. 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
  3. Reload your shell:

    source .bashrc
  4. 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.

  1. Create and activate a new environment:

    mkdir ~/exampleapp/ && cd ~/exampleapp/
    python -m venv .venv
  2. 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:

  1. Install the Django CLI:

    (.venv) pip install Django
  2. 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/
  3. 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.

  1. 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.target

    These settings will vary depending on your system and application. We suggest consulting the official documentation for the configuration parameters and best practices.

  2. 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

  1. Ensure the .bashrc is sourced properly.
  2. Check if the service is running systemctl --user status app.service
  3. Check the logs using journalctl --user -f.

More information about how to use Systemd is available in the following support article.

5. Configure Webserver

https

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.