Running Flask, Gunicorn, and Celery

07/02/2024

How I set up a headless Ubuntu VPS for hosting Python apps with Nginix, Gunicorn, Flask and Celery:

Tutorials I Followed:

Debugging:

sudo nginx -t make sure Nginx configuration is valid

sudo ufw status see which ports are open in the firewall

sudo systemctl status [SERVICE] check the status of a service

sudo systemctl daemon-reload sudo systemctl restart [SERVICE] restart a service

More systemctl commands:

sudo systemctl start sudo systemctl stop

sudo systemctl enable sudo systemctl disable

1. Testing Flask

cd /var/www go to the web root

mkdir celeryflask cd celeryflask create and go into a new project directory

python3 -m venv celeryflask-env create a Python virtual environment in a new directory 'celeryflask-env'

source celeryflask-env/bin/activate activate the virtual environment

pip install wheel pip install flask gunicorn install Wheel, Flask & Gunicorn to the virtual environment

vim app.py create a file for the Flask application

sudo ufw status sudo ufw allow 5005 make sure your chosen port is open, open the port if necessary

/var/www/celeryflask/app.py
from flask import Flask app = Flask(__name__) @app.route("/") def hello (): return "Hello There!" if __name__ == "__main__": app.run(host='0.0.0.0', port=5005, debug=True)

python app.py run the Flask app with the built-in development server

-test the website-

ctrl-c quit the dev server

deactivate deactivate the virtual environment

2. Installing Redis to the Server

Follow the instructions on the Redis site

Note: when running Redis but not as a service, you have to specify the config file to load.
Redis comes with its own systemctl service file.

Redis file locations:

/usr/bin/redis-server Redis binary

/etc/redis/redis.conf Redis config file

/etc/init.d/redis-service Redis service file

sudo systemctl start redis-server.service start Redis

sudo systemctl enable redis-server.service set Redis to run at boot

redis-cli ping returns PONG if Redis is up & running

3. Testing Celery

source celeryflask-env/bin/activate activate the Python virtual environment

pip install redis pip install celery install redis-py (the Redis Python client package) and Celery to the virtual environment

vim tasks.py create a file for the Celery application

/var/www/celeryflask/tasks.py
from celery import Celery app = Celery('tasks', backend='redis://localhost', broker='redis://localhost') @app.task def add(x, y): return x + y

tmux new -s celery-sesh start a new tmux session named celery-sesh

source celeryflask-env/bin/activate activate the virtual environment within the tmux session

celery -A tasks worker --loglevel INFO start a Celery worker on the Celery app 'tasks'

ctrl-b d detach from the tmux session

Other tmux commands:

tmux a -t celery-sesh reattach to tmux session celery-sesh

tmux ls list tmux sessions

Make sure celery is working:

python launch the python interpreter in interactive mode

>>> from tasks import add >>> result = add.delay(4, 4) >>> result.ready() >>> result.get(timeout=1) >>> exit()

tmux kill-server kill all tmux sessions

deactivate deactivate the virtual environment

4. Testing Gunicorn

source celeryflask-env/bin/activate activate the virtual environment

vim wsgi.py create the wsgi entry point

/var/www/celeryflask/wsgi.py
from app import app from app.py import the app variable if __name__ == "__main__": app.run()

gunicorn --bind 0.0.0.0:5005 wsgi:app run Gunicorn in the foreground

-test the website-

ctrl-c exit Gunicorn

deactivate deactivate virtual environment

5. Running Celery as a Service

cd /etc/systemd/system

sudo vim celeryflask-celery.service

/etc/systemd/system/celeryflask-celery.service
[Unit] Description=Celery Service for celeryflask After=network.target [Service] User=casey Group=www-data WorkingDirectory=/var/www/celeryflask Environment="PATH=/var/www/celeryflask/celeryflask-env/bin" ExecStart=/var/www/celeryflask/celeryflask-env/bin/celery -A tasks worker -f celery.log [Install] WantedBy=multi-user.target

sudo systemctl daemon-reload

sudo systemctl start celeryflask-celery

cd /var/www/celeryflask

source celeryflask-env/bin/activate

python

Make sure celery is working

>>> from tasks import add >>> result = add.delay(4, 4) >>> result.ready() >>> result.get(timeout=1) >>> exit()

deactivate

sudo systemctl enable celeryflask-celery

6. Running Gunicorn as a Service

cd /etc/systemd/system

sudo vim celeryflask-gunicorn.service

/etc/systemd/system/celeryflask-gunicorn.service
[Unit] Description=Gunicorn Service for celeryflask After=network.target [Service] User=casey Group=www-data WorkingDirectory=/var/www/celeryflask Environment="PATH=/var/www/celeryflask/celeryflask-env/bin" ExecStart=/var/www/celeryflask/celeryflask-env/bin/gunicorn --reload --log-file gunicorn.log --bind 0.0.0.0:5005 wsgi:app [Install] WantedBy=multi-user.target

sudo systemctl daemon-reload

sudo systemctl start celeryflask-gunicorn

-test the website-

sudo systemctl enable celeryflask-gunicorn

7. Using Nginx as a reverse proxy server for Gunicorn

1. Bind Gunicorn to a socket

cd /etc/systemd/system

sudo vim celeryflask-gunicorn.service

Edit the service file to bind gunicorn to a socket instead of directly to the ip / port.
The sock file will be created the first time the service runs

ExecStart=/var/www/celeryflask/celeryflask-env/bin/gunicorn --reload --log-file gunicorn.log --bind unix:celerytut2.sock -m 007 wsgi:app

sudo systemctl daemon-reload

sudo systemctl restart celeryflask-gunicorn

2. Handle the request with Nginx as a reverse proxy server

cd /etc/nginx/sites-available

sudo vim celeryflask

/etc/nginx/sites-available/celeryflask
server { listen 5005 default_server; server_name _; location / { include proxy_params; proxy_pass http://unix:/var/www/celeryflask/celeryflask.sock; # disable cache while in dev mode: proxy_no_cache 1; proxy_cache_bypass 1; } }

Link to celeryflask's sites-available in the sites-enabled directory:

sudo ln -s /etc/nginx/sites-available/celeryflask /etc/nginx/sites-enabled

sudo systemctl restart nginx restart Nginx

-test the website-

🠜⭪ HOME 🠜⭪ SITEMAP