Deployment Guide

    Deploy Wagtail CMS

    Wagtail is a powerful open-source CMS built on Django, combining an intuitive admin interface with Python's flexibility. This guide covers deploying Wagtail on RamNode's reliable VPS hosting with PostgreSQL, Gunicorn, Nginx, and SSL encryption.

    Ubuntu 22.04/24.04
    Django + PostgreSQL
    ⏱️ 45-60 minutes
    1

    Introduction

    Wagtail is a powerful, open-source content management system built on Django. It combines an intuitive admin interface with the flexibility of a full Python web framework, making it ideal for building complex websites and applications.

    Why Choose Wagtail?

    • Built on Django – leverage Python's powerful ecosystem
    • Intuitive StreamField for flexible content modeling
    • Powerful image and document management
    • Built-in search functionality
    • Excellent developer experience with clean APIs
    • Active community and extensive documentation
    2

    Prerequisites

    Before beginning this deployment, ensure you have:

    • A RamNode VPS with Ubuntu 22.04 or 24.04 LTS
    • Root or sudo access to your server
    • A registered domain name pointed to your server's IP address
    • Basic familiarity with Linux command line and SSH

    Recommended Server Specifications

    ResourceMinimumRecommended
    RAM1 GB2+ GB
    CPU1 vCPU2+ vCPUs
    Storage20 GB SSD40+ GB SSD
    3

    Initial Server Setup

    Update the System

    Start by connecting to your RamNode VPS via SSH and updating all system packages:

    Update system
    sudo apt update && sudo apt upgrade -y

    Create a Dedicated User

    Create a non-root user to run your Wagtail application (security best practice):

    Create user
    sudo adduser wagtail
    sudo usermod -aG sudo wagtail

    Configure the Firewall

    Enable UFW and allow SSH, HTTP, and HTTPS traffic:

    Configure firewall
    sudo ufw allow OpenSSH
    sudo ufw allow 'Nginx Full'
    sudo ufw enable
    4

    Install Dependencies

    Install Python and Development Tools

    Install Python 3, pip, and essential development libraries:

    Install Python
    sudo apt install -y python3 python3-pip python3-venv python3-dev \
      build-essential libpq-dev libjpeg-dev zlib1g-dev libwebp-dev

    Install PostgreSQL

    PostgreSQL is the recommended database for production Wagtail deployments:

    Install PostgreSQL
    sudo apt install -y postgresql postgresql-contrib

    Install Nginx

    Nginx will serve as our reverse proxy and handle static files:

    Install Nginx
    sudo apt install -y nginx
    5

    Database Configuration

    Switch to the postgres user and create a database and user for Wagtail:

    Access PostgreSQL
    sudo -u postgres psql

    Run the following SQL commands in the PostgreSQL prompt:

    Create database and user
    CREATE DATABASE wagtail_db;
    CREATE USER wagtail_user WITH PASSWORD 'your_secure_password';
    ALTER ROLE wagtail_user SET client_encoding TO 'utf8';
    ALTER ROLE wagtail_user SET default_transaction_isolation TO 'read committed';
    ALTER ROLE wagtail_user SET timezone TO 'UTC';
    GRANT ALL PRIVILEGES ON DATABASE wagtail_db TO wagtail_user;
    \q

    ⚠️ Important: Replace 'your_secure_password' with a strong, unique password and store it securely.

    6

    Install Wagtail

    Create Project Directory and Virtual Environment

    Set up the project directory structure and Python virtual environment:

    Setup project
    sudo mkdir -p /var/www/wagtail
    sudo chown wagtail:wagtail /var/www/wagtail
    cd /var/www/wagtail
    python3 -m venv venv
    source venv/bin/activate

    Install Wagtail and Dependencies

    Install Wagtail along with production dependencies:

    Install Wagtail
    pip install --upgrade pip
    pip install wagtail gunicorn psycopg2-binary pillow

    Create the Wagtail Project

    Generate a new Wagtail project:

    Create project
    wagtail start mysite .
    7

    Production Configuration

    Configure Production Settings

    Create a production settings file at mysite/settings/production.py:

    mysite/settings/production.py
    from .base import *
    import os
    
    DEBUG = False
    
    SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
    
    ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': 'wagtail_db',
            'USER': 'wagtail_user',
            'PASSWORD': os.environ.get('DB_PASSWORD'),
            'HOST': 'localhost',
            'PORT': '5432',
        }
    }
    
    STATIC_ROOT = '/var/www/wagtail/static'
    MEDIA_ROOT = '/var/www/wagtail/media'
    
    CSRF_TRUSTED_ORIGINS = ['https://yourdomain.com']
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    SECURE_SSL_REDIRECT = True
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True

    Create Environment File

    Create /var/www/wagtail/.env to store sensitive configuration:

    /var/www/wagtail/.env
    DJANGO_SETTINGS_MODULE=mysite.settings.production
    DJANGO_SECRET_KEY=your-secret-key-here
    DB_PASSWORD=your_secure_password

    Generate a secure secret key using:

    Generate secret key
    python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"

    Initialize the Database

    Run migrations and create a superuser:

    Initialize database
    source /var/www/wagtail/.env
    python manage.py migrate
    python manage.py createsuperuser
    python manage.py collectstatic --noinput
    8

    Gunicorn Configuration

    Create Gunicorn Socket File

    Create /etc/systemd/system/gunicorn.socket:

    /etc/systemd/system/gunicorn.socket
    [Unit]
    Description=Gunicorn socket for Wagtail
    
    [Socket]
    ListenStream=/run/gunicorn.sock
    
    [Install]
    WantedBy=sockets.target

    Create Gunicorn Service File

    Create /etc/systemd/system/gunicorn.service:

    /etc/systemd/system/gunicorn.service
    [Unit]
    Description=Gunicorn daemon for Wagtail
    Requires=gunicorn.socket
    After=network.target
    
    [Service]
    User=wagtail
    Group=www-data
    WorkingDirectory=/var/www/wagtail
    EnvironmentFile=/var/www/wagtail/.env
    ExecStart=/var/www/wagtail/venv/bin/gunicorn \
        --access-logfile - \
        --workers 3 \
        --bind unix:/run/gunicorn.sock \
        mysite.wsgi:application
    
    [Install]
    WantedBy=multi-user.target

    Enable and Start Gunicorn

    Start Gunicorn
    sudo systemctl start gunicorn.socket
    sudo systemctl enable gunicorn.socket
    sudo systemctl status gunicorn.socket
    9

    Nginx Configuration

    Create /etc/nginx/sites-available/wagtail:

    /etc/nginx/sites-available/wagtail
    server {
        listen 80;
        server_name yourdomain.com www.yourdomain.com;
    
        location = /favicon.ico { access_log off; log_not_found off; }
    
        location /static/ {
            alias /var/www/wagtail/static/;
            expires 30d;
            add_header Cache-Control "public, immutable";
        }
    
        location /media/ {
            alias /var/www/wagtail/media/;
            expires 7d;
        }
    
        location / {
            include proxy_params;
            proxy_pass http://unix:/run/gunicorn.sock;
            proxy_connect_timeout 300s;
            proxy_read_timeout 300s;
        }
    
        client_max_body_size 100M;
    }

    Enable the configuration and test Nginx:

    Enable site
    sudo ln -s /etc/nginx/sites-available/wagtail /etc/nginx/sites-enabled/
    sudo rm /etc/nginx/sites-enabled/default
    sudo nginx -t
    sudo systemctl restart nginx
    10

    SSL/TLS Configuration

    Install Certbot

    Install Certbot for Let's Encrypt SSL certificates:

    Install Certbot
    sudo apt install -y certbot python3-certbot-nginx

    Obtain SSL Certificate

    Run Certbot to obtain and configure SSL:

    Get certificate
    sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

    Follow the prompts to complete certificate installation. Certbot will automatically configure Nginx for HTTPS.

    Verify Automatic Renewal

    Test renewal
    sudo certbot renew --dry-run

    Maintenance & Updates

    Updating Wagtail

    To update Wagtail and its dependencies:

    Update Wagtail
    cd /var/www/wagtail
    source venv/bin/activate
    pip install --upgrade wagtail
    python manage.py migrate
    python manage.py collectstatic --noinput
    sudo systemctl restart gunicorn

    Backup Strategy

    Implement regular backups of your database and media files:

    Backup commands
    # Database backup
    pg_dump -U wagtail_user wagtail_db > backup_$(date +%Y%m%d).sql
    
    # Media files backup
    tar -czf media_backup_$(date +%Y%m%d).tar.gz /var/www/wagtail/media/

    Log Monitoring

    View logs
    # Gunicorn logs
    sudo journalctl -u gunicorn
    
    # Nginx logs
    sudo tail -f /var/log/nginx/access.log
    sudo tail -f /var/log/nginx/error.log

    Security Best Practices

    • Keep your system and all packages updated regularly
    • Use strong, unique passwords for all accounts
    • Configure fail2ban to protect against brute force attacks
    • Disable root SSH login and use key-based authentication
    • Regularly audit user access and permissions
    • Enable automatic security updates for Ubuntu

    Troubleshooting

    IssueSolution
    502 Bad GatewayCheck if Gunicorn is running: sudo systemctl status gunicorn
    Static files not loadingRun collectstatic and verify Nginx static path
    Database connection errorVerify PostgreSQL is running and credentials are correct
    Permission denied errorsCheck ownership: chown -R wagtail:www-data /var/www/wagtail

    🎉 Congratulations!

    Your Wagtail CMS is now deployed on your RamNode VPS with a production-ready configuration! You can access the admin panel at https://yourdomain.com/admin/ using the superuser credentials you created.

    For additional resources, refer to the official Wagtail documentation and the Django documentation.