Deploy Django to a Linux (Ubuntu) Server
Deploy Django with Apache and mod_wsgi on a Ubuntu virtual machine on Microsoft Azure.
Create an Azure Virtual Machine
Go to Microsoft Azure
-> Azure services -> Create a resource -> Virtual machine -> Create
Resource Group: markdown-blog-server-group
Virtual machine name: markdown-blog-server
Username: user0
Continue with default settings till you get
Click Download private key and create resourse
Set up SSH
mv /mnt/c/Users/[username]/downloads/happyhacker.pem ~/.ssh/happyhacker.pem
chmod 400 ~/.ssh/happyhacker.pem
ssh -i ~/.ssh/happyhacker.pem user0@20.255.61.200
exit
cat ~/.ssh/id_rsa.pub
# Copy the content
ssh -i ~/.ssh/happyhacker.pem user0@20.255.61.200
nano ~/.ssh/authorized_keys
# Append it to the authorized_keys file
sudo chmod 700 ~/.ssh/
sudo chmod 600 ~/.ssh/*
exit
ssh user0@20.255.61.200
Upgrade the system
sudo apt-get update && sudo apt-get upgrade
Get hostname, set hostname(Optional) and add it into hosts file
$ hostname
markdown-blog-server
$ sudo hostnamectl set-hostname [hostname] # Set a new hostname(Optional)
$ sudo nano /etc/hosts
Add 'public.IP.adress hostname' under '127.0.0.1 localhost' into hosts file
Firewall installation and setup, 'ufw' stands for Uncomplicated Firewall
sudo apt install ufw
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw allow ssh
sudo ufw allow 8000
sudo ufw enable
sudo ufw status
For Azure VM, we also need to go to Networking -> Inbound port rules and add inbound port rules -> Destination port ranges -> 8000.
Copy source code into VM home Directory
scp -r markdown_blog user0@20.2.100.200:~/
Or pull code from GitHub or your own Git server
ssh-keygen -t ecdsa -b 521
cd ~/.ssh
ls
cat id_ecdsa.pub
copy the content in id_ecdsa.pub and go to www.github.com -> GitHub profile picture (on the top right) -> settings -> SSH and GPG keys -> SSH keys / Add new -> paste it into 'Key'
cd ~
git clone git@github.com:username/repo_name.git
Create a virtual environment, activate it and install Python libraries
cd project-folder
sudo apt install python3-pip python3-venv python3-dev default-libmysqlclient-dev
python3 -m venv venv
source venv/bin/activate
pip list
pip install -r requirements.txt
Copy production .env, db.sqlite3 and media folder into project folder
scp .env db.sqlite3 user0@20.255.61.200:~/markdown_blog/
scp -r media user0@20.255.61.200:~/markdown_blog/
# Copy files from remote server into local computer Example
scp user0@20.255.61.200:~/markdown_blog/db.sqlite3 db.sqlit
e3
Run dev server and test if the website can be open outside VM
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic
python manage.py runserver 0.0.0.0:8000
Install Apache and mod-wsgi
sudo apt-get install apache2
sudo apt-get install libapache2-mod-wsgi-py3
Configure Apache web server
cd /etc/apache2/sites-available
ls
sudo cp 000-default.conf markdown_blog.conf
sudo nano markdown_blog.conf
...
#Include conf-available/serve-cgi-bin.conf
alias /static /home/user0/markdown_blog/static
<Directory /home/user0/markdown_blog/static>
Require all granted
</Directory>
alias /media /home/user0/markdown_blog/media
<Directory /home/user0/markdown_blog/media>
Require all granted
</Directory>
<Directory /home/user0/markdown_blog/blog>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIScriptAlias / /home/user0/markdown_blog/blog/wsgi.py
WSGIDaemonProcess markdown_blog python-path=/home/user0/markdown_blog python-home=/home/user0/markdown_blog/venv
WSGIProcessGroup markdown_blog
</VirtualHost>
...
Apache2-enable the site
sudo a2ensite markdown_blog
sudo a2dissite 000-default.conf # Disable default configure file
sudo systemctl reload apache2
systemctl status apache2.service
An AH00558 error will not prevent Apache from running correctly. The message is mainly for informational purposes
Set up file permissions
cd ~
sudo chown :www-data markdown_blog/db.sqlite3;sudo chmod 664 markdown_blog/db.sqlite3
sudo chown :www-data markdown_blog/;sudo chmod 775 markdown_blog/
sudo chown -R :www-data markdown_blog/media/;sudo chmod -R 775 markdown_blog/media/
www-data is the user that web servers on Ubuntu (Apache, nginx, for example) use by default for normal operation. The web server process can access any file that www-data can access. It has no other importance.
Allow HTTP traffic
For Azure VM, we need to go to Networking -> Inbound port rules and add inbound port rules -> Destination port ranges -> 80.
sudo ufw allow http/tcp
sudo service apache2 restart
You should be able to open the site with IP address now
Please refer to How To Troubleshoot Common Apache Errors if it doesn't work.
Eable HTTPS with a free SSL/TLS certificate using Let's Encrypt
sudo nano /etc/apache2/sites-available/markdown_blog.conf
ServerName peng.works
ServerAlias www.peng.works
#WSGIScriptAlias ...
#WSGIDaemonProcess ...
#WSGIProcessGroup ...
sudo snap install core; sudo snap refresh core
sudo apt-get remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --apache -d peng.works -d www.peng.works # Create certificates for both domains
sudo cat /etc/apache2/sites-available/markdown_blog.conf # Checking a few new lines at the bottom
sudo cat /etc/apache2/sites-available/markdown_blog-le-ssl.conf # Checking a few new lines at the bottom
sudo nano /etc/apache2/sites-available/markdown_blog.conf
# Remove below lines (Ctrl+K == delete a line in nano)
alias /static /home/user0/markdown_blog/static
<Directory /home/user0/markdown_blog/static>
Require all granted
</Directory>
alias /media /home/user0/markdown_blog/media
<Directory /home/user0/markdown_blog/media>
Require all granted
</Directory>
<Directory /home/user0/markdown_blog/blog>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
#WSGIScriptAlias ...
#WSGIDaemonProcess ...
#WSGIProcessGroup ...
sudo nano /etc/apache2/sites-available/markdown_blog-le-ssl.conf
# Uncomment below lines
WSGIScriptAlias ...
WSGIDaemonProcess ...
WSGIProcessGroup ...
sudo apachectl configtest
sudo ufw allow https
sudo service apache2 restart
sudo certbot renew --dry-run
sudo crontab -e
1
# m h dom mon dow command
# It will run on 4:30am the first day of any month, any day of the week
30 4 1 * * sudo certbot renew --quiet
For Azure VM, we need to go to Networking -> Inbound port rules and add inbound port rules -> Destination port ranges -> 443.
The commands above are subject to change. Please refer to Let's Encrypt for the latest update
Django deployment checklist
python manage.py check --deploy
How to generate a Django secret key
python3 manage.py shell
from django.core.management.utils import get_random_secret_key
get_random_secret_key()
Set 'Debug' to 'False' and disallow port 8000
sudo ufw delete allow 8000
sudo service apache2 restart