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.
- 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.
- Install Python, PostgreSQL (or SQLite for very light use), Gunicorn, and Nginx; run Gunicorn as a systemd service.
- Expose the site with Cloudflare Tunnel instead of port forwarding, which also handles HTTPS and dynamic IPs.
- Reduce writes: log to the journal with limits, avoid swap on SD cards.
- Back up the database and media to another machine or cloud storage every day.
- 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.
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=200Min/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.
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
arm64images. - Upgrading from 32-bit OS requires a reinstall; start with 64-bit.
Next steps
- Expose services without port forwarding using Deploy Django With Cloudflare Tunnel.
- Use swap sensibly with Add Swap to a Small Django Server.
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.