How to Deploy a Django Project with Gunicorn, Pyenv, and Nginx or Apache
This guide walks you through installing and deploying a Django application using Gunicorn, Pyenv, and Nginx or Apache on a Linux server.
Target OS: Ubuntu 22.04 LTS or other modern Debian-based distributions.
1. Create a Non-Root User
sudo adduser webapp
sudo usermod -aG sudo webapp
2. Install System Dependencies (as root)
sudo apt update
sudo apt install -y make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev \
python-openssl git
3. Switch to webapp
User and Install Pyenv
su - webapp
Install Pyenv
curl https://pyenv.run | bash
Add this to ~/.bashrc
:
echo -e '\n# Pyenv Setup\nexport PATH="$HOME/.pyenv/bin:$PATH"\n\
eval "$(pyenv init --path)"\neval "$(pyenv init -)"' >> ~/.bashrc
source ~/.bashrc
Install Python (e.g., 3.10.5)
pyenv install -v 3.10.5
pyenv virtualenv 3.10.5 virtual
pyenv activate virtual
python --version
Now, we have installed python 3.10.5 using pyenv and we can use 'pyenv activate virtual' to activate the virtual environment,
4. Set Up Your Django Project
Create Project Directory and Virtual Environment
As we installed python, you can clone your git repo to this webapp user location.Install Django and Gunicorn
Normally, there will be requirements.txt file and we can install those withpip install -r requirements.txt
Make sure to install GuniCorn if it's not already mentioned on requirements file. You can manually install as below
pip install gunicorn
Start Your Django Project
Once the requirements are installed, you can check if there is any issues by running check command.
python manage.py check
Kindly ensure that you have activated virtual environment and running it from location same as manage.py.
To test the application locally, you can run below command however it will be exited once you stoped the command.
python manage.py runserver
5. Configure Gunicorn and supervisor
Inorder to better serve the application, we can use the Gunicorn. Please add below gunicorn.conf file under webapp user.
chdir = "/home/webapp/ottu/ottu"
daemon = False
errorlog = "/home/webapp/logs/gunicorn.error_log"
keepalive = 20
loglevel = "debug"
proc_name = "gunic_yourwebsite_webapp"
pidfile = "/home/webapp/run/gunic.pid"
reload = True
reload_extra_files = "/home/webapp/yourwebsite/yourwebsite/config/wsgi.py"
timeout = 300
user = "webapp"
workers = 3
Now, we need to use supervisor. Please install it as follow
sudo apt install -y supervisor
Once done, start the supervisord as below
sudo systemctl enable supervisor
sudo systemctl start supervisor
sudo systemctl status supervisor
Now, we can add below configuration on /etc/supervisord.d/ location with below config file
[program:webapp]
command=/home/webapp/.pyenv/versions/virtual/bin/gunicorn -c /home/webapp/gunicorn.conf config.wsgi:application
directory=/home/webapp/ottu/ottu
autostart=true
autorestart=true
startretries=3
startsecs=5
numprocs=1
user=webapp
stdout_logfile=/home/webapp/logs/webapp.out.log
stderr_logfile=/home/webapp/logs/webapp.err.log
We can run below commands to update and start the supervisor
supervisorctl reread
supervisorctl update
supervisorctl status
6. Set Up Reverse Proxy
Using Nginx (preferred)
sudo apt install nginx
sudo nano /etc/nginx/sites-available/myproject
server {
listen 80;
server_name yourwebsite.com www.yourwebsite.com;
# Redirect www to non-www and force HTTPS
if ($host ~* ^www\.(.*)) {
return 301 https://$1$request_uri;
}
return 301 https://yourwebsite.com$request_uri;
}
server {
listen 443 ssl;
server_name yourwebsite.com www.yourwebsite.com;
# SSL Certificates
ssl_certificate /etc/pki/tls/certs/yourwebsite_localhost.crt;
ssl_certificate_key /etc/pki/tls/private/yourwebsite_localhost.key;
ssl_trusted_certificate /etc/pki/tls/certs/yourwebsite_ca.cabundle;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5:!SEED:!IDEA;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# Redirect www to non-www
if ($host ~* ^www\.(.*)) {
return 301 https://$1$request_uri;
}
# Static files
location /static/ {
alias /home/webapp/yourwebsite/yourwebsite/staticfiles/;
}
location /media/ {
alias /home/webapp/yourwebsite/yourwebsite/yourwebsite/media/;
}
# Well-known path (e.g., for Let's Encrypt)
location ^~ /.well-known/ {
alias /home/webapp/public_html/.well-known/;
}
# Proxy to app server
location / {
proxy_pass http://127.0.0.1:8589;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
}
# Security headers
server_tokens off;
}
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
OR Using Apache
sudo apt install apache2 libapache2-mod-wsgi-py3
sudo nano /etc/apache2/sites-available/myproject.conf
ServerName yourwebsite.com
ServerAlias www.yourwebsite.com
# Redirect www to non-www
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
ProxyPassMatch ^/.well-known !
Alias /.well-known /home/webapp/public_html/.well-known
#RewriteEngine on
RewriteCond %{SERVER_NAME} =yourwebsite.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
ServerName yourwebsite.com
ServerAlias www.yourwebsite.com
# Redirect www to non-www
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [L,NE,R=301]
#RewriteRule ^ https://yourwebsite.com%{REQUEST_URI} [L,R=301]
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
ProxyPass /static/ !
Alias /static/ /home/webapp/yourwebsite/yourwebsite/staticfiles/
Require all granted
ProxyPass /media/ !
Alias /media/ /home/webapp/yourwebsite/yourwebsite/yourwebsite/media/
Require all granted
ProxyPassMatch ^/.well-known !
Alias /.well-known /home/webapp/public_html/.well-known
Require all granted
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set "Host" "yourwebsite.com"
ProxyPass / http://127.0.0.1:8589/ connectiontimeout=300 timeout=300 Keepalive=On
ProxyPassReverse / http://127.0.0.1:8589/
Require all granted
AllowOverride all
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA
SSLCertificateFile /etc/pki/tls/certs/yourwebsite_localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/yourwebsite_localhost.key
SSLCertificateChainFile /etc/pki/tls/certs/yourwebsite_ca.cabundle
ServerSignature Off
ServerTokens Prod
sudo a2ensite myproject
sudo systemctl restart apache2
7. Final Test
Open your domain in a browser. You should see your Django website live.
Conclusion
You’ve successfully deployed a Django project using Pyenv (user-local for webapp
), Gunicorn, supervisor and either Nginx or Apache on Ubuntu 22.04.
Comments
Post a Comment