Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Set up and deploy a Flask web application as a systemctl service with Nginx

profile picture
Author
Einar de Baas
Published
2025-01-20
Time to read
9 minutes reading time

About the author- I like Panthers

Introduction

Welcome to this guide on how to install and deploy your very own Flask web application. For this example I will be using Ubuntu Server and Python 3.12. This has been tested on Python 3.12, it might work on older versions too.

Prerequisites

  • A domain - to host your backend on
  • A server with Ubuntu - to run/host your backend
  • Some basic knowledge of Linux commands

Example terminology

  • Domain: <example.com>

Step 1 - Set up your domain

We first have to point our DNS records to our server, this is because we want to have the Flask backend hosted on our domain.

Go to your DNS provider and create a new A record like this:

Type Name Value
A example.com YourServerIP

Save the new record and wait 24 hours for the DNS to propagate.

Now that your domain is good to go, we can move on with the tutorial.

Step 2 - Install Python (if needed)

To start, we first need to install Python if this is not already done. Usually Python is pre-installed on Ubuntu. You can check this by running these commands:

python3 --version
python3 -m venv --help
python3 -m ensurepip --version       # In python3.12-venv
dpkg -s build-essential
dpkg -s python3-dev

If you see output containing a version with 3.12.x, venv (virtual environments) works, and the other packages are also installed, it means you are good to go and you can now move on to step 4.

If you do not see any output you can install Python by following these commands:

sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.12
sudo apt install python3.12-venv
sudo apt install build-essential python3-dev

The commands above will add the Python repository, update your package list, and install Python from the repository.

Step 3 - Create and set up the working directory

Then we are going to create a directory and a virtual environment. In this case we will use /home/YourUser/flaskbackend.

mkdir ~/flaskbackend      # Create a directory in /home/YourUser
cd ~/flaskbackend         # Move into the created directory
python3 -m venv venv      # Create a Python virtual environment. Doing this without a venv can kill your system.
source venv/bin/activate  # Activate the virtual environment

Now you should see (venv) before your name. This means that your venv (virtual environment) is sucessfully activated. We can now move on with installing the required Python packages.

Install Flask and uWSKI for Python. uWSGI is the WSGI server we will use to deploy the backend.

pip install flask
pip install uWSGI

Now we are going to create the application/Python file. For this you can use your favorite text editor. For this tutorial we are going to use Nano.

  1. Create app.py and open a text editor

    nano app.py
  2. Paste your Flask code in there

    If you don't already have a Flask Python script, you can create one or use the example script below. For this tutorial, we will use a basic script that returns "Hello, World!" and "Hi". This is the code we will use and deploy:

    # Import the modules
    from flask import Flask
    
    # Setting the app variable
    app = Flask(__name__)
    
    # Creating our "homepage"
    @app.route("/")
    def hello_world():
        return "Hello, World!"
    
    # Creating our hello-world route
    @app.route("/some-route")
    def say_hi():
         return "Hi"
    
    # Setting the run command
    if __name__ == "__main__":
         app.run(host="0.0.0.0", port=5000)

Step 4 - Testing the Flask application

Now we are going to test if the script works. For the example above, run this command to start your backend in development mode:

python3 app.py

This should return:

* Serving Flask app 'app'
* Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://YourServerIP:5000
Press CTRL+C to quit
Restarting with stat
* Debugger is active!
* Debugger PIN: 351-930-704

Now you can go to http://YourServerIP:5000 and see if your web application is there. If it is, we can move on.

Step 5 - Test if uWSGI works

  1. Create uwsgi.py and open a text editor. Creating wsgi.py will tell uWSGI what to do.

    nano wsgi.py
  2. Paste this code in there:

    from app import app
    
    if __name__ == "__main__":
        app.run()

Now we are going to test if uWSGI can actually serve the application.

Replace YourPort with the port you want to have it on

uwsgi --socket 0.0.0.0:YourPort --protocol=http --processes=2 -w wsgi:app

Now (again) go to http://YourServerIP:YourPort

See if you can see the standard backend page. If you can, we can move on.

Type and enter deactivate — this will make you exit the venv.

Step 6 - Set up a systemctl service for our Flask backend

  1. Create the service file

    A service file tells your system what your application is and what it needs to do.

    sudo nano /etc/systemd/system/flaskbackend.service
  2. Paste this in the service file:

    In the content below change:

    • YourUser ➔ to your username
    • NumberOfProcesses ➔ to the number of processes you want to have
    [Unit]
    Description=A uWSGI instance to serve the Flask backend
    After=network.target
    
    
    [Service]
    User=YourUser
    Group=www-data
    WorkingDirectory=/home/YourUser/flaskbackend
    Environment="PATH=/home/YourUser/flaskbackend/venv/bin"
    ExecStart=/home/YourUser/flaskbackend/venv/bin/uwsgi --socket /home/YourUser/flaskbackend/flaskbackend.sock --module wsgi:app --master --processes NumberOfProcesses --chmod-socket=660 --vacuum --py-autoreload 1
    
    [Install]
    WantedBy=multi-user.target
  3. Start the service

    sudo systemctl daemon-reload        # Reload the service files
    sudo systemctl start flaskbackend   # Start your backend
    sudo systemctl enable flaskbackend  # Tell your system to start the Flask backend at boot
  4. Check the status of your running backend

    sudo systemctl status flaskbackend

    The output should look like this:

    ● flaskbackend.service - A uWSGI instance to serve the Flask backend
         Loaded: loaded (/etc/systemd/system/flaskbackend.service; enabled; preset: enabled)
         Active: active (running) since Sat 2024-11-23 20:32:32 CET; 2 weeks 1 day ago
       Main PID: 1547894 (uwsgi)
          Tasks: 82 (limit: 38366)
         Memory: 307.1M (peak: 1.1G)
            CPU: 2d 2h 7min 35.756s
         CGroup: /system.slice/flaskbackend.service
                 ├─1547894 /home/YourUser/flaskbackend/venv/bin/uwsgi --socket /home/YourUser/flaskbackend/flaskbackend.sock --module wsgi:app --master --processes numberofprocesses --chmod-socket=660 --vacuum --py-autoreload 1
                 ├─1548580 /home/YourUser/flaskbackend/venv/bin/uwsgi --socket /home/YourUser/flaskbackend/flaskbackend.sock --module wsgi:app --master --processes numberofprocesses --chmod-socket=660 --vacuum --py-autoreload 1

Step 7 - Set up Nginx

Now this is running, we are going to setup a Nginx proxy.

  • Update your packages and install Nginx:

    sudo apt update                                    # Update your package list
    sudo apt install nginx                             # Install Nginx
    sudo systemctl start nginx                         # Start Nginx
    sudo systemctl enable nginx                        # Start Nginx at boot 
    sudo unlink /etc/nginx/sites-enabled/default       # Remove the standard Nginx site
  • Change the Nginx configuration to avoid permission issues.

    sudo nano /etc/nginx/nginx.conf

    Change user www-data; to user YourUser; (you need to replace YourUser with your actual user)

  • Create the Nginx configuration file

    sudo nano /etc/nginx/sites-available/flaskbackend  # Create the Nginx configuration file
  • Paste the following configuration:

    Replace example.com and YourUser with your actual domain and username.

    server {
        listen 80;
        server_name example.com www.example.com;
    
        location / {
            include uwsgi_params;
            uwsgi_pass unix:/home/YourUser/flaskbackend/flaskbackend.sock;
        }
    }
  • Create a symbolic link to /etc/nginx/sites-enabled (where the enabled sites are located)

    If you update the file in /etc/nginx/sites-enabled, the changes will be automatically reflected in /etc/nginx/sites-available.

    sudo ln -s /etc/nginx/sites-available/flaskbackend /etc/nginx/sites-enabled
    sudo nginx -t

    With the last command, you should get:

    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
  • Restart Nginx

    sudo systemctl restart nginx      # Restart Nginx

Now go to your domain, e.g. http://example.com, and you should see your web application

Step 8 - Set up a SSL certificate using Certbot

Now that this is all set up we are going to secure the web application with a SSL certificate using Certbot

sudo apt update                                         # Update your list of packages
sudo apt install python3-certbot-nginx                  # Install Certbot for Nginx
sudo certbot --nginx -d example.com -d www.example.com

The last command will change example.com to example.com. This will request an SSL certificate for www.example.com and example.com. Answer the questions and you should have installed your certificate

Now you can go to https://example.com and see your Flask web application.

Conclusion

That's it! You have now done the following things:

  • Installed Python on your Ubuntu system
  • Installed uWSGI and Flask in your venv
  • Created a Nginx reverse proxy
  • Set up a working SSL certificate

I hope this guide has helped you. Thanks for following along!

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get €20/$20 free credit!

Valid until: 31 December 2025 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more