Deploy Django with PyInfra

2024.12.27

I'm all about minimalistic efficiency, and PyInfra is the perfect tool for automating repetitive deployment commands.

git pull
python manage.py migrate
python manage.py collectstatic
sudo systemctl restart gunicorn

In this post, I'll show you how to deploy a Django application with PyInfra.

Note: This guide focuses specifically on removing the repetitive deploment commands.

Why PyInfra?

PyInfra

We used to deploy Django applications with Fabric where you can use Python to run automated ssh commands. Ansible is another popular choice for server automation, but PyInfra is a modern alternative that offers a more Pythonic approach to server automation then ansible does.

  • 🚀 Super fast execution over thousands of targets with predictable performance. Up to 10x faster than Ansible.
  • 🚨 Instant debugging with realtime output from shell commands being executed and no abstraction layer.
  • 🔄 Declarative operations that only make changes when needed and enable diff checking.
  • 📦 Extendable with the entire Python package ecosystem. Inventory and operations are written in Python.

Setting Up PyInfra

Just add pyinfra to your requirements.txt file and install it with pip from pypi.

pip install pyinfra

The Deployment Script

Create a deploy.py file in the root of your project and add the following code

from pyinfra.operations import git, server, systemd


# Pull the latest changes
git.repo(src="git@github.com:<username>/<repository>.git", dest="/srv/<application>", pull=True)

# Migrations
server.shell(
    name="Migrations",
    commands=[
        "cd /srv/<application> && . .venv/bin/activate && python manage.py migrate --settings=<application>.settings.production",
    ],
)

# Collectstatic
server.shell(
    name="Collectstatic",
    commands=[
        "cd /srv/<application> && . .venv/bin/activate && python manage.py collectstatic --noinput",
    ],
)

# Restart the app
systemd.service("<application>", running=True, restarted=True, _sudo=True)

Learn more about the available operations in the PyInfra documentation.

Inventory

PyInfra needs to know where to run the commands. Create an inventory.py file in the root of your project and add the following information about your server.

hosts = [
    (
        "<server_ip>",
        {
            "ssh_user": "deploy", # User to connect to the server
            "ssh_key": "~/.ssh/id_rsa", # Path to your private key
            "ssh_forward_agent": True, # Forward your ssh agent for git pull
        },
    ),
]

Learn more about the inventory file in the PyInfra documentation.

Running the Deployment

pyinfra inventory.py deploy.py -y

This command will run the deploy.py script on the server specified in the inventory.py file. Or even on multiple servers if you have more than one host defined.

This will allow you to deploy updates to your Django application with a single command without wasting time on repetitive commands.