Deploying Wagtail on CentOS8 with MariaDB/Nginx/Gunicorn

skriptmonkey

Skriptmonkey

Posted on January 2, 2021

Deploying Wagtail on CentOS8 with MariaDB/Nginx/Gunicorn

Wagtail is an actively developed, open source CMS built on Python and the Django web framework. In this tutorial, we will go over how to deploy Wagtail on a CentOS 8 server with MariaDB, Nginx, and Gunicorn.

Getting Started

Start with a fresh install of CentOS 8 and make sure your server is up to date.

dnf update -y
# reboot the server to apply the updates if needed.
Enter fullscreen mode Exit fullscreen mode

Create a non-root sudo user, if you haven't already

useradd <username>
passwd <username> #enter new password
# add the user to the wheel group for sudo access.
usermod -aG wheel <username>
Enter fullscreen mode Exit fullscreen mode

Next, lets install Python 3.8 using our newly created sudo user account.

su <username>
sudo dnf module -y install python38
Enter fullscreen mode Exit fullscreen mode

Now we need to install both Nginx and MariaDB.

sudo dnf install nginx mariadb-server git
Enter fullscreen mode Exit fullscreen mode

Setup the environment

At this point I like to create a Wagtail user account for managing the project code.

sudo groupadd --system wagtail
sudo useradd --system --gid wagtail --shell /bin/bash --home /opt/wagtail wagtail
sudo mkdir /opt/wagtail
sudo chown wagtail:wagtail /opt/wagtail
Enter fullscreen mode Exit fullscreen mode

If you're hosting your project on GitHub or GitLab you can create an SSH key using the following commands.

sudo su wagtail
ssh-keygen -t rsa -b 2048 -C "<your email address>"
Generating public/private rsa key pair.
Enter file in which to save the key (/opt/wagtail/.ssh/id_rsa): <enter>
Created directory '/opt/wagtail/.ssh'.
Enter passphrase (empty for no passphrase): <enter password and/or press enter>
Enter same passphrase again: <enter password and/or press enter>
Your identification has been saved in /opt/wagtail/.ssh/id_rsa.
Your public key has been saved in /opt/wagtail/.ssh/id_rsa.pub.
Enter fullscreen mode Exit fullscreen mode

You can get the key by running the following command.

cat /opt/wagtail/.ssh/id_rsa.pub
Enter fullscreen mode Exit fullscreen mode

Setting up the database

Before we do anything else, lets start the MariaDB server and enable MariaDB on boot. Run these commands as root.

systemctl start mariadb
systemctl enable mariadb
Enter fullscreen mode Exit fullscreen mode

Now, to give ourselves a nice, secure default setup run the following command.

mysql_secure_installation
Enter fullscreen mode Exit fullscreen mode
Enter current password for root (enter for none): <enter>
Set root password? [Y/n] n
Remove anonymous users? [Y/n] <enter>
Disallow root login remotely? [Y/n] <enter>
Remove test database and access to it? [Y/n] <enter>
Remove test database and access to it? [Y/n] <enter>
Enter fullscreen mode Exit fullscreen mode

Log in to MariaDB and create the database and user.

mysql -u root -p
Enter password: <enter>
CREATE DATABASE wagtail CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'wagtaildb'@'localhost' IDENTIFIED BY '<db user password';
GRANT ALL PRIVILEGES ON wagtail.* to wagtaildb@localhost;
FLUSH PRIVILEGES;
exit
Enter fullscreen mode Exit fullscreen mode

Deploying your Project

The next step is to pull the code down from your repository. This guide assumes GitHub or GitLab is being used but feel free to use whatever you prefer. For this example I am using an empty project hosted on GitLab named Hello.

If you're following this guide closely you should be logged in as root right now.

Create the Python virtual environment in the wagtail users home directory.

su - wagtail
python3.8 -m venv .venv
source .venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Upgrade setuptools and pip

pip install --upgrade setuptools pip
Enter fullscreen mode Exit fullscreen mode

Create a directory to store the logs.

mkdir logs
Enter fullscreen mode Exit fullscreen mode

Clone your git repositiory and cd into the project directory.

git clone https://gitlab.com/Skriptmonkey/hello.git
cd hello
Enter fullscreen mode Exit fullscreen mode

Install the dependancies.

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Migrate your database.

python manage.py migrate
Enter fullscreen mode Exit fullscreen mode

And finally, collect your static assets. Your STATIC_ROOT variable in the base.py settings file should be set to someplace that Nginx can easily access. I go with '/var/www/static'. Run the following commands as root.

cd /opt/wagtail
source .venv/bin/activate
cd hello
python manage.py collectstatic --noinput
Enter fullscreen mode Exit fullscreen mode

Change back to the wagtail user and create a new settings file in the settings folder called local.py.

su - wagtail
vim /opt/wagtail/hello/hello/settings/local.py
Enter fullscreen mode Exit fullscreen mode

In this settings file we want to import from .base, add a SECRET_KEY, and add in our ALLOWED_HOSTS. How you generate a secret key is up to you. I like to create a "test" project on my local machine and take the SECRET_KEY from that.

from .base import *


SECRET_KEY = '<your secret key>' 

# SECURITY WARNING: define the correct hosts in production!
ALLOWED_HOSTS = ['exampleurl.com', 'www.exampleurl.com']

Enter fullscreen mode Exit fullscreen mode

Configuring Gunicorn

If Gunicorn hasn't been added to the requirements.txt file in your project it should be. But if it isn't you can install it through pip as the wagtail user.

pip install gunicorn
Enter fullscreen mode Exit fullscreen mode

We need to create a start file for gunicorn. This file will be called whenever you need to start the application server. Feel free to use your favorite text editor.

vim /opt/wagtail/gunicorn_start
Enter fullscreen mode Exit fullscreen mode

Paste this into your new file and update the variables to reflect your project. Pay special attention to the DJANGO_SETTINGS_MODULE, Wagtail uses a different convention than Django by default.

#!/bin/bash

NAME="hello"
DJANGODIR=/opt/wagtail/hello
USER=wagtail
GROUP=wagtail
WORKERS=3
BIND=unix:/opt/wagtail/run/gunicorn.sock
DJANGO_SETTINGS_MODULE=hello.settings.production
DJANGO_WSGI_MODULE=hello.wsgi
LOGLEVEL=error

cd $DJANGODIR
source /opt/wagtail/.venv/bin/activate

export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH

exec /opt/wagtail/.venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
  --name $NAME \
  --workers $WORKERS \
  --user=$USER \
  --group=$GROUP \
  --bind=$BIND \
  --log-level=$LOGLEVEL \
  --log-file=-
Enter fullscreen mode Exit fullscreen mode

Make the file executable.

chmod +x ~/gunicorn_start
Enter fullscreen mode Exit fullscreen mode

Make the run directory to store the unix socket file.

mkdir ~/run
Enter fullscreen mode Exit fullscreen mode

Set the permissions on the new directory.

chmod 755 ~/run
Enter fullscreen mode Exit fullscreen mode

Now exit out of the wagtail user so we can setup the systemd gunicorn service.

First create the systemd service file using your favorite editor.

sudo vim /etc/systemd/system/gunicorn.service
Enter fullscreen mode Exit fullscreen mode

Add the following to the file:

[Unit]
Description=gunicorn daemon
After=network.target

[Service]
User=wagtail
Group=wagtail
WorkingDirectory=/opt/wagtail
ExecStart=/opt/wagtail/gunicorn_start

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Start the gunicorn service and enable the service to start on boot.

sudo systemctl start gunicorn
sudo systemctl enable gunicorn
Enter fullscreen mode Exit fullscreen mode

Configuring Nginx

Lets get SELinux squared away before we start on configuring Nginx. We need to install the SELinux utilities.

sudo dnf install policycoreutils-python-utils -y
Enter fullscreen mode Exit fullscreen mode

Now we add httpd_t to the permissive domains in SELinux.

sudo semanage permissive -a httpd_t
Enter fullscreen mode Exit fullscreen mode

While we're allowing things to happen on our server lets also allow both http and https through the server firewall.

sudo firewall-cmd --zone=public --permanent --add-service=http
sudo firewall-cmd --zone=public --permanent --add-service=https
Enter fullscreen mode Exit fullscreen mode

Change into the Nginx conf.d directory.

cd /etc/nginx/conf.d/
Enter fullscreen mode Exit fullscreen mode

Once again, using your favorite editor create a config file for Nginx.

sudo vim wagtail.conf
Enter fullscreen mode Exit fullscreen mode

Add this into the file:

upstream app_server {
    server unix:/opt/wagtail/run/gunicorn.sock fail_timeout=0;
}

server {
    listen 80;
    #listen [::]:80; # <- Uncomment this if you also have AAAA DNS record for IPV6.
    server_name IP_ADDRESS_OR_DOMAIN_NAME;  # <- insert here the ip address/domain name

    keepalive_timeout 5;
    client_max_body_size 4G;

    access_log /opt/wagtail/logs/nginx-access.log;
    error_log /opt/wagtail/logs/nginx-error.log;

    location /static/ {
        autoindex on;
        alias /opt/wagtail/hello/static/;
    }

    location /media/ {
        alias /opt/wagtail/hello/media/;
    }

    location / {
        try_files $uri @proxy_to_app;
    }

    location @proxy_to_app {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://app_server;
    }
}
Enter fullscreen mode Exit fullscreen mode

Test your Nginx configuration.

sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

Start the service and enable it on boot.

sudo systemctl start nginx
sudo systemctl enable nginx
Enter fullscreen mode Exit fullscreen mode

Reboot the server.

sudo reboot
Enter fullscreen mode Exit fullscreen mode

That's it!

You should now have a functional Wagtail site deployed.

Next I'd recommend configuring your webserver with an SSL certificate. Let's Encrypt is a good, free option.

💖 💪 🙅 🚩
skriptmonkey
Skriptmonkey

Posted on January 2, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related