Django on AWS Lightsail

Ozan Tellioğlu
7 min readDec 22, 2020

--

In this article, I will try to explain how you can deploy your Django project using LightSail. I realized that there are quite a few tutorials explaining how you can deploy in EC2 or ElasticBean, however, I couldn’t find much about Lightsail considering this is a quite new product of Amazon. You will also see how you can set up an Apache server and use your custom domain to serve your page with an HTTPS connection.

Create an Instance

This is the easiest part of the deployment. You need to login to AWS LightSail using the LINK and click “ Create Instance” from the Instances tab on the Home page. You can also change the region of the instance using the “ Change AWS Region and Availability Zone” button.

Note: I prefer deploying my project all from scratch rather than pre-installed using “Apps+OS” instances. I feel like I am much more in control when I set up everything on my own. Also, the instance with pre-installed Django is using Bitnami, which I don’t find quite easy and explanatory. I tried to deploy with the help of Bitnami and unfortunately, I encountered many problems.

Furthermore, AWS doesn’t allow you to create the cheapest instance with 512MB RAM if you want to use an instance that has pre-installed Django with Bitnami. Since my project was quite small, the cheapest option was quite enough for me.

  • You can also automate snapshots by using “Enable Automatic Snapshots”. It will be useful if you want to change your instance with better specifications or move your project to EC2.
  • Remember to create an SSH key pair and save it in a safe place. You won’t be able to download it again. It will help you to connect to your instance remotely. However, LightSail also has an option to connect to your instance using Web SSH. It is quite useful when you want to make some small changes and you don’t have your computer with you.

Initial Setup

As I mentioned, you can connect to your instance using Web SSH or your SSH Key. Web SSH is quite easy, you just click the button “ Connect Using SSH” and the browser opens a new tab for your console. If you want to use your SSH Key, use the below syntax using your command line from your computer (It is only for demonstration, please use your own key name and your Public IP address):

ssh -i ozan.pem ubuntu@18.244.234.42

Before starting, you should consider that I will install my virtual environment and project within the following directory so that you can understand better all the following commands:

# Virtual Environment Directory
/home/ubuntu/env

# Django Application Directory
/home/ubuntu/ozan

# Public IP Address of Instance
18.244.234.42

Now it is time to install the required packages:

# Update Ubuntu
sudo apt-get update
sudo apt-get upgrade
# Install Python and Virtualenv
sudo apt install python3-pip
pip3 install virtualenv
# Install apache and wsgi
sudo apt install apache2 libapache2-mod-wsgi-py3
# Optional: Install git if you want to track your project
sudo apt install git-all
# Reboot the instance and upgrade fully
sudo reboot
sudo apt full-upgrade
# Create a New Virtual Environment
python3 -m virtualenv env
source env/bin/activate
python -m pip install --upgrade pip
# Locate your requirements file and install
pip install -r requirements.txt

Bring Your Project via Git

I assume that you use Git to bring your project to the instance. If not, you should start because it is the easiest way to update/make changes to your project:

git clone https://github.com/ozntel/Django-Blog-Application.git# Navigate to your project folder and complete migrations
python manage.py makemigrations
python manage.py migrate

# Optional: If you are using caching through database, create the table:
python manage.py createcachetable
# Edit hosts in Settings.py and add public ip of your instance:
ALLOWED_HOSTS = ['18.244.234.42']
# Optional: comment out the below settings from your settings.py if
you have in your project since we will first deploy HTTP:
SECURE_SSL_REDIRECT = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

I assume you would like your virtual environment to be activated automatically once you start your terminal, you can edit bashrc and add commands, which you want to be run before your terminal starts:

sudo vim ~/.bashrc 
# add the line below
source /home/ubuntu/env/bin/activate

Apache HTTP Setup

# Create a configuration file for Django in Apache sudo nano /etc/apache2/sites-available/django.conf

Now you need to adjust the below lines for your project (Public IP, DocumentRoot, Virtual Environment, etc.)

<VirtualHost *:80>	
ServerAdmin admin@18.244.234.42
ServerName 18.244.234.42
ServerAlias www.18.244.234.42
DocumentRoot /home/ubuntu/ozan
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /home/ubuntu/ozan/ozan>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess ozan python-path=/home/ubuntu/ozan python-home=/home/ubuntu/env
WSGIProcessGroup ozan
WSGIScriptAlias / /home/ubuntu/ozan/ozan/wsgi.py
</VirtualHost>

Staying in the same directory, use the configuration file “django.conf”, which you created above, for apache2, or simply change the directory back using the command below:

cd /etc/apache2/sites-available 
sudo a2ensite django.conf

Now it is time to reload apache2:

sudo systemctl reload apache2 
#If apache doesn't reload, you might want to try to start:
sudo systemctl start apache2

Remember to provide required access to Apache and project folders:

sudo ufw allow 'Apache Full'
sudo chmod 664 /home/ubuntu/ozan/db.sqlite3
sudo chown www-data:www-data /home/ubuntu/ozan/db.sqlite3
sudo chown www-data:www-data /home/ubuntu/ozan
sudo chmod 777 /home/ubuntu/ozan

Now you should be able to access your Django project using your Public IP from any browser.

SSL Setup HTTPS

Firstly, you need to create a static IP address from the LightSail Home Page using the Networking tab (Not from inside of the instance) and point this static IP to your instance. The purpose of this is to make sure that you don’t have a different IP address when you reboot your instance on the server.

Secondly, you need to create A record in your DNS settings (from your domain provider) and point your domain to the Public IP address you see available as static IP. it should look like below:

www     14400     A      18.244.234.42

As you can see I am directing www since I have already created a rule to redirect the main domain (ozan.pl) with 301 HTTP response. It is purely for the purpose of SEO. Google might have a problem if you have 2 different links pointing to the same page (www.ozan.pl/mainpage & ozan.pl/mainpage) Just to keep in mind for the future.

Now get back to your django.conf file (we created earlier in this article)

sudo nano /etc/apache2/sites-available/django.conf

and change the Public IP address you provided before to your domain name:

<VirtualHost *:80>	
ServerAdmin admin@ozan.pl
ServerName www.ozan.pl
ServerAlias www.ozan.pl
DocumentRoot /home/ubuntu/ozan
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /home/ubuntu/ozan/ozan>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess ozan python-path=/home/ubuntu/ozan python-home=/home/ubuntu/env
WSGIProcessGroup ozan
WSGIScriptAlias / /home/ubuntu/ozan/ozan/wsgi.py
</VirtualHost>

As you can see, I adjusted ServerAdmin, ServerName, and ServerAlias.

Now you need to make the following installations:

sudo apt install certbot
sudo apt-get install python3-certbot-apache

IMPORTANT: Before we proceed further, you need to make a small change in your django.conf file (which you just adjusted and added your domain) and comment out “ WSGIDaemonProcess”. Unfortunately, there is a bug in apache2 and it won’t complete the installation unless you comment the line below out from django.conf:

#WSGIDaemonProcess ozan python-path=/home/ubuntu/ozan  python-home=/home/ubuntu/env

After commenting out the line above, you can run the following command:

sudo certbot --authenticator standalone \
--installer apache \
-d www.ozan.pl \
--pre-hook "apachectl stop" \
--post-hook "apachectl start"

Make sure that you change “www.ozan.pl" to your domain.

After running this command, you will get a success message:

Congratulations! You have successfully enabled https://www.ozan.pl

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=www.ozan.pl
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/www.ozan.pl/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/www.ozan.pl/privkey.pem
Your cert will expire on 2021-03-19. To obtain a new or tweaked
version of this certificate in the future, simply run certbot again
with the "certonly" option. To non-interactively renew *all* of
your certificates, run "certbot renew"
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
- If you like Certbot, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le

- We were unable to subscribe you the EFF mailing list because your
e-mail address appears to be invalid. You can try again later by
visiting https://act.eff.org.

This will automatically change the existing django.conf file to redirect HTTP to HTTPS and create a new configuration file to handle the SSL connection from port 443.

A few more small changes and we are done. Go to the new configuration file (which will be named most probably similar to “django-le-sl.conf”) and remove the comment from WSGIDaemonProcess line:

WSGIDaemonProcess ozan python-path=/home/ubuntu/ozan  python-home=/home/ubuntu/env

And go back to your django settings file and remove the comments from the lines you commented out at the beginning:

CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True

Every 3 months, you need to renew your Let’s Encrypt certificate, however, you can create automation with Crontab in Ubuntu to run “sudo certbot renew” for you every midnight.

Hope this article will help you to deploy your Django project easily. If you encounter any problem, please feel free to leave a comment below or simply contact me using any channel provided on my page.

Cheers!

Originally published at https://www.ozan.pl on December 22, 2020.

--

--