DEV Community

Cover image for Installing Flask on Ubuntu 24.04
Sanskriti Harmukh for Vultr

Posted on with Aashish Chaurasiya Originally published at docs.vultr.com

Installing Flask on Ubuntu 24.04

Flask is a lightweight, open-source Python web framework for building web applications and APIs, offering routing, request handling, and Jinja2 templating out of the box while staying easy to extend. This guide installs Flask on Ubuntu 24.04 inside a Python virtual environment, builds a basic Flask application, and runs it in production behind Gunicorn and Nginx with HTTPS enabled via Let's Encrypt. By the end, you'll have a Flask application served over HTTPS through Nginx and managed as a systemd service.


1. Set Up the Flask Project Environment

Python and Pip come pre-installed on Ubuntu, and Flask works with any active Python version. Set up an isolated virtual environment before installing Flask.

1. Update the server's package index:

$ sudo apt update
Enter fullscreen mode Exit fullscreen mode

2. Check the installed Python version:

$ python3 --version
Enter fullscreen mode Exit fullscreen mode

If Python isn't installed, install it:

$ sudo apt install python3 python3-pip -y
Enter fullscreen mode Exit fullscreen mode

3. Check the installed Pip version:

$ pip --version
Enter fullscreen mode Exit fullscreen mode

Output:

pip 24.0 from /usr/lib/python3/dist-packages/pip (python 3.12)
Enter fullscreen mode Exit fullscreen mode

4. Install the venv Python virtual environment module:

$ sudo apt install python3-venv -y
Enter fullscreen mode Exit fullscreen mode

5. Create a new directory for the Flask project:

$ mkdir flask_project
Enter fullscreen mode Exit fullscreen mode

6. Switch to the Flask project directory:

$ cd flask_project
Enter fullscreen mode Exit fullscreen mode

7. Create a new flaskenv virtual environment:

$ python3 -m venv flaskenv
Enter fullscreen mode Exit fullscreen mode

This creates an isolated flaskenv environment for managing Python packages.

8. Activate the flaskenv virtual environment:

$ source flaskenv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Your shell prompt should change to reflect the active environment:

(flaskenv) example_user@server:/flask_project$ 
Enter fullscreen mode Exit fullscreen mode

2. Install Flask on Ubuntu 24.04

1. Install Flask using Pip:

$ pip install flask
Enter fullscreen mode Exit fullscreen mode

Output:

Collecting flask
  Downloading flask-3.1.0-py3-none-any.whl.metadata (2.7 kB)
Collecting Werkzeug>=3.1 (from flask)..........
  Downloading werkzeug-3.1.3-py3-none-any.whl.metadata (3.7 kB)
  Downloading MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)........
Installing collected packages: MarkupSafe, itsdangerous, click, blinker, Werkzeug, Jinja2, flask
Successfully installed Jinja2-3.1.4 MarkupSafe-3.0.2 Werkzeug-3.1.3 blinker-1.9.0 click-8.1.7 flask-3.1.0 itsdangerous-2.2.0
Enter fullscreen mode Exit fullscreen mode

To install Flask globally without a virtual environment, use this instead:

$ pip install flask --user
Enter fullscreen mode Exit fullscreen mode

2. Check the installed Flask version:

$ flask --version
Enter fullscreen mode Exit fullscreen mode

Output:

Python 3.12.3
Flask 3.1.0
Werkzeug 3.1.3
Enter fullscreen mode Exit fullscreen mode

3. Create a Basic Flask Application

1. Create a new flask_app.py file using a text editor such as nano:

$ nano flask_app.py
Enter fullscreen mode Exit fullscreen mode

2. Add the following contents to the file:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
Enter fullscreen mode Exit fullscreen mode

Save and close the file. This application listens on port 5000 across all server interfaces (0.0.0.0) and returns "Hello World!" when accessed.

3. Allow connections to TCP port 5000 through the firewall:

$ sudo ufw allow 5000/tcp
Enter fullscreen mode Exit fullscreen mode

4. Reload UFW to apply the changes:

$ sudo ufw reload
Enter fullscreen mode Exit fullscreen mode

5. Run the application:

$ python3 flask_app.py
Enter fullscreen mode Exit fullscreen mode

Output:

 * Serving Flask app 'flask_app'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5000
 * Running on http://YOUR_SERVER_IP:5000
Press CTRL+C to quit
Enter fullscreen mode Exit fullscreen mode

6. Access port 5000 using your server's IP address in a web browser:

http://SERVER-IP:5000
Enter fullscreen mode Exit fullscreen mode

4. Set Up Gunicorn as a System Service to Serve Flask Applications

Gunicorn is a Python WSGI server used to run Flask, Django, and FastAPI applications in production.

1. Install Gunicorn using Pip:

$ pip install gunicorn
Enter fullscreen mode Exit fullscreen mode

Output:

Collecting gunicorn
  Downloading gunicorn-23.0.0-py3-none-any.whl.metadata (4.4 kB)
Collecting packaging (from gunicorn)
  Downloading packaging-24.2-py3-none-any.whl.metadata (3.2 kB)
Downloading gunicorn-23.0.0-py3-none-any.whl (85 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 85.0/85.0 kB 7.7 MB/s eta 0:00:00
Downloading packaging-24.2-py3-none-any.whl (65 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 65.5/65.5 kB 27.9 MB/s eta 0:00:00
Installing collected packages: packaging, gunicorn
Successfully installed gunicorn-23.0.0 packaging-24.2
Enter fullscreen mode Exit fullscreen mode

2. Print your working directory and note the Flask project path:

$ pwd
Enter fullscreen mode Exit fullscreen mode

Output should look similar to:

/home/linuxuser/flask_project
Enter fullscreen mode Exit fullscreen mode

3. Create a new gunicorn_conf.py file:

$ sudo nano gunicorn_conf.py
Enter fullscreen mode Exit fullscreen mode

4. Add the following configuration, replacing /home/linuxuser/flask_project with your actual project path:

from multiprocessing import cpu_count

# Socket Path
bind = 'unix:/home/linuxuser/flask_project/gunicorn.sock'

# Worker Options
workers = cpu_count() + 1
worker_class = 'uvicorn.workers.UvicornWorker'

# Logging Options
loglevel = 'debug'
accesslog = '/home/linuxuser/flask_project/access_log'
errorlog =  '/home/linuxuser/flask_project/error_log'
Enter fullscreen mode Exit fullscreen mode

Save and close the file. This sets up a UNIX socket, dynamically allocates workers based on CPU cores, and logs debug-level messages.

5. Create a new flask_app.service systemd service file:

$ sudo nano /etc/systemd/system/flask_app.service
Enter fullscreen mode Exit fullscreen mode

6. Add the following, replacing linuxuser with your actual user and /home/linuxuser/flask_project with your project path:

[Unit]
Description=Gunicorn instance to serve Flask application
After=network.target

[Service]
User=linuxuser
Group=www-data
WorkingDirectory=/home/linuxuser/flask_project
Environment="PATH=/home/linuxuser/flask_project/flaskenv/bin"
ExecStart=/home/linuxuser/flask_project/flaskenv/bin/gunicorn --workers 3 --bind unix:/home/linuxuser/flask_project/flask_app.sock flask_app:app

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Save and close the file.

7. Reload the systemd daemon:

$ sudo systemctl daemon-reload
Enter fullscreen mode Exit fullscreen mode

8. Enable the flask_app service to start at boot:

$ sudo systemctl enable flask_app
Enter fullscreen mode Exit fullscreen mode

9. Start the flask_app service:

$ sudo systemctl start flask_app
Enter fullscreen mode Exit fullscreen mode

10. Check the service status:

$ sudo systemctl status flask_app
Enter fullscreen mode Exit fullscreen mode

Output:

 flask_app.service - Gunicorn instance to serve Flask application
     Loaded: loaded (/etc/systemd/system/flask_app.service; enabled; preset: enabled)
     Active: active (running) since Wed 2024-12-04 09:35:59 UTC; 17s ago
   Main PID: 15711 (gunicorn)................
Enter fullscreen mode Exit fullscreen mode

11. Alternatively, run the Flask application directly with Gunicorn:

$ gunicorn --bind 0.0.0.0:5000 flask_app:app
Enter fullscreen mode Exit fullscreen mode

5. Configure Nginx as a Reverse Proxy to Secure the Flask Application

1. Deactivate the flaskenv virtual environment:

$ deactivate
Enter fullscreen mode Exit fullscreen mode

2. Install Nginx:

$ sudo apt install nginx -y
Enter fullscreen mode Exit fullscreen mode

3. Create a new flask_app Nginx virtual host configuration:

$ sudo nano /etc/nginx/sites-available/flask_app
Enter fullscreen mode Exit fullscreen mode

4. Add the following, replacing flask.example.com with your domain and /home/linuxuser/flask_project with your project path:

server {
    listen 80;
    server_name flask.example.com;

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/linuxuser/flask_project/flask_app.sock;
    }
}
Enter fullscreen mode Exit fullscreen mode

Save and close the file.

5. Link the configuration to sites-enabled to enable it:

$ sudo ln -s /etc/nginx/sites-available/flask_app /etc/nginx/sites-enabled
Enter fullscreen mode Exit fullscreen mode

6. Test the Nginx configuration:

$ sudo nginx -t
Enter fullscreen mode Exit fullscreen mode

Output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Enter fullscreen mode Exit fullscreen mode

7. Restart Nginx to apply the changes:

$ sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

8. Check the firewall status:

$ sudo ufw status
Enter fullscreen mode Exit fullscreen mode

9. Remove the earlier port 5000 firewall rule:

$ sudo ufw delete allow 5000/tcp
Enter fullscreen mode Exit fullscreen mode

10. Allow the Nginx Full profile to enable HTTP and HTTPS:

$ sudo ufw allow 'Nginx Full'
Enter fullscreen mode Exit fullscreen mode

11. Reload UFW to apply the changes:

$ sudo ufw reload
Enter fullscreen mode Exit fullscreen mode

12. Set your user's home directory permissions to 755 so Nginx can read it. Replace linuxuser with your actual user:

$ sudo chmod 755 /home/linuxuser/
Enter fullscreen mode Exit fullscreen mode

Generate Trusted SSL Certificates

The Flask app currently serves plain HTTP, which is insecure. Use Let's Encrypt to generate a trusted SSL certificate.

1. Install the Certbot Let's Encrypt client via Snap:

$ sudo snap install --classic certbot
Enter fullscreen mode Exit fullscreen mode

2. Generate a certificate for your domain, replacing flask.example.com and user@example.com with your actual domain and email:

$ sudo certbot --nginx -d flask.example.com -m user@example.com --agree-tos
Enter fullscreen mode Exit fullscreen mode

3. Verify that Certbot auto-renews the certificate:

$ sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

Output should look similar to:

Account registered.
Simulating renewal of an existing certificate for flask.example.com

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/flask.example.com\/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Enter fullscreen mode Exit fullscreen mode

4. Restart Nginx to apply the SSL configuration:

$ sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

5. Access your domain in a browser and confirm the Flask application loads over HTTPS:

https://flask.example.com
Enter fullscreen mode Exit fullscreen mode

6. Uninstall Flask on Ubuntu 24.04

1. Deactivate the virtual environment:

$ deactivate
Enter fullscreen mode Exit fullscreen mode

2. Delete the Flask project directory:

$ rm -rf ~/flask_project
Enter fullscreen mode Exit fullscreen mode

3. Uninstall Flask if it was installed globally:

$ pip uninstall Flask
Enter fullscreen mode Exit fullscreen mode

7. Troubleshooting

  • Check the Gunicorn logs for detailed errors:

    $ journalctl -u flask_app.service -f
    
  • On a 502 Bad Gateway error:

    • Verify the Flask service is running:

      $ sudo systemctl status flask_app
      
    • Verify your user's home directory has at least 0755 permissions:

      $ sudo chmod 755 /home/linuxuser/
      
    • Check the Nginx error logs:

      $ sudo tail -f /var/log/nginx/error.log
      
  • If the application doesn't return the expected output, double-check your configuration and restart the app.

Next Steps

  • Swap the sample route for your real application logic and add additional endpoints.
  • Add monitoring and error tracking (e.g., Sentry, Prometheus) for production visibility.
  • Automate certificate renewal checks and set up log rotation for Gunicorn and Nginx.
  • Explore Flask extensions (Flask-SQLAlchemy, Flask-Migrate, Flask-Login) to expand functionality.

For the full guide with additional tips, visit the original article on Vultr Docs.

Top comments (0)