How I Set Up and Got My First Django Project Running On My Own Server
During the global pandemic of Covid-19 I got really bored and I realized that no one was using my old gaming PC that I built when I was in about grade 8 or 9. To be fair, its been running the same windows on the same shitty 500gb HDD from seagate with so much malware and extra programs that it took 10 mins to start up. Everyone in my house was using a laptop of their own anyways and so this specific desktop had no use to them. Thus the idea of using this as a server for my personal website came to my head. After all my front end still needs a lot of work, so why not gain some extra points by hosting the website myself? This is what led me to the website you are looking at right now.
Also you dont necessarily have to use your own PC to host your own server. Obviously the security risks of running your own server from your home is a real risk and can lead to potentially dangerous results. Not to mention the fact that most ISP's only offer dynamic IPs which is a headache(unless automated) as you must always add the new ip to your allowed hosts in settings.py, as well as change the ip with your domain name provider. I personally use No-ip because it has automated support with my router and its cheaper than Dyndns at $25 a year. If this concerns you, I suggest using a service like digital ocean or linode. This service allows you to use a fresh ubuntu server with a set amount of ram and storage to deploy your website, it is however a paid service. But the learning experience of setting up your own SSL certificate and setting up apache2 and everyting else is the exact same.
Installation
I chose to use Ubuntu Server because I found a lot more support and resourses for Ubuntu than I did for FreeBSD or openSUSE (although after many failed installation attempts I did consider using one of the latter). To install the OS I did the regular, create a bootable USB using Belena Etcher on my other PC (it was running Manjaro at the time but have since changed it to Kubuntu). I then plugged in the USB into the PC. Spammed F12, chose the USB as the boot option and went through the installation. For some reason it always failed at making the partition, even with manually setting the partitions and clearing it with the terminal (using sudo dd). I tried using Ubuntu 18.04 server LTS instead to no avail. So instead I tried using a different harddrive. I had 2 1TB HDD in my current PC, so I took one of them and placed them in the server PC and tried the installation with that. After doing that, the installation went smoothly and it finally worked (with ubuntu 18.04 server LTS).
Set Up
To set up, the first thing I did was:
sudo apt upgrade
sudo apt install apache2
sudo apt install libapache2-mod-wsgi-py3
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.8
sudo apt install python3-pip
sudo apt install openssl
sudo apt install openssh-server
sudo apt install git
pip install django
pip install virtualenv
pip install any other dependencies you may have on your project such as tinyMCE
A lot of people also prefer to use mySQL over SQLlite3 (which is what I used), if so install mysql_server as well. The above list is not absolute, it is something for you to use to get a general idea of what you may need.
I essentially went through everything I thought I may have needed for my server, the above is what I could remember. At one point I even installed and tried using Nginx, but I preferred apache2 so that's what I ended up using. Openssh was used with port 22 (the default one) so that I can terminal in from anywhere if there was a problem with my server (at the time this was mainly related to dynamic ip issues). My friend Navinn (https://navn.me) later suggested that I use it locally (which seems obvious to most peoplle but never crossed my mind).
Anyways, the main thing I wanted to talk about was how I set up my django website with my server. Well, the first step was to forward all requests to port 80 on your router to your server. The ip address of your server can be found by doing this:
sudo ifconfig
a dialogue like this will appear:
-
enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.2.72 netmask 255.255.255.0 broadcast 192.168.2.255 inet6 fe80::428d:5cff:fe8a:1aef prefixlen 64 scopeid 0x20<link> ether 40:8d:5c:8a:1a:ef txqueuelen 1000 (Ethernet) RX packets 278072 bytes 17825874 (17.8 MB) RX errors 0 dropped 69872 overruns 0 frame 0 TX packets 6853 bytes 1498802 (1.4 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 1307 bytes 121032 (121.0 KB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1307 bytes 121032 (121.0 KB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
In this case my local IP is 192.168.2.72 (whatever is found under inet)
Essentially the settings in your router will look something like this:
Name | Status | Protocol | Internal Port | External Port | Local IP |
---|---|---|---|---|---|
Apache | On | Both | 80-80 | 80-80 | 192.168.2.72 |
This is what the options were with my bell homehub router, this will be different depending on what router/brand you use. For example, there may not be an option for internal/external, in that case just put 80 alone.
First test that your apache server is up and running by trying to access it via your public IP address or locally. You should see the default ubuntu/apache server page. Looks something like this:
.
This page essentially means that your server is running, and that you can access it, however it is not displaying your project yet obviously because you haven't added it.
Deployment
The next step is adding the virtualenv to your django project directory using python virtualenv. When I first started I wondered why every tutorial was doing this, because at first glance it does not seem to be necessary. However, after doing my own research I found out that its because it seperates your project from the rest of the OS, thus allowing you to install and use necessary software in the /bin folder of your project instead of the actual machine. And everyone recommends using a virtualenv for your django projects. To do this:
virtualenv ~/example.com/my_project -p /home/user name/opt/python-3.8/bin/python3
To activate:
source project/bin/activate
Your terminal will look something like this
(env)user@server_name:~
I strongly suggest adding this to your gitignore because there are quite a bit of files and I myself have neglected this and its very annoying to reset all your commits.
The next thing you need to do is enable the WSGI mod for apache with the following line:
sudo a2enmod mod-wsgi
The next thing you need to do is add the WSGI.py and other django files to your virtual host. First open the virtual host conf file. For Ubuntu and apache2 it is the following:
sudo nano /etc/apache2/sites-available/000-default.conf
Add the following lines:
-
<Directory /path/to/project/app> <Files wsgi.py> Require all granted </Files> </Directory> <Directory /path/to/project/staticfiles/> Require all granted </Directory> <Directory /path/to/project/media/> Require all granted </Directory> WSGIDaemonProcess project-name python-home=/path/to/project/myprojectenv python-path=/path/to/project WSGIProcessGroup project-name WSGIScriptAlias / /path/to/project/app/wsgi.py
Check the syntax of the current conf file with the following:
sudo apachectl configtest
You will get a message like this if evertything is OK:
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
Syntax OK
The main thing to take away from that message is that 'Syntax OK', the above just means there is no proper name for the server, which in the grand scheme of things did not really matter to me.
If it says 'Syntax OK' You can now restart the apache server. There are 2 ways:
sudo /etc/init.d/apache2 restart
sudo apachectl restart
With the init.d method you get
[ ok ] Restarting apache2 (via systemctl): apache2.service.
as a message, which I prefer over apachectl which is just:
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
When I first did this, the django website was not comming up and it remained on the default Apache/Ubuntu page. I late realized that you also have to white-list these files on the main Apache conf file.
Do the following:
sudo nano /etc/apache2/apache2.conf
Add the following lines:
-
<Directory /usr/share> AllowOverride None Require all granted </Directory> <Directory /var/www/> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> <Directory /srv/> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> <Directory /path/to/project/> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> WSGIScriptAlias / /path/to/project/app/wsgi.py WSGIpythonPath /path/to/project/:/path/to/project/myprojectenv/lib/python3.8/site-packages WSGIDaemonProcess project-name python-path=/path/to/project:/path/to/project/myprojectenv/lib/python3.8/site-packages WSGIProcessGroup project-name Alias /media/ /path/to/project/media/ Alias /static/ /path/to/project/staticfiles/
Do not forget the trailing '/', it took me a long time to realize that by not adding those slashes, you don't white-list everything and for the longest time I had each thing individually white-listed without realizing why I had to. Once this is done, your site should be up and running, with your public IP.
You may need to do certain things like:
cd /your/project/directory
python manage.py makemigrations
python manage.py migrate
python manage.py collectstatic
sudo /etc/init.d/apache2 restart
Make migrations is to merge all your models, migrate officially migrates them. Collectstatic is there so that your admin page has its css and doesn't look like pure HTML (Took me too long to figure this out when my admin page looked messed up).
The main thing to take away from this post is that I am by no means smart, and I overlooked some very obvious things, as well as make tons of mistakes along the way. However, this taught me to keep a keen eye on the details as well as follow instructions and tutorials carefully, while figuring things out that work for my specific situation. If I was able to do this, anyone can. I also strongly suggest hosing your website or project yourself. Its a great learning oppurtunity and its fun as well. Not to mention the extra big brain points and flex points you get for being able to say you have your own server.
If you actually are trying this out yourself and somehow stumble on this post and need help, don't hesitate to email me at sharanshangar@gmail.com. Id be happy to help anyway I can, after all thats a great way for us both to learn!
I will add more posts regarding SSL and other features, this post was just to deploy it. Unfortunately with just these steps, you won't have the amazing https:// before your url.