Deploy a Django Application¶
This guide walks you through deploying a standard Django application packaged with uv.
Prerequisites¶
A Linux server (Ubuntu/Debian) with SSH access
A domain pointing to the server (or sslip.io for testing)
Fujin installed (see installation)
Server Setup¶
Fujin provides helper commands to set up your server. These commands handle SSH key setup and user creation.
Set up SSH access (if you don’t have SSH configured):
# Interactive SSH setup wizard
fujin server setup-ssh
Create a dedicated deployment user:
# Interactive user creation wizard
fujin server create-user
These commands ensure your server is properly configured for deployments. For more details, see server.
Project Setup¶
Initialize your Django project with uv:
uv tool install django
django-admin startproject bookstore
cd bookstore
uv init --package .
uv add django gunicorn
The uv init --package command initializes a packaged application, which is required for Fujin.
By default, uv creates a src layout. For Django, it’s often easier to use a flat layout and use manage.py as the entry point.
Remove the default
srcdirectory:rm -r srcConvert
manage.pyto__main__.pyinside the package:mv manage.py bookstore/__main__.pyThis allows running the app via
python -m bookstoreor the installed CLI command.Update
pyproject.tomlto define the script entry point:pyproject.toml¶[project.scripts] bookstore = "bookstore.__main__:main"
This exposes a
bookstorecommand that functions likemanage.py.
Initialize Fujin¶
fujin init
This command does two things:
1. Creates a fujin.toml configuration file in your project root.
2. Creates a .fujin directory containing template files (e.g., for Systemd services and Caddy configuration). You can customize these templates if needed, but the defaults work for most cases.
Create a production environment file:
touch .env.prod
Configuration¶
Django Settings: Update
bookstore/settings.pyto allow your domain and configure static files.ALLOWED_HOSTS = ["your-domain.com"] STATIC_ROOT = "./staticfiles"
Fujin Configuration: Edit
fujin.toml.[[hosts]] user = "fujin" address = "your-domain.com" envfile = ".env.prod" # Define the web process. We bind Gunicorn to a Unix socket for better performance. [processes.web] command = ".venv/bin/gunicorn bookstore.wsgi:application --bind unix:/run/bookstore.sock" listen = "unix//run/bookstore.sock" # Configure routing and static files [[sites]] domains = ["your-domain.com"] routes = { "/static/*" = { static = "{app_dir}/staticfiles/" }, "/media/*" = { static = "{app_dir}/media/" }, "/" = "web" }
Release Command:
The release command runs every time you deploy. It’s the perfect place to run database migrations and collect static files.
release_command = "bookstore migrate && bookstore collectstatic --no-input"bookstore migrate: Applies database migrations.bookstore collectstatic: Collects static files to thestaticfilesfolder in your app directory.
Note: Since we’re using
{app_dir}/staticfiles/in the Caddy configuration, static files are served directly from the app directory. No need for rsync to/var/www.
Deploy¶
Provision and deploy:
fujin up
The fujin up command is your “first deploy” tool. It performs the following:
1. Provisions the server: Installs necessary system packages (like Python, uv, Caddy).
2. Deploys the app: Uploads your code, installs dependencies, runs the release command, and starts the services.
For subsequent updates after the initial deployment, use fujin deploy.
Updating Your Application¶
After the initial deployment with fujin up, use fujin deploy for all updates:
Code changes:
# Make your changes
git commit -am "Fix bug"
# Deploy to server
fujin deploy
Environment variable changes:
# Update .env.prod
nano .env.prod
# Redeploy
fujin deploy
Configuration changes:
# Update fujin.toml
nano fujin.toml
# Deploy with new configuration
fujin deploy
The fujin deploy command is fast - it only uploads and installs what changed.