Flask production server setup

Prepare Your Ubuntu Server (Work)

1. Update the System

Start by updating the system packages:

Run:

sudo apt update && sudo apt upgrade -y

Install Python and Dependencies

If you don’t already have Python 3 installed, you can install it along with pip:

Run:

sudo apt install python3 python3-pip python3-venv -y

Install Git (if you’re using version control)

Run:

sudo apt install git -y

2. Clone Your Flask Application

If you have your Flask app stored in a Git repository, clone it to your server:

Run:

sudo mkdir /var/flask/
cd /var/flask/
sudo git clone https://github.com/hatted/quizzizz02.git flask-quiz-app

Output:

Cloning into 'flask-quiz-app'...
remote: Enumerating objects: 101, done.
remote: Counting objects: 100% (101/101), done.
remote: Compressing objects: 100% (60/60), done.
remote: Total 101 (delta 39), reused 101 (delta 39), pack-reused 0 (from 0)
Receiving objects: 100% (101/101), 695.59 KiB | 4.55 MiB/s, done.
Resolving deltas: 100% (39/39), done.

If you’re transferring files manually, you can use scp (Secure Copy) or any other method to move your files into the /var/www/ directory.

3. Set Up a Virtual Environment

Navigate to your app directory: Run:

cd /var/flask/flask-quiz-app

Create a virtual environment for your app:

Run:

sudo python3 -m venv venv

Activate the virtual environment:

Run:

source venv/bin/activate

4. Install the Requirements

Make sure your requirements.txt file is in the project directory. Then, install all the dependencies:

Run:

pip install -r requirements.txt

If you haven’t generated a requirements.txt file, you can do so using the following command:

Run:

pip freeze > requirements.txt

Test your app locally:

python app.py

or if you’re using Flask’s built-in runner:

flask run

Test web by another terminal:

Run:

curl http://127.0.0.1:5000

Output:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>quizz - quizz</title>
    <link rel="stylesheet" href="/static/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/css/style.css">
</head>

<body>
    <h1></h1>

    <!-- Bootstrap JS and dependencies (Popper.js, Bootstrap JS) -->
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"></script>
    <script src="/static/js/bootstrap.bundle.min.js"></script>
</body>

Quit app.

Run:

Ctrl+C

5. Configure the Database (SQLite)

If your app uses SQLite, you don’t need to worry about setting up a server; SQLite will automatically create the database file. Just make sure the database is placed in a directory that your Flask app can access.

6. Install Gunicorn

Install Gunicorn in your virtual environment to serve the Flask app:

Run:

pip install gunicorn

Test Gunicorn by running your app:

Run:

gunicorn -w 4 -b 0.0.0.0:8080 run:app

This will run the app with 4 worker processes (-w 4) [recommend (2 * number_of_cores) + 1] and bind it to port 8080 (-b 0.0.0.0:8080).

run:app is the run.py file that contains your Flask app instance. EG.

from app import create_app

app = create_app()

if __name__ == '__main__':
    app.run(debug=True)

Visit http://your-server-ip:8080 to confirm it works.

7. Install Nginx

Nginx will act as a reverse proxy server, forwarding requests to Gunicorn. Install Nginx:

Run:

sudo apt install nginx -y

Output:

[...]
Enabling conf security.
Enabling conf serve-cgi-bin.
Enabling site 000-default.
[...]

Once installed, you can start Nginx:

Run:

sudo systemctl start nginx

Make sure Nginx is enabled to start on boot:

Run:

sudo systemctl enable nginx

8. Configure Nginx as Reverse Proxy

Create a new Nginx configuration file for your app:

Run:

sudo vi /etc/nginx/sites-available/flask-quiz-app

📓 [!NOTE] Use your server’s domain or IP address

Add the following configuration to proxy requests to Gunicorn:

server {
    listen 80;
    server_name **your_domain_or_ip**;
    # Use your server's domain or IP address

    location / {
        proxy_pass http://127.0.0.1:5000;
    # Gunicorn will be running on port 5000
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Optional: Handle static files (e.g., images, CSS)
    #location /static/ {
    #    alias /var/www/flask-quiz-app/static/;
    #}
}

Enable the site by creating a symbolic link to the sites-enabled directory:

Run:

sudo ln -s /etc/nginx/sites-available/flask-quiz-app /etc/nginx/sites-enabled

Then, check the Nginx configuration for syntax errors:

Run:

sudo nginx -t

Output:

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

If everything is okay, restart Nginx to apply the changes:

Run:

sudo systemctl restart nginx

9. Set Up Gunicorn as a Service

To make sure Gunicorn runs as a service and starts on boot, create a systemd service file.

Create the Gunicorn service file:

Run:

sudo vi /etc/systemd/system/flask-quiz-app.service

Add the following content:

[Unit]
Description=Flask Quiz App
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/flask/flask-quiz-app
Environment="PATH=/var/flask/flask-quiz-app/venv/bin"
ExecStart=/var/flask/flask-quiz-app/venv/bin/gunicorn -w 4 -b 127.0.0.1:8080 run:app
ExecStart=/var/flask/flask-quiz-app/venv/bin/gunicorn -w 4 -b unix:flask-quiz-app.sock run:app

[Install]
WantedBy=multi-user.target

Reload systemd to recognize the new service:

Run:

sudo systemctl daemon-reload

Start and enable the Gunicorn service:

Run:

sudo systemctl start flask-quiz-app
sudo systemctl enable flask-quiz-app
sudo systemctl restart flask-quiz-app

Restart server

reboot

You can check the status of the Gunicorn service:

Run:

sudo systemctl status flask-quiz-app

9.1 restart after reboot

cd /var/flask/flask_uid/
source venv/bin/activate
gunicorn -w 4 -b 0.0.0.0:8080 run:app

open http://your-server-ip:8080 to confirm it works. then open http://your_domain_or_ip to confirm it works.

10. Adjust Firewall Settings (if necessary)

If you’re using ufw (Uncomplicated Firewall), allow traffic on HTTP port (80):

Run:

sudo ufw allow 'Nginx Full'
sudo ufw enable

11. Access Your App

Your Flask app should now be accessible through your server’s IP or domain name. Open a browser and go to:

http://your_domain_or_ip

Summary of the Steps:

  • Update and install system dependencies.
  • Clone your Flask app to the server.
  • Set up a virtual environment and install dependencies.
  • Install Gunicorn to serve your Flask app.
  • Configure Nginx as a reverse proxy.
  • Set up Gunicorn to run as a service using systemd.
  • Allow traffic through the firewall.
  • Access your app in the browser.

extra

Install and Configure Supervisor

Supervisor is a client/server system that allows its users to monitor and control a number of processes on UNIX-like operating systems. Supervisor can handle auto-reloading Gunicorn if it crashes or if the Linode is rebooted unexpectedly.

Install Supervisor:

Run:

sudo apt install supervisor

Create a Supervisor script. Replace any instances of flask_app with the name of the application:

Run:

sudo nano /etc/supervisor/conf.d/flask_app.conf

Output:

File: /etc/supervisor/conf.d/flask_app.conf
[program:flask_app]
directory=/home/flask_app_project
command=gunicorn3 --workers=3 flask_app:app
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/var/log/flask_app/flask_app.err.log
stdout_logfile=/var/log/flask_app/flask_app.out.log

Create the log directories and files listed in the flask_app.conf file. Make sure to replace flask_app if it was modified in the Supervisor script above:

Run:

sudo mkdir /var/log/flask_app
sudo touch /var/log/flask_app/flask_app.out.log
sudo touch /var/log/flask_app/flask_app.err.log

Reload Supervisor to apply the changes:

Run:

sudo supervisorctl reload

Output:

Restarted supervisord

The application should now be accessible again through the IP address of the Linode. If you are unable to access the application or receive a bad gateway error, Gunicorn is likely not running. Check the log files to further investigate the issue.

Run:

cat /var/log/flask_app/flask_app.err.log
cat /var/log/flask_app/flask_app.out.log

Output:


The Flask application is now deployed to the production environment and available to anyone for viewing. You can follow a similar workflow to deploy any Flask application to a Linode.

set hostname

Run:

sudo hostnamectl set-hostname domain.com
hostname -f

install Let’s Encrypt

Run:

sudo apt-get install snapd
sudo snap install core; sudo snap refresh core
sudo snap install --classic certbot
sudo apt-get install certbot
sudo apt-get install python3-certbot
sudo apt-get install python3-certbot-apache

Leave a Reply