How to Deploy a Flask Application with uWSGI, Nginx, and SSL on Debian 10
After building a Flask web application, you’ll quickly discover that its built-in server is intended primarily for development use. This walkthrough will demonstrate how to deploy your Flask project on a Debian 10 cloud server using Nginx as the reverse proxy, uWSGI as the application server, and Certbot for securing your site with SSL.
Prerequisites for Deploying Flask on Debian 10
- A Debian 10 system with all packages up to date
- Root access or sudo privileges
- A domain name is optional but recommended
You can proceed with the setup without a domain by configuring Nginx with localhost. However, note that obtaining a valid SSL certificate via Certbot won’t be possible in that case, so the SSL setup portion should be omitted.
Step 1: Installing Nginx on Debian 10
Begin by installing the Nginx package on your server:
# apt install nginx
Once installed, test Nginx by entering your server’s IP address into a browser. If it’s functioning correctly, the default Nginx welcome page should be displayed.
Should you have a domain name, make sure to configure your DNS records to point to your server. The sample configuration for this guide includes:
- IPv4 Address: 192.0.2.123
- Server Names: example.com and www.example.com
Step 2: Installing Flask and Configuring uWSGI
Begin by installing the necessary Python development tools and the Flask and uWSGI packages:
# apt install python3-pip python-dev
# pip3 install uwsgi flask
Next, create a directory to store your website’s files:
# mkdir /var/www/example
If you already have a Flask project to deploy, copy it into the /var/www/example
directory. Otherwise, you can create a simple test app as shown below:
# nano /var/www/example/main.py
Insert the following content into the file:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Hello World!"
if __name__ == "__main__":
app.run(host="0.0.0.0")
Now, set up a configuration file for uWSGI:
# nano /var/www/example/config-uwsgi.ini
Paste the following configuration into the file:
[uwsgi]
app = main
module = %(app)
callable = app
socket = /var/www/example/example.sock
chdir = /var/www/example
chmod-socket = 666
processes = 4
die-on-term = true
You can increase the number of processes for better performance on more powerful servers.
Step 3: Configuring Nginx for Flask and uWSGI
Start by deleting the default Nginx configuration file:
# rm /etc/nginx/sites-enabled/default
Next, create a custom Nginx configuration file:
# nano /var/www/example/config-nginx.conf
Add the following configuration to the file. If you’re not using a domain name, replace example.com
and www.example.com
with localhost
under server_name
:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location / {
include uwsgi_params;
uwsgi_pass unix:/var/www/example/example.sock;
}
}
Create a symbolic link to make Nginx recognize this configuration by linking it to the conf.d
directory:
# ln -s /var/www/example/config-nginx.conf /etc/nginx/conf.d/
To apply the new settings, restart the Nginx service:
# systemctl restart nginx
Step 4: Launching the uWSGI Application Server
Although Nginx is now set up to forward requests to uWSGI, the application server hasn’t been started yet. Use the nohup
command to run uWSGI in the background:
# nohup uwsgi /var/www/example/config-uwsgi.ini &
To test that the process continues after exiting the terminal, press Ctrl + C to send the SIGINT signal. You’ll observe that the uWSGI process stays active in the background.
For a production-grade deployment, it’s advisable to configure uWSGI to start automatically using systemd
.
Finally, open your website in a browser. If everything is functioning properly, you should see the message: Hello World!
Step 4: Launching the uWSGI Application Server
Although Nginx is now set to forward traffic to uWSGI, the uWSGI service still needs to be started. Use nohup
to run it in the background:
# nohup uwsgi /var/www/example/config-uwsgi.ini &
After launching, press Ctrl + C to issue a SIGINT signal and confirm the process continues to run in the background. For long-term use in a production environment, it is best to configure uWSGI to start at boot using a systemd
service.
Open your web browser and visit the server’s address. You should see the Hello World! message displayed from your Flask application.
Step 5: Securing Your Flask Application with SSL
If you’re using a public domain, you can add HTTPS support using a free SSL certificate from Let’s Encrypt via Certbot.
Begin by installing Certbot along with the Nginx plugin:
# apt install certbot python-certbot-nginx
Next, issue a request for an SSL certificate:
# certbot --nginx
Follow the interactive prompts. Accept the terms of service and confirm which domain names should receive SSL coverage by pressing Enter to choose all available options.
When asked, choose the option to automatically redirect all HTTP traffic to HTTPS for secure browsing.
Conclusion
With the help of this beginner-friendly guide, your Flask application is now live on a Debian 10 server, served via Nginx and uWSGI, and protected by an SSL certificate through Certbot. For full deployment readiness, ensure uWSGI runs at boot as a restricted user. Refer to the official Flask and uWSGI documentation for recommended production practices.