Установка и запуск TODO-приложения на VPS с помощью Flask и systemd

VpsSimpleToDo — это простой TODO-приложение на Flask, которое вы можете развернуть на своём сервере за несколько шагов. В этой статье я подробно расскажу, как установить и запустить проект на VPS.


Шаг 1: Клонируем проект

git clone https://gitverse.ru/BigGratz/VpsSimpleToDo
cd VpsSimpleToDo

Шаг 2: Установка зависимостей

Создайте и активируйте виртуальное окружение:

python3 -m venv venv
source venv/bin/activate

Установите зависимости:

pip install -r requirements.txt

Содержимое requirements.txt

flask

Шаг 3: Запуск приложения вручную

python app.py

Оно будет доступно по адресу: http://127.0.0.1:5000/


Шаг 4: Настройка systemd для автоматического запуска

Создайте файл flask_app.service:

sudo nano /etc/systemd/system/flask_app.service

Содержимое flask_app.service

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

[Service]
User=youruser
Group=www-data
WorkingDirectory=/home/youruser/VpsSimpleToDo
Environment="PATH=/home/youruser/VpsSimpleToDo/venv/bin"
ExecStart=/home/youruser/VpsSimpleToDo/venv/bin/gunicorn -w 1 -b 0.0.0.0:5000 app:app

[Install]
WantedBy=multi-user.target

Замените youruser на вашего системного пользователя.

sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable flask_app
sudo systemctl start flask_app

Проверьте статус:

sudo systemctl status flask_app

Структура проекта

VpsSimpleToDo/
├── app.py
├── requirements.txt
├── static/
│   └── styles.css
├── templates/
│   └── index.html
└── flask_app.service (создаётся отдельно)

Исходный код файлов

app.py

from flask import Flask, render_template, request, redirect

app = Flask(__name__)
tasks = []

@app.route('/')
def index():
    return render_template('index.html', tasks=tasks)

@app.route('/add', methods=['POST'])
def add():
    task = request.form.get('task')
    if task:
        tasks.append(task)
    return redirect('/')

@app.route('/delete/<int:task_id>')
def delete(task_id):
    if 0 <= task_id < len(tasks):
        tasks.pop(task_id)
    return redirect('/')

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

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Simple TODO</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
    <div class="container">
        <h1>My TODO List</h1>
        <form action="/add" method="POST">
            <input type="text" name="task" placeholder="Enter new task" required>
            <button type="submit">Add</button>
        </form>
        <ul>
            {% for task in tasks %}
                <li>
                    {{ task }}
                    <a href="/delete/{{ loop.index0 }}">Delete</a>
                </li>
            {% endfor %}
        </ul>
    </div>
</body>
</html>

static/styles.css

body {
    font-family: Arial, sans-serif;
    background: #f4f4f4;
    margin: 0;
    padding: 0;
}

.container {
    max-width: 500px;
    margin: 50px auto;
    background: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

h1 {
    text-align: center;
}

form {
    display: flex;
    gap: 10px;
    margin-bottom: 20px;
}

input[type="text"] {
    flex: 1;
    padding: 10px;
    font-size: 16px;
}

button {
    padding: 10px 20px;
    font-size: 16px;
    background: #007BFF;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

ul {
    list-style: none;
    padding: 0;
}

li {
    background: #eee;
    margin-bottom: 10px;
    padding: 10px;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
}

Заключение

Теперь у вас есть готовое к использованию простое TODO-приложение на Flask, запущенное через systemd на вашем VPS. Вы можете использовать это решение как базу для более сложных проектов.