Introduction
Flask is a Python framework for building web applications. With Flask, developers can easily define routes, handle HTTP requests and responses, and render dynamic content using Jinja2 templates. It also supports extensions allowing developers to integrate features like database access, form handling, and user authentication.
In this article, we are going to deploy a Flask application using Gunicorn, along with CSRF protection and Content Security Policies implementation. We are also going to set up a reverse proxy using Nginx and implement HTTPS by requesting a free SSL certificate from Let’s Encrypt.
Deploy Vultr Optimized Cloud Instance
- Sign up and log in to the Vultr Customer Portal.
- Navigate to the Products page.
- From the side menu, select Compute.
- Click the Deploy Server button in the center.
- Choose Optimized Cloud Compute as the server type.
- Choose a server Location.
- Choose Ubuntu 24.04 as the operating system.
- Choose a suitable plan.
- Choose any Additional Features if required.
- Click Deploy Now.
Add Your Demo Application Code Files
Set Up a Python Virtual Environment
- Install the
python3-venv
package$ sudo apt install python3-venv
- Create a virtual environment.
$ python3 -m venv myenv
- Activate the virtual environment.
$ source myenv/bin/activate
Add Demo Application Code Files
- Clone the Github repository.
$ git clone https://github.com/mayankdebnath/flask-todo-demo.git
- Navigate to the project directory.
$ cd flask-todo-demo/sample/
- Install Flask and Gunicorn packages.
$ pip install flask gunicorn
- Allow incoming connections to port
5000
.$ ufw allow 5000
Apply CSRF Protection and Content Security Policies
Cross-Site Request Forgery (CORS) is a vulnerability that allows someone to exploit and take advantage of a user’s logged-in session on a trusted website to make unauthorized requests to a different website that the user trusts. WTForms is a Flask extension that integrates CSRF protection by default to prevent CORS attacks.
Content Security Policy (CSP) is an extra layer of security for web applications that protects them from malicious attacks. CSP instructs the browser on what resources are allowed to load on a specific webpage. Usually, the website administrator configures a CSP by adding a special header to the server’s response for a webpage, then the browser receives the CSP header and understands what resources are allowed to load. Talisman is an extension for Flask that simplifies the process of adding CSP to Flask applications.
- Install
flask-wtf
andtalisman
packages$ pip install flask-wtf talisman
- Open the
app.py
file.$ nano app.py
- Edit the
app.py
file to include Content Security Policies.from talisman import Talisman talisman = Talisman( app, content_security_policy={ 'default-src': ['\'self\''], 'script-src': ['\'self\'', '\'unsafe-inline\'', 'https://code.jquery.com'], 'style-src': ['\'self\'', '\'unsafe-inline\'', 'https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css', 'https://todoapp5.ddns.net/static/styles.css', 'https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css'], }, force_https=True, session_cookie_secure=True, frame_options='DENY', )
- In the
app.py
file, import and configure CSRF protection.from flask_wtf.csrf import CSRFProtect app.config['SECRET_KEY'] = 'your_secret_key_here' csrf = CSRFProtect(app) csrf._csrf_request_token_key = 'X-CSRFToken'
Save and close the file.
- Navigate to the
templates
directory.$ cd templates
- Open the
index.html
file.$ nano index.html
- Edit the HTML page to include CSRF configuration.
<script> var csrfToken = $('input[name="csrf_token"]').val(); $.ajaxSetup({ beforeSend: function(xhr, settings) { if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrfToken); } } }); </script>
Save and close the file.
- Exit the
templates
directory.$ cd ..
Configuring Nginx as a Reverse Proxy
Nginx acts as a reverse proxy between your web server and clients. It directs incoming requests based on your request configuration settings. In this section, we are going to configure our application for reverse proxy for efficient request handling and load balancing. We are also going to request a free SSL certificate from Let’s Encrypt to implement HTTPS that secures the communication between a user and a web server for our domain.
- Log in to the Vultr Customer Portal.
- Navigate to the Products page.
- From the side menu, expand the Network drop-down, and select DNS.
- Click the Add Domain button in the center.
- Follow the setup procedure to add your domain name by selecting the IP address of your server.
- Set the following hostnames as your domain’s primary and secondary nameservers with your domain registrar.
– ns1.vultr.com – ns2.vultr.com
- Install Nginx.
$ sudo apt install nginx
- Create a new Nginx configuration file.
$ sudo nano /etc/nginx/sites-available/app.conf
- Paste the following configuration into the file.
server { listen 80; listen [::]:80; server_name <your_domain>; location / { proxy_pass http://127.0.0.1:5000/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
- Activate the virtual host configuration.
$ sudo ln -s /etc/nginx/sites-available/app.conf /etc/nginx/sites-enabled/
- Test the Nginx configuration.
$ sudo nginx -t
- Reload Nginx.
$ sudo systemctl reload nginx
- Allow incoming connections to port
80
and443
.$ sudo ufw allow 80/tcp && sudo ufw allow 443/tcp
- Install the certbot package.
$ sudo snap install --classic certbot
- Request an SSL certificate.
$ sudo certbot --nginx -d example.com -d www.example.com
- Start a Gunicorn server.
$ gunicorn -b 0.0.0.0:5000 app:app
- You can now access your Flask application at
https://<your_domain>
.
Do More With Python Apps on Vultr
- Containerize Python Web Applications
- Install Python and Pip on Ubuntu 24.04
- Use Vultr Cloud Inference in Python
- Deep Dive Into Important AI / ML Python Packages
- AI Powered Search with Python and Milvus Vector Database
- Perform Natural Language Processing Tasks with Python
Conclusion
In this article, we explored how to deploy a Flask application using Nginx reverse proxy and Gunicorn with CSRF protection and CSPs. We also secured the application by adding an SSL certificate and enabling HTTPS access.
This is a sponsored article by Vultr. Vultr is the world’s largest privately-held cloud computing platform. A favorite with developers, Vultr has served over 1.5 million customers across 185 countries with flexible, scalable, global Cloud Compute, Cloud GPU, Bare Metal, and Cloud Storage solutions. Learn more about Vultr
Vultr is the world’s largest privately-held cloud computing platform. A favorite with developers, Vultr has served over 1.5 million customers across 185 countries with flexible, scalable, global Cloud Compute, Cloud GPU, Bare Metal, and Cloud Storage solutions.