Deploy a Python application behind Nginx that interacts with RabbitMQ/Celery for email sending and logging functionality.
- Python3 installed
- An Ubuntu 22.04 server
- Ngrok account with a static domain set up
- Create the log file and set user permissions
sudo touch /var/log/messaging_system.log && sudo chmod 666 /var/log/messaging_system.log
- Edit the .env file with your SMTP username and password, and the username, password, and vhost name you would use to set up rabbitmq
- Install python dependencies
sudo apt update
sudo apt install -y python3-pip build-essential libssl-dev libffi-dev python3-dev python3-venv python3-flask python3-dotenv
- Install rabbitmq and set up a user with permissions
sudo rabbitmqctl add_user ${USER} ${PASSWORD}
#add virtual host
sudo rabbitmqctl add_vhost '${USER}_vhost'
#add user tag
sudo rabbitmqctl set_user_tags ${USER} '${USER}_tag'
#set permissions
sudo rabbitmqctl set_permissions -p '${USER}_vhost' ${USER} ".*" ".*" ".*"
- Install celery
sudo apt update
sudo apt install celery
- Set up celery systemd service
- Create a celery config file
/etc/default/celeryd
# Name of nodes to start
# here we have a single node
CELERYD_NODES="w1"
# or we could have three nodes:
#CELERYD_NODES="w1 w2 w3"
# Absolute or relative path to the 'celery' command:
CELERY_BIN="/home/ubuntu/stage-three/app/celeryenv/bin/celery"
#CELERY_BIN="/virtualenvs/def/bin/celery"
# App instance to use
# comment out this line if you don't use an app
CELERY_APP="app.celery"
# or fully qualified:
#CELERY_APP="proj.tasks:app"
# Celery working directory
CELERYD_WORKDIR="/home/ubuntu/stage-three/app"
# celery worker user
CELERYD_USER=“ubuntu”
CELERYD_GROUP=“ubuntu”
# How to call manage.py
CELERYD_MULTI="multi"
# Extra command-line arguments to the worker
CELERYD_OPTS="--time-limit=300 --concurrency=8"
# - %n will be replaced with the first part of the nodename.
# - %I will be replaced with the current child process index
# and is important when using the prefork pool to avoid race conditions.
CELERYD_STATE_DIR=“/var/run/celery”
CELERYD_PID_FILE="/var/run/celery/%n.pid"
CELERYD_LOG_FILE="/var/log/celery/%n%I.log"
CELERYD_LOG_LEVEL="INFO"
# you may wish to add these options for Celery Beat
CELERYBEAT_PID_FILE="/var/run/celery/beat.pid"
CELERYBEAT_LOG_FILE="/var/log/celery/beat.log"
- Create the PID and log files and ensure your user owns the files or has appropriate permissions
sudo mkdir -p /var/run/celery && sudo chown ubuntu:ubuntu /var/run/celery
sudo mkdir /var/log/celery && sudo chown ubuntu:ubuntu /var/log/celery
- Set up the celery service file in
/etc/systemd/system/celery.service
[Unit]
Description=Celery Service
After=network.target
[Service]
Type=forking
User=ubuntu
Group=ubuntu
EnvironmentFile=/etc/default/celeryd
WorkingDirectory=/home/ubuntu/stage-three/app
ExecStartPre=+/bin/bash -c 'mkdir -p /var/run/celery'
ExecStartPre=+/bin/bash -c 'chown ubuntu:ubuntu /var/run/celery'
ExecStart=/bin/bash -c '${CELERY_BIN} -A $CELERY_APP multi start $CELERYD_NODES \
--pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
--loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
ExecStop=/bin/bash -c '${CELERY_BIN} multi stopwait $CELERYD_NODES \
--pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
--loglevel="${CELERYD_LOG_LEVEL}"'
ExecReload=/bin/bash -c '${CELERY_BIN} -A $CELERY_APP multi restart $CELERYD_NODES \
--pidfile=${CELERYD_PID_FILE} --logfile=${CELERYD_LOG_FILE} \
--loglevel="${CELERYD_LOG_LEVEL}" $CELERYD_OPTS'
Restart=always
[Install]
WantedBy=multi-user.target
- Run the systemctl commands to start the service
#reload the daemon and start and enable the service
sudo systemctl daemon-reload
sudo systemctl start celery
sudo systemctl enable celery
- Set up gunicorn as a systemd service in
/etc/systemd/system/gunicorn.service
[Unit]
Description=Gunicorn instance to serve the stagethree app
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/stage-three/app
Environment="PATH=/home/ubuntu/stage-three/app/celeryenv/bin"
ExecStart=/home/ubuntu/stage-three/app/celeryenv/bin/gunicorn --workers 3 --bind unix:stagethree.sock app:app
[Install]
WantedBy=multi-user.target
- Run the systemctl commands to start the service
#reload the daemon and start and enable the service
sudo systemctl daemon-reload
sudo systemctl start gunicorn
sudo systemctl enable gunicorn
- Install nginx
sudo apt update
sudo apt install nginx
- Change the owner of the nginx config file to your user and edit the file to include your user instead of
www-data
sudo chown ubuntu:ubuntu /etc/nginx/nginx.conf
sudo nano /etc/nginx/nginx.conf
- Create the nginx config file in
/etc/nginx/sites-available/stagethree
server {
listen 80;
server_name localhost;
location / {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/stage-three/app/stagethree.sock;
}
}
- Create a symlink to sites-enabled, delete default config files, and reload nginx
sudo ln -s /etc/nginx/sites-available/stagethree /etc/nginx/sites-enabled
sudo rm /etc/nginx/sites-available/default && sudo rm /etc/nginx/sites-enabled/default
sudo systemctl reload nginx
- Install ngrok
- Create the ngrok config file if it does not exists in
/home/ubuntu/.config/ngrok/ngrok.yml
version: "2"
authtoken: <your-token>
tunnels:
stagethree:
proto: http
addr: 80
domain: <your-domain>
- Create the ngrok systemd service file in
/etc/systemd/system/ngrok.service
[Unit] Description=Start ngrok tunnel on startup After=network-online.target Wants=network-online.target systemd-networkd-wait-online.service [Service] ExecStart=/usr/local/bin/ngrok start --all --config /home/ubuntu/.config/ngrok/ngrok.yml ExecReload=/bin/kill -HUP $MAINPID KillMode=process IgnoreSIGPIPE=true Restart=always RestartSec=3 Type=simple [Install] WantedBy=multi-user.target
- Run the systemctl commands to start the service
#reload the daemon and start and enable the service
sudo systemctl daemon-reload
sudo systemctl start ngrok
sudo systemctl enable ngrok