Run Django in Production on a Raspberry Pi

Run a Django app reliably on a Raspberry Pi 4 or 5: use 64-bit Raspberry Pi OS on an SSD instead of an SD card, run Gunicorn and Nginx under systemd, expose it safely with Cloudflare Tunnel, and back up off the device.

Problem statement

A Raspberry Pi makes a cheap, quiet, always-on server for a home dashboard, a family app, an internal tool, or a small public site. Running manage.py runserver on it works for a weekend, then fails: the SD card corrupts after a power cut, the home router's IP changes, port forwarding exposes the network, and nobody notices when the app stops. A Pi can host Django properly if you treat it like a small production server: reliable storage, a real app server under systemd, a safe way to reach it from outside, and backups that leave the device.

Django on a Raspberry PiPi 4 or 564-bit OS on SSDGunicorn + Nginxunder systemdCloudflare Tunnelno open portsBackups off devicedaily copyReliable storage, supervised processes, a tunnel, and off-device backups make a Pi dependable.
  1. Use a Raspberry Pi 4 or 5 with at least 2 GB RAM, booting 64-bit Raspberry Pi OS Lite (or Ubuntu Server) from a USB or NVMe SSD.
  2. Install Python, PostgreSQL (or SQLite for very light use), Gunicorn, and Nginx; run Gunicorn as a systemd service.
  3. Expose the site with Cloudflare Tunnel instead of port forwarding, which also handles HTTPS and dynamic IPs.
  4. Reduce writes: log to the journal with limits, avoid swap on SD cards.
  5. Back up the database and media to another machine or cloud storage every day.
  6. Use a good power supply and, ideally, a small UPS.

Step-by-step solution

1. Choose hardware and storage

A Pi 4 or Pi 5 with 4 GB RAM handles a Django app with PostgreSQL and a few Gunicorn workers comfortably. Storage matters most: SD cards wear out under database writes and corrupt on power loss. Boot from a USB 3 SSD (Pi 4 and 5) or an NVMe HAT (Pi 5). Flash Raspberry Pi OS Lite (64-bit) with Raspberry Pi Imager, setting the hostname, a user, and your SSH key in the imager's settings.

2. Install the stack

sudo apt update && sudo apt full-upgrade -y
sudo apt install -y python3-venv python3-dev build-essential libpq-dev postgresql nginx
sudo -u postgres psql -c "CREATE ROLE myapp LOGIN PASSWORD 'change-me';" -c "CREATE DATABASE myapp OWNER myapp;"

Set up the project in /srv/app with a virtualenv, an environment file, and Gunicorn under systemd with a Unix socket, then Nginx in front, following Deploy Django With Gunicorn and Nginx on Ubuntu; Raspberry Pi OS is Debian-based, so the commands are the same. Most Python packages publish aarch64 wheels, so installs do not compile.

Two or three Gunicorn workers suit a Pi's four cores and memory. For a tiny single-user app, SQLite in WAL mode is fine and saves memory; see Run Django on SQLite in Production.

where the database lives mattersSD card boot✕wears out under database writes✕corrupts easily on power loss✕slow random I/O for PostgresUSB or NVMe SSD boot✓built for sustained writes✓far faster random I/O✓Pi 4 and 5 boot from USB directlyAn SSD is the single biggest reliability upgrade for a Pi serverdjango-deployment.com
If you must use an SD card, choose an endurance-rated one and keep good backups.

3. Expose it safely with Cloudflare Tunnel

Port forwarding on a home router exposes your network and breaks when the ISP changes your IP. A tunnel makes an outbound connection from the Pi to Cloudflare, which then serves your domain with HTTPS:

curl -L https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bookworm main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update && sudo apt install -y cloudflared
cloudflared tunnel login
cloudflared tunnel create pi-app
cloudflared tunnel route dns pi-app app.example.com

Configure the tunnel to send traffic to Nginx on http://localhost:80, install it as a service with sudo cloudflared service install, and add app.example.com to ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS with https://. See Deploy Django With Cloudflare Tunnel. For private use only, Tailscale is an alternative that keeps the app off the public internet entirely.

4. Reduce wear and keep it running

  • Limit journal size: SystemMaxUse=200M in /etc/systemd/journald.conf.
  • Avoid swap on SD cards; on an SSD a small swap file is fine.
  • Enable unattended security upgrades.
  • Add an uptime check (an external service pinging the public URL) so you know when the Pi or your home connection is down.

5. Back up off the device

A Pi is one power surge away from data loss. Back up nightly to another machine or cloud storage:

pg_dump -Fc myapp | gzip > /var/backups/myapp-$(date +%F).dump.gz
rclone copy /var/backups remote:pi-backups --max-age 48h
rclone sync /srv/app/media remote:pi-media

Run these from a systemd timer and test a restore on another machine occasionally.

make a Pi dependableBoot from SSD, not SD cardUSB 3 or NVMeGunicorn and Nginx under systemdrestart on failure, start on bootCloudflare Tunnel or Tailscaleno router port forwardingNightly backups leave the Pirclone to cloud storageOfficial power supply, small UPSpower cuts cause corruptionEach item removes a common way home servers faildjango-deployment.com
With these in place, a Pi can run for months without attention.

Verification check: reboot the Pi and confirm the site comes back by itself (systemctl is-active gunicorn nginx cloudflared), the public URL loads over HTTPS from a phone on mobile data, and the latest backup exists off the device.

Explanation

A Raspberry Pi runs the same Linux and Python stack as a cloud VPS, so Django needs no changes. The differences are environmental: consumer storage, home power, and residential internet. SSD storage addresses write endurance and corruption, systemd brings the app back after reboots and crashes, and an outbound tunnel avoids exposing the home network while also solving changing IP addresses and certificates. Backups that leave the device cover the remaining risk: the Pi itself failing.

Edge cases / notes

  • Heat. Pi 5 throttles under sustained load without cooling; use the active cooler or a case with a fan.
  • Bandwidth. Home upload speeds limit how much media you can serve; offload large files to object storage.
  • Docker works on 64-bit Pi OS; use arm64 images.
  • Upgrading from 32-bit OS requires a reinstall; start with 64-bit.

Next steps

FAQ

Can a Raspberry Pi run Django in production?

Yes, for small sites and internal tools, if it boots from an SSD, runs Gunicorn under systemd, and has off-device backups.

Should I use PostgreSQL or SQLite on a Pi?

PostgreSQL for multi-user apps; SQLite in WAL mode for very light, mostly single-user use.

How do I make a home Pi reachable without port forwarding?

Use Cloudflare Tunnel for public access or Tailscale for private access.

Which Raspberry Pi model is best?

A Pi 5 or Pi 4 with 4 GB or more RAM, booting from an SSD.

Keep going