Running Flask as a Service

On my ROV, I am running the Python web server Flask. I want it to start automatically when the Raspberry Pi starts. For this, I need to make it into a Service. Flask displays the following warning on startup. Stating that you should not use it in a production environment, as it is not a development server. However, since I am not doing that, I should be fine.

Flask - not a production server warning
Flask – not a production server warning

Running a Flask Application as a Service with Systemd

Linux has this thing called Systemd that manages most services for us. Systemd’s configuration files are composed of sections called ‘units’. There are several types of units, including services, sockets, devices, timers, and more. For services, unit configuration files must have a .service extension.

I have saved my service file in the Git repo, so that I can edit it for other projects.

[Unit]
Description=ROV Flask web application
After=network.target

[Service]
# User=pi
WorkingDirectory=/home/pi/ROV/Flask/
ExecStart=/home/pi/ROV/Flask/run.sh
Restart=always
StandardOutput=file:/home/pi/flask_output.log
StandardError=file:/home/pi/flask_error.log

[Install]
WantedBy=multi-user.target

The [Unit] section is shared across all systemd unit configuration files. It defines general metadata about the unit and outlines dependency relationships that determine startup order. In this template, I’ve included a description of the service and specified that it should start after the networking stack is up. This should allow it to bind to all IP addresses.

The [Service] section contains application-specific settings. Here, I have configured the service to run under the user Pi, set the working directory, and specified the command used to launch the application.

The Restart directive instructs systemd to automatically restart the service if it stops, ensuring recovery from crashes or unexpected exits.

The [Install] section determines how and when the service should be enabled. By adding WantedBy=multi-user.target, I’m telling systemd to start the service automatically when the system enters multi-user mode.

Run.sh

For some reason, I have been unable to work out; I can’t seem to get Flask to run. I have tried multiple incantations, and nothing seems to work happily, however… I can get it to start if I launch it from a shell script. So in the same folder as the Flask Python files, I have a script called run.sh with the following contents:

#!/bin/bash
su -c 'cd /home/pi/ROV/Flask && .venv/bin/python app.py --port:8082' pi

This is the script that the Service file invokes and runs as root. The second line explicitly changes the directory to the Flask folder and then uses the && operator to allow it to run app.py as the user pi.

To make the script executable, you need to perform ‘chmod +x run.py’.

.env

I also have an .env file in the root of the Flask folder with the following contents:

# Development settings
FLASK_HOST=0.0.0.0
FLASK_PORT=8082
PROJECT=ROV

Running the Service

Service files are expected to be found in the /etc/systemd/system directory so that systemd can see them. I will copy the flask.service file into /etc/systemd/system, and then tell systemd to refresh its configuration, then start my new service.

sudo cp ~/ROV/Configs/flask.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl start flask

Now this is all working as it should; it’s probably not the best way of doing things, but it does allow me to have my Flask app running on port 8082

My ROV Flask app running on port 8082
My ROV Flask app is running on port 8082

Leave a comment

Your email address will not be published. Required fields are marked *

The maximum upload file size: 20 MB. You can upload: image, audio, video, document, spreadsheet, interactive, text, archive, code, other. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop files here