Linux Deployment Guide for Flask Applications: From Development to systemd Service Management

#Flask #Linux #systemd #Python #WebDevelopment #Backend #Deployment #SystemService #DevOps

Table of Contents

When developing web applications in a Linux environment, we often need our applications to start automatically when the system boots and be easily manageable through the command line. This article will detail how to package a simple Flask application as a Linux system service, and use systemd to manage its lifecycle.

Writing a Basic Flask Application

First, we need to create a simple Flask application. Create a myapp.py file in the /usr/local/bin/ directory:

#!/usr/bin/env python3
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello, World!"

if __name__ == "__main__":
    # Listen on all interfaces, port 5000
    app.run(host="0.0.0.0", port=5000)

In this example:

  • The first line shebang (#!/usr/bin/env python3) ensures the correct Python interpreter is used
  • We define a basic route “/” that returns “Hello, World!” when accessed
  • app.run() starts the built-in development server, listening on all network interfaces on port 5000

Set the file to be executable:

sudo chmod +x /usr/local/bin/myapp.py

Testing the Flask Application

Before proceeding to the next step, verify that the application runs correctly:

/usr/local/bin/myapp.py

Open http://localhost:5000 in your browser, and you should see the “Hello, World!” response.

Creating a systemd Service Unit File

To make the Flask application a system service, we need to create a systemd service unit file. Create the file /etc/systemd/system/myapp.service with root privileges:

[Unit]
Description=My Flask Application
After=network.target nss-user-lookup.target

[Service]
# Directly execute the file (with executable permissions set)
ExecStart=/usr/local/bin/myapp.py
# Alternatively, you can use:
# ExecStart=/usr/bin/python3 /usr/local/bin/myapp.py

# Automatically restart when the application exits abnormally
Restart=on-failure

# Specify the user to run as (replace with your actual username)
User=<your_username>

# Set environment variables, such as setting Flask to production mode
Environment=FLASK_ENV=production

[Install]
WantedBy=multi-user.target

Important Notes

  • User Setting: Ensure this user exists in the system; you can check with id <your_username>
  • If using LDAP or network authentication, After=nss-user-lookup.target ensures user information can be correctly resolved
  • Running as a non-root user is a security best practice, but for testing, you can temporarily remove the User/Group setting
  • Restart=on-failure ensures the application automatically restarts if it exits abnormally

Enabling and Managing the systemd Service

After creating the service file, execute the following commands to enable and manage the service:

Enabling the Service

# Reload systemd configuration
sudo systemctl daemon-reload

# Enable the service (auto-start on boot)
sudo systemctl enable myapp.service

# Start the service immediately
sudo systemctl start myapp.service

# Check service status
sudo systemctl status myapp.service

Managing the Service

# Stop the service
sudo systemctl stop myapp.service

# Restart the service
sudo systemctl restart myapp.service

# Disable auto-start on boot
sudo systemctl disable myapp.service

Creating a Convenient Command Line Tool

To make application management more convenient, we can create a wrapper script. Create a script named myapp in /usr/local/bin/:

#!/bin/bash
# Wrapper script: Control myapp.service via systemctl

SERVICE_NAME=myapp.service

case "$1" in
  start)
    sudo systemctl start $SERVICE_NAME
    ;;
  stop)
    sudo systemctl stop $SERVICE_NAME
    ;;
  status)
    sudo systemctl status $SERVICE_NAME
    ;;
  restart)
    sudo systemctl restart $SERVICE_NAME
    ;;
  *)
    echo "Usage: $0 {start|stop|status|restart}"
    exit 1
    ;;
esac

Set the script to be executable:

sudo chmod +x /usr/local/bin/myapp

Now you can use the following commands to manage the application:

  • Start: myapp start
  • Stop: myapp stop
  • Status: myapp status
  • Restart: myapp restart

Common Issues and Solutions

Status Error (status=217/USER)

  • Issue: Service fails to start, showing status=217/USER
  • Solution: Verify that the user specified in myapp.service exists, check with id <your_username>

Unable to Connect to the Application

  • Issue: Service is running but cannot be accessed in the browser
  • Solution: Check firewall settings, ensure traffic on port 5000 is allowed
    sudo ufw allow 5000/tcp  # If using UFW
    

Permission Issues

  • Issue: Service cannot write logs or access files
  • Solution: Ensure User/Group settings are correct, and the user has appropriate permissions for the necessary files and directories

Conclusion

Through this complete process, we’ve successfully packaged a simple Flask application as a Linux system service, and achieved:

  1. Auto-start on boot: Configured through the systemd service unit file
  2. Automatic restart: Recovers automatically when the application exits abnormally
  3. Convenient management: Provides simple command-line instructions for service management

This method is not only applicable to Flask applications but can also be applied to other Python web frameworks such as Django, FastAPI, etc. Depending on your project requirements, you may need further optimization, such as adding logging, monitoring, or more complex environment variable settings.

Disclaimer: All reference materials on this website are sourced from the internet and are intended for learning purposes only. If you believe any content infringes upon your rights, please contact me at csnote.cc@gmail.com, and I will remove the relevant content promptly.


Feedback Welcome: If you notice any errors or areas for improvement in the articles, I warmly welcome your feedback and corrections. Your input will help this blog provide better learning resources. This is an ongoing process of learning and improvement, and your suggestions are valuable to me. You can reach me at csnote.cc@gmail.com.