How to host a website on AWS and make it resilient.
Tags:
aws nginx transport-layer-securityDescription:
Hosting a website is easy, but it is a lot harder to host a dynamic website that is secured and can handle high loads.
A website just for you on the internet is a great way to showcase yourself, your knowledge and your ability to the world. That may sound hard, but contrary to the popular belief, hosting a website on the internet is not as hard asd you may expect.
This article aims to show readers why and how to host a dynamic website on the cloud with load balancing and secured connections. All you need is some knowledge of Python programming, a little understanding of computer networking, and how Linux-based operating system works.
A more detailed guide on the same topic could be found on Real Python . I would recommend you to read that article if you want a step-by-step instruction of how this works.
Without further ado, let's get started!
To host a website, you need a server, which is a computer that connects to the internet to provide responses for requests from any client computer that wants to connect to your website.
There are many ways to have such a computer. The most traditional way is probably to buy your own PC, set up your own home network, sign a good high-speed internet contract with your internet service provider, install everything correctly within your home network, then deploy the website. As you may guess, there is a million ways for things to go wrong with this set up, and the initial investment for setting up all of this is not so negligible either. In addition, your system is not very scalable, which means when you get more popular and the amount of data sent to your server increases, there is no way for you to easily increase the capacity of your server, except buying new expensive equipment.
That is why more and more internet servers are moving to "the cloud", or more correctly, the "public cloud", run by professional could providers, such as Amazon AWS, Microsoft Azure, or Google Cloud Platform. By installing your server there as an "Infrastructure as a Service" (IaaS), you will not need to care at all about all the network setup up to layer 3 (the network layer) of the OSI layer. Everything is taken care already and you only need to take care of the transport layer and above. Additionally, server scalability is also a lot easier since it will also be taken care by the cloud provider, all you need is just a few mouse clicks.
Among the biggest public cloud providers, AWS was chosen for my project for no particular reason, except for its generous free tier that offers one year of free usage of its Amazon EC2 , which is a virtual machine with enough performance for hosting a website at the personal scale.
Among others of its kind, Django is advertised to be a powerful and versatile web development framework with a comprehensive set of built-in features, rapid development capabilities, efficient scalability, robust security measures, a supportive community, and a mature ecosystem, allowing you to build high-quality web applications efficiently and effectively (Django ). In addition, Django is based on Python, if you know Python, you will quickly understand Django. Great, right?
Of course, advertisements should not totally be trusted, however, I believe you will have more faith in Django when you know that many of the most famous websites on the internet now are coded partially using Django. Some of the biggest names are Instagram, Spotify, Youtube, and DropBox (according to djangostars ).
Yes, even large scale applications like Instagram and Youtube use Django, so, why don't we?
It is not so hard to install Django on an AWS EC2 server and the methods of doing so has been on all over the internet already, therefore I will just skip this part. The details could be found by just a few searches on the internet, or on Real Python .
It is worth noting that you do not need to create your own Django project from the start. There are countless well-built projects already shared by wonderful people of the Django community on the internet that will reduce the work for you drastically. For example, my website uses a template from Abdelaali ES SALMI on Github , which again uses Argon Design System from Creative Tim . The template has shorten my coding time for the website drastically. My big thanks to all the people that put their website source codes online for free.
It should be noted that to really put your website into real deployment, you need a domain. There are many ways to do it, but I personally use Google Domains , which offers user a very easy platform to buy and manage your domains.
For the domain name, for most cases, I would recommend you to use your real name as the domain. In the worse case scenario when your real-name domain has been occupied already, you still should buy a domain that is as close to your real name as possible. Because your website is your "personal branding" on the internet, you should associate it with something that will not change and will always be used to identify "you". You may want to use your nickname for your domain, but nicknames are not fixed and will change with time, which is not suitable to be set as the "address" of you on the internet.
Django is a web framework, not a web server, and is not designed to host any websites. The hosting part should be relied on another specialized web sever application, in this case, there are two, Gunicorn , and Nginx
Django is a web framework. It lets you build the core web application that powers the actual content on the site. It handles HTML rendering, authentication, administration, and backend logic.
Gunicorn is an application server. It translates HTTP requests into something Python can understand. Gunicorn implements the Web Server Gateway Interface (WSGI), which is a standard interface between web server software and web applications.
Nginx is a web server. It’s the public handler, more formally called the reverse proxy, for incoming requests and scales to thousands of simultaneous connections.
-- Brad Solomon on Real Python
Overall, when a request is sent to your website, Nginx as a web server will receive the request. The request is sent to Gunicorn which will load balance the request into several worker processes all using the fame Django framework. These workers will give the response for the request. Nginx will analyze the response and decide how to serve files back to clients based on those responses. If the response contains static files that has been cached within Nginx system already, Nginx will directly server the file to clients without having to query Gunicorn.
With load balancing from Nginx and Gunicorn, the website is ready for real production deployment and is ready to handle significant loads, as long as the hardware permits.
When setting up EC2, or any other equivalents, one important component is to set the "inbound security rules" to allow only SSH connection via port 22 to control your server, and HTTPs connection via port 443 to publish it to the world. In addition, in the initial development stages of your website, you can also allow port 80 for HTTP connection, however, later on, only the secured HTTPS should be used.
Besides those ports, all other ports should be disabled, because you would not want bad people on the internet scan available ports on your system to set up some nasty attacks.
In order to allow the secured HTTPS connection, firstly you will need an SSL/TLS certificate. There are many ways to do this, but the easiest way would be to use a bot called Certbot to do this for you.
After obtaining the certificate, the next step is to add SSL credentials into Nginx config file, and reconfigure Nginx to listen for the HTTPS port 443 along with the HTTP port 80.
To further enhance the security of your website, it is better to redirect all HTTP connection to HTTPS. This task could easily be done with a single line of code within the Nginx configuration file.
Even better, to avoid man-in-the-middle attacks when re-directing between websites, we can force web browsers to only connect to the HTTPS site without any redirecting. This could be done by setting up a HSTS header policy within Nginx. With the HSTS header, the browser does upfront work and force any attempts to connect to the HTTP page to be sent to the HTTPS page.
To help protect sensitive information from being sent through the referer header, we can set up the referrer-policy header within Nginx. This header gives you control over the referrer information shared with external websites and helps safeguard user privacy.
Your website is mostly done, however, if you want multiple people to post stuff on your website, it is better to have a Content-Seciruty-Policy (CPS) Header to avoid cross-site scripting and data-injection attacks. This could be done by django-csp , an extension for Django developed by Mozilla.
With instructions from this article, I hope you will be able to create a production-ready website by yourself, and share your amazing stories to the world.
Again, I would recommend you to read the article by Brad Solomon on Real Python in order to really understand the process I have explained above.