Розібратися, як влаштована твоя програма на сервері, дописати до неї власну адресу відповіді й перевірити, що вона працює цілодобово — навіть коли твій комп’ютер вимкнено.
Замість <логін> разом із дужками підстав свій — той, який тобі видали на першому занятті. Логін має вигляд bohdan.g9: ім’я, крапка, номер групи. Через цей пропуск адреси написані тут текстом, а не посиланнями: клікнути можна лише на сам сервер — http://91.219.61.4/. Кабінет — сторінка, де видно, які пункти автоперевірки тобі вже зараховано.
Термінал — вікно, у якому команди набирають текстом і у відповідь отримують текст; кнопок і меню там немає. SSH (secure shell) — спосіб працювати в терміналі чужого комп’ютера: команду ти набираєш у себе, виконується вона на сервері, а результат друкується в тебе на екрані. Рядок «Вхід на сервер» — і є та команда, якою це роблять.
API — набір адрес, за якими дані забирає інша програма, а не людина. Докладніше про це в теорії.
Твоя програма на Python почне відповідати на запити з інтернету: будь-хто, хто відкриє адресу /u/<логін>/api/ping, отримає відповідь із твоїм іменем. Ти впишеш дані свого проєкту у файл-опис, додаси власний ендпоінт — ще одну адресу, за якою твоя програма щось відповідає, — і перевіриш роботу з сервера й із браузера.
Далі ти перевіриш, що ця програма працює без тебе: подивишся, чи ввімкнено автозапуск, вийдеш із сервера й переконаєшся, що відповіді й далі приходять, а потім примусово зупиниш програму й подивишся, як система запускає її знову за кілька секунд.
Бекенд — програма, яка постійно працює на сервері й відповідає на запити. Сервер — комп’ютер, який увімкнений цілодобово і має адресу в інтернеті; наш сервер має адресу 91.219.61.4. Те, що ти бачиш на екрані — сторінку, кнопки, текст — називають фронтендом; ним ми займемося на занятті 05.
Коли ти відкриваєш будь-яку адресу, браузер надсилає на сервер HTTP-запит. HTTP — це набір правил, за якими програми в інтернеті обмінюються повідомленнями. У запиті головні дві речі:
GET означає «віддай мені дані», POST — «прийми ці дані», DELETE — «видали». Коли ти просто вводиш адресу в браузері, він завжди надсилає GET. Сьогодні ми працюємо лише з GET.91.219.61.4/u/bohdan.g9/api/ping шлях — це /u/bohdan.g9/api/ping.У відповідь сервер надсилає код відповіді — тризначне число, яке коротко каже, чим усе скінчилося. Ці числа доведеться знати напам’ять, вони будуть на кожному занятті до кінця курсу.
| Код | Що означає | Коли ти це побачиш |
|---|---|---|
| 200 | Запит виконано | Усе гаразд, у відповіді є дані |
| 404 | Такого шляху немає | Помилка в адресі або ендпоінт ще не написано |
| 500 | Програма на сервері завершилася з помилкою | Запит дійшов до твого коду, і під час виконання сталася помилка |
| 502 | Твоя програма не відповіла серверу | Її зупинено або вона саме перезапускається |
Приклад із твого життя: гра на телефоні пише «немає з’єднання з сервером». Це означає, що її бекенд не відповів — або зупинився, або мережа не дійшла. Після сьогоднішнього заняття ти сам відповідаєш за те, щоб таке не сталося з твоїм сервісом.
Ти відкрив у браузері адресу свого API і бачиш сторінку з написом «500 Internal Server Error». Що сталося?
Звичайна сторінка — це HTML: текст разом з оформленням, зроблений для людини. Коли дані забирає інша програма, оформлення тільки заважає. Для цього є JSON — текстовий формат запису даних, який легко читає будь-яка мова програмування.
{"status": "ok", "author": "Богдан"}Ти вже знаєш цю структуру: у Python це словник. У фігурних дужках — пари «ключ: значення», ключ у лапках, пари через кому. Значенням може бути число, рядок, список у квадратних дужках або інший такий самий набір у фігурних.
API (від application programming interface) — набір адрес, за якими дані забирає програма, а не людина. Приклад: застосунок прогнозу погоди на твоєму телефоні не відкриває сайт — він звертається до API і отримує JSON із числами, а вже сам малює з них картинку. Твій сервіс сьогодні починає працювати так само.
Окрема адреса всередині API називається ендпоінт — точка, за якою сервер щось конкретне відповідає. У тебе їх сьогодні буде три: /api/ping, /api/about і той, який ти напишеш сам.
Однокласник пише мобільний застосунок і хоче показувати в ньому кількість твоїх записів. Що зручніше віддати йому у відповіді?
На сервері 91.219.61.4 одночасно працюють програми всієї групи. Щоб система розуміла, кому передати запит, кожна програма займає свій порт — число від 1 до 65535. Твій порт видано разом з акаунтом, він виглядає як 9536. Одне число — одна програма: якщо запустити другу на тому самому порту, вона одразу завершиться з повідомленням address already in use.
Твоя програма слухає порт не на всіх адресах, а тільки на 127.0.0.1. Це особлива адреса, яка означає «цей самий комп’ютер»; її ще називають localhost. З інтернету на неї зайти неможливо — вона в кожного комп’ютера своя й веде сама на себе.
Ззовні всі заходять на порт 80 — це порт, який браузер підставляє сам, коли адреса починається з http://. На порту 80 працює nginx — програма, яка приймає всі запити на сервер і дивиться на шлях:
/u/bohdan.g9/api/… — nginx передає запит програмі Богдана на її порт, отримує відповідь і повертає її браузеру. Таку передачу називають проксі;/u/bohdan.g9/ — nginx віддає файл із теки ~/www, наприклад index.html.Налаштування nginx робить викладач; тобі його чіпати не треба. Але знати цей порядок важливо: коли API не відповідає, ти маєш розуміти, де саме шукати причину — у nginx чи у своїй програмі.
На сервері ти виконав команду curl http://127.0.0.1:9536/api/ping (curl надсилає запит за вказаною адресою і друкує відповідь текстом) — відповідь є. Друг удома вводить у себе в браузері http://127.0.0.1:9536/api/ping — нічого не відкривається. Чому?
Віртуальне оточення (скорочено venv) — окрема тека з бібліотеками Python для конкретного проєкту. Вона потрібна, щоб проєкти не заважали один одному версіями бібліотек. Програма, яка встановлює бібліотеки в таке оточення, називається pip. У нас одне спільне оточення на всю групу — /opt/club/venv, і потрібні бібліотеки там уже встановлені, тому pip запускати не треба.
З того, що вже стоїть у цьому оточенні, тобі сьогодні важливі дві речі:
Ось як виглядає ендпоінт у файлі ~/app/main.py:
@app.get("/api/ping")
def ping():
return {"status": "ok", "author": CFG["product"]["author"]}Рядок @app.get("/api/ping") над функцією називають декоратором. Він каже FastAPI: коли надійде запит методом GET на шлях /api/ping — виклич цю функцію. Функція повертає звичайний словник Python, а FastAPI сам перетворює його на JSON. Нічого більше писати не потрібно.
Звідки береться ім’я автора? З файла ~/app/project.yaml — це маніфест проєкту, тобто короткий опис, який читає програма: назва продукту, автор, для кого сервіс і які в нього функції. Формат YAML — текст, у якому вкладеність показана відступом зліва: чим глибше рядок вкладений, тим більший у нього відступ, а всі рядки одного рівня мають однаковий відступ. У наших файлах один рівень — це два пробіли. Із цього файла читає дані і твоя програма, і скрипт автоперевірки. Якщо там написано «Ім’я» — саме це слово побачить перевірка, і критерій не зарахує.
Останнє про цей файл: uvicorn читає main.py і project.yaml один раз, коли запускається. Якщо ти змінив файл, а програму не перезапустив, сервер і далі віддаватиме стару версію. Як її перезапускати — у наступному розділі.
Ще одна команда, яка тобі знадобиться: curl — вона надсилає HTTP-запит прямо з термінала й друкує відповідь текстом. Це швидший спосіб перевірки, ніж відкривати браузер, і він працює навіть тоді, коли поруч немає екрана з браузером.
Ти вписав своє ім’я у project.yaml, зберіг файл, оновив у браузері сторінку /api/ping — а там усе ще «Ім’я». Що ти пропустив?
Процес — запущена програма. Коли ти запускаєш uvicorn руками в терміналі, процес належить твоєму сеансу SSH. Закриваєш вікно — сеанс закінчується, процес зупиняється разом із ним. Сайт після цього не відповідає.
Служба — програма, якою керує сама операційна система. Вона запускає її, коли сервер вмикається, стежить, чи процес працює, і запускає його знову, якщо той завершився. Твій сеанс SSH тут ні до чого.
У Linux службами керує systemd — частина системи, яка запускає й зупиняє все, що має працювати постійно. Служби бувають системні (їх налаштовує адміністратор) і користувацькі — твої власні. Тому в усіх командах є --user: він означає «моя служба, а не загальносерверна». Твоя служба зветься club-api.
Опис служби зберігається в текстовому unit-файлі ~/.config/systemd/user/club-api.service. У ньому написано, яку команду запускати, з якої теки і що робити, коли процес завершився. Файл уже готовий, редагувати його не треба, але два рядки варто прочитати:
ExecStart=/opt/club/venv/bin/uvicorn main:app --host 127.0.0.1 --port 9536
Restart=always
RestartSec=3Restart=always — вказівка systemd: якщо процес завершився з будь-якої причини, запусти його знову. RestartSec=3 — зачекай перед цим три секунди. Саме ці два рядки роблять так, що після аварійного завершення програма запускається знову без твоєї участі.
Далі два слова, які легко переплутати:
start — запусти службу зараз, у цю секунду;enable — запам’ятай, що цю службу треба запускати автоматично щоразу, коли вмикається сервер. Стан перевіряється командою systemctl --user is-enabled club-api, правильна відповідь — enabled.І окремо — linger. За звичайних налаштувань systemd зупиняє всі користувацькі служби, щойно людина виходить із сервера. Linger — це дозвіл для акаунта тримати свої служби запущеними без активного сеансу. Його вмикає викладач від імені адміністратора. Без linger твоя служба зупинялася б щоразу, коли ти виходиш із сервера, і сайт із API переставали б відповідати.
Коли щось іде не так, дивись журнал — це файл, куди systemd складає повідомлення служби: усе, що вона надрукувала, і всі помилки. Читається командою journalctl --user -u club-api -n 30: показати останні 30 рядків журналу служби club-api.
Ти налаштував службу, перевірив, що API відповідає, закрив термінал і пішов додому. Через дві години відкриваєш свою адресу з телефона — сторінка й API працюють. Завдяки чому?
Скрипт автоперевірки примусово зупиняє твій процес, чекає шість секунд і знову запитує /api/ping. У відповідь приходить 200. Що спрацювало?
| Слово | Що означає |
|---|---|
| термінал, SSH | Вікно, у якому команди набирають текстом, і спосіб виконувати їх на сервері зі свого комп’ютера |
| бекенд | Програма на сервері, яка відповідає на запити |
| HTTP | Правила, за якими браузер і сервер обмінюються повідомленнями |
| метод, шлях | Дві головні частини запиту: що зробити і з чим |
| код відповіді | Число, яким сервер повідомляє результат: 200, 404, 500, 502 |
| заголовки | Службові рядки на початку відповіді; у першому з них — код відповіді |
| JSON | Текстовий формат даних, схожий на словник Python |
| API | Набір адрес, за якими дані забирає інша програма |
| ендпоінт | Одна адреса всередині API, за якою сервер щось відповідає |
| порт | Число, за яким система розрізняє програми на одному комп’ютері |
| 127.0.0.1 | Адреса «цей самий комп’ютер», ззовні недоступна |
| nginx | Програма на порту 80, яка передає запити твоїй програмі |
| venv, pip | Тека з бібліотеками проєкту і програма, яка їх встановлює |
| FastAPI, uvicorn | Фреймворк для опису ендпоінтів і програма, що слухає порт |
| маніфест, YAML | Файл project.yaml з описом проєкту і формат, у якому він написаний |
| curl | Команда, що надсилає запит із термінала й друкує відповідь |
| змінна | Ім’я, замість якого термінал підставляє збережений текст: $PORT |
| процес, служба | Запущена програма і програма під наглядом системи |
| systemd, unit-файл | Частина Linux, що керує службами, і текстовий опис однієї служби |
| enable, linger | Автозапуск служби і дозвіл їй працювати без сеансу SSH |
| журнал | Записи служби, які показує journalctl |
Виконуй кроки послідовно. Скрізь, де у команді є $USER, підставляти нічого не треба — на сервері ця змінна вже містить твій логін.
ssh <логін>@91.219.61.4Замість <логін> разом із дужками підстав свій, тобто набери ssh bohdan.g9@91.219.61.4. Пароль під час введення не показується взагалі: ні крапок, ні зірочок. Це нормально, набирай і натискай Enter.
systemctl --user status club-apiУ виводі шукай рядок Active:. Що там може бути:
active (running) — служба працює, все гаразд;inactive (dead) — служба зупинена, запусти командою systemctl --user start club-api;failed — служба намагалася запуститись і не змогла. Причину дивись у кроці 12.Нижче видно Main PID — номер процесу в системі, і кілька останніх рядків журналу. Вийти з перегляду — клавіша q.
grep ExecStart ~/.config/systemd/user/club-api.serviceКоманда grep шукає рядок у файлі й друкує його. Ти побачиш команду запуску, а в кінці — --port і твоє число. Запиши його: воно твоє на весь курс.
Щоб не набирати число щоразу, збережи його у змінну — це ім’я, замість якого термінал підставляє збережений текст. Далі досить написати $PORT, і туди підставиться твоє число. Змінна живе до кінця цього сеансу термінала: після виходу з сервера її треба задати заново.
PORT=$(grep -o -- '--port [0-9]*' ~/.config/systemd/user/club-api.service | grep -o '[0-9]*')
echo "мій порт: $PORT"Як читати цей рядок. Запис $( ) означає «виконай команду в дужках і підстав сюди те, що вона надрукувала». Ключ -o каже grep друкувати не весь рядок, а лише знайдений шматок; два дефіси -- потрібні, щоб grep не сприйняв --port за свій власний ключ. Перший grep знаходить --port 9536, другий залишає з цього саме число. Перевір, що echo надрукував те саме число, яке ти щойно бачив.
curl http://127.0.0.1:$PORT/api/pingМаєш побачити рядок виду {"status":"ok","author":"Ім’я"}. Це означає: програма працює й слухає свій порт. Ім’я поки чуже — виправиш у кроці 6.
Щоб побачити ще й код відповіді, додай ключ -i. Тоді curl надрукує ще й заголовки — службові рядки на початку відповіді, у яких сервер повідомляє код відповіді, тип даних та іншу технічну інформацію. Браузер їх не показує, але отримує так само:
curl -i http://127.0.0.1:$PORT/api/pingПерший рядок має бути HTTP/1.1 200 OK.
curl -i http://91.219.61.4/u/$USER/api/pingТепер запит іде довшим шляхом: спочатку до nginx на порт 80, звідти — до твоєї програми. Якщо крок 4 працює, а цей дає 502 — проблема в передачі між nginx і твоєю програмою, скажи про це викладачеві.
Відкрий ту саму адресу в браузері на своєму комп’ютері. Браузер покаже той самий JSON — просто текстом.
nano ~/app/project.yamlnano — простий текстовий редактор у терміналі. Стрілками рухайся по тексту, набирай як завжди. Зберегти — Ctrl+O, потім Enter. Вийти — Ctrl+X.
Заповни розділ product даними свого проєкту — тими, що ти записав на першому занятті у файл BRIEF.md (це текстовий опис задуму: назва, для кого сервіс, що він уміє). Якщо не пам’ятаєш, де цей файл, подивись список своїх файлів командою ls ~/app і прочитай його командою cat ~/app/BRIEF.md. Ось приклад, як має вийти:
product:
name: "Трекер домашніх завдань"
author: "Богдан"
target_user: "мій молодший брат, який забуває, що задали"
features:
- "додати завдання з датою"
- "позначити виконане"
- "показати список на сьогодні"Три правила YAML, через які файл найчастіше перестає читатися:
name: "Трекер", а не name:"Трекер";systemctl --user restart club-api
curl http://127.0.0.1:$PORT/api/pingТепер у полі author має бути твоє ім’я. Запам’ятай цю пару команд: після кожної зміни main.py чи project.yaml — спочатку restart, потім перевірка.
cat ~/app/main.pycat друкує вміст файла на екран. Знайди в ньому обидва наявні ендпоінти й перевір, що розумієш кожен рядок: декоратор, назву функції, словник у return. Питання «поясни цей рядок» буде на початку наступного заняття.
Перевір другий ендпоінт — він віддає більше даних:
curl http://91.219.61.4/u/$USER/api/aboutУ полі features має бути список із трьох функцій, які ти щойно вписав у крок 6. Якщо там порожні квадратні дужки [] — повернись і заповни features.
nano ~/app/main.pyОпустися стрілкою вниз у самий кінець файла й з нового рядка додай цей код. Рядок @app.get має починатися від лівого краю, без відступу; відступи всередині функції — чотири пробіли, як у сусідніх функціях:
@app.get("/api/user")
def user():
"""Для кого цей сервіс. Дані беремо з project.yaml."""
return {
"product": CFG["product"]["name"],
"for_whom": CFG["product"]["target_user"],
}Що тут відбувається: декоратор реєструє новий шлях /api/user, функція читає з уже завантаженого маніфесту два значення й повертає їх словником. FastAPI перетворить його на JSON.
Збережи, перезапусти, перевір:
systemctl --user restart club-api
curl http://91.219.61.4/u/$USER/api/userЯкщо у відповідь прийшов {"detail":"Not Found"} — так FastAPI відповідає на шлях, якого не знає. Отже, служба не перезапустилася або код додано не в той файл. Якщо служба перейшла у стан failed — у коді помилка, дивись крок 12.
systemctl --user is-active club-api
systemctl --user is-enabled club-api
loginctl show-user $USER -p Linger --valueПравильні відповіді по черзі: active, enabled, yes.
disabled — служба працює зараз, але після перезавантаження сервера сама не запуститься. Виправ: systemctl --user enable --now club-api. Ключ --now означає «і запусти одразу».no — це вмикає викладач від імені адміністратора, сам ти не зможеш. Скажи про це на занятті.Зараз ти навмисно зупиниш свій процес найрізкішим способом. Сигнал SIGKILL завершує процес негайно: програма навіть не отримує цього сигналу, тому не встигає нічого зберегти й не може скасувати зупинку. Це саме те, що робить скрипт автоперевірки.
systemctl --user kill -s SIGKILL club-api
systemctl --user is-active club-apiДруга команда одразу після першої, найімовірніше, покаже activating, inactive або failed — це очікувано. Порахуй уголос до п’яти й виконай перевірку знову:
systemctl --user is-active club-api
curl http://127.0.0.1:$PORT/api/pingМає бути active і звична відповідь із твоїм іменем. Пауза між зупинкою і новим запуском — три секунди, її задає рядок RestartSec=3.
Тепер друга перевірка — вихід із сервера:
exitТермінал повернувся на твій комп’ютер. Онови в браузері сторінку http://91.219.61.4/u/<логін>/api/ping — вона відповідає, хоча твого сеансу на сервері вже немає. Це працює linger.
Кроки 12 і 13 знову виконуються на сервері, тому зайди туди ще раз:
ssh <логін>@91.219.61.4Змінна PORT після виходу зникла разом із попереднім сеансом. Коли зайдеш, задай її тією самою командою, що в кроці 3 — інакше в наступних командах замість числа підставиться порожнє місце:
PORT=$(grep -o -- '--port [0-9]*' ~/.config/systemd/user/club-api.service | grep -o '[0-9]*')journalctl --user -u club-api -n 30Останні 30 рядків журналу. Шукай знизу вгору перший рядок зі словом Error — там буде назва помилки й номер рядка у файлі. Найчастіші випадки:
IndentationError — збилися відступи в main.py;SyntaxError — пропущена дужка, кома або двокрапка;yaml.scanner.ScannerError — помилка формату в project.yaml: табуляція або немає пробілу після двокрапки.Виправ помилку, збережи файл, виконай systemctl --user restart club-api і перевір стан ще раз.
cat ~/www/index.htmlПеревірка L02.6 шукає на цій сторінці назву продукту — точно ту саму, що в project.yaml. Якщо назви немає або вона інша, відредагуй сторінку: nano ~/www/index.html.
Потім відкрий у браузері свій кабінет http://91.219.61.4/k/<логін>/ і подивись, які критерії вже зараховано. Перевірка виконується не миттєво — почекай кілька хвилин і онови сторінку.
Шість пунктів, кожен зараховується окремо. Починай з L02.1: поки він не проходить, не пройдуть і L02.2 та L02.5 — вони теж вимагають, щоб служба працювала. L02.3, L02.4 і L02.6 перевіряються незалежно від нього.
| Код | Критерій | Що робить скрипт | Якщо не зараховано |
|---|---|---|---|
| L02.1 | /api/ping відповідає 200 і віддає JSON | Відкриває ззовні /u/<логін>/api/ping, чекає код 200 і JSON із ключами status та author. |
Перевір по черзі: systemctl --user status club-api — чи active; curl http://127.0.0.1:$PORT/api/ping — чи працює локально (якщо ти щойно зайшов на сервер заново, спочатку задай PORT командою з кроку 3, інакше замість числа підставиться порожнє місце й curl видасть незрозумілу помилку). Якщо локально працює, а ззовні ні — скажи викладачеві, це налаштування nginx. |
| L02.2 | автор у відповіді збігається з project.yaml | Читає product.author з ~/app/project.yaml і звіряє з полем author у відповіді. Поки там заготовка «Ім’я» — не зараховує. |
Впиши своє ім’я без прізвища у project.yaml і перезапусти службу. Значення мають збігатися дослівно, разом із великими літерами. |
| L02.3 | служба ввімкнена в автозапуск | Виконує systemctl --user is-enabled club-api і чекає відповіді enabled. Це означає, що після перезавантаження сервера служба запуститься сама. |
Виконай systemctl --user enable --now club-api. Якщо у відповідь помилка — скопіюй її текст і покажи викладачеві. |
| L02.4 | служба працює далі після виходу із SSH (linger) | Виконує loginctl show-user <логін> -p Linger --value і чекає yes. |
Це налаштовує викладач від імені адміністратора: loginctl enable-linger <логін>. Сам ти виправити не можеш — просто скажи про це. |
| L02.5 | служба сама запускається після примусової зупинки | Примусово зупиняє процес сигналом SIGKILL, чекає шість секунд і перевіряє, чи служба знову active. Працює завдяки Restart=always. |
Перевір, що в ~/.config/systemd/user/club-api.service є рядок Restart=always, і виконай systemctl --user daemon-reload. Якщо служба щоразу завершується з помилкою одразу після запуску, systemd після кількох спроб припиняє її запускати: виправ помилку в коді, потім systemctl --user reset-failed club-api і restart. |
| L02.6 | сторінка учня відкривається | Відкриває http://91.219.61.4/u/<логін>/, чекає код 200 і шукає в тексті сторінки назву продукту з project.yaml. |
Файл має лежати саме в ~/www/index.html. Назва на сторінці має збігатися з product.name дослівно. Якщо там ще текст заготовки — заміни його. |
/api/plan. Додай у main.py ще один ендпоінт, який повертає список із трьох рядків — що ти плануєш додати до сервісу найближчим часом. Список пиши прямо в коді: return {"next": ["...", "...", "..."]}. Не забудь перезапустити службу й перевірити відповідь через curl.http://91.219.61.4/u/<логін>/api/about. Так ти перевіряєш саме те, що бачить сторонній відвідувач, а не те, що видно з домашньої мережі. Зроби скриншот.is-active знову покаже active. Запиши це число. Виходити з сервера цього разу не треба.nano ~/app/README.md і додай два рядки: свій порт і час відновлення з пункту 3. Якщо в файлі є розділ «Як запустити» — пиши в нього; якщо такого розділу немає, додай рядки в кінець файла. Якщо файла ще немає, nano відкриє порожній — напиши рядки й збережи.На початку наступного заняття буде питання «поясни рядок»: викладач покаже будь-який рядок із твого main.py і попросить сказати, що він робить.
Найчастіша ситуація за сьогодні. uvicorn читає main.py і project.yaml один раз під час запуску. Поки не буде systemctl --user restart club-api, у пам’яті лишається попередня версія. Якщо після перезапуску дані все одно старі — перевір, що редагував файл у теці ~/app, а не копію в іншому місці: ls -l ~/app/project.yaml покаже час останньої зміни.
Виконай journalctl --user -u club-api -n 30 і читай знизу вгору. Перший рядок з Error назве файл і номер рядка. Помилка майже завжди у тому, що ти щойно міняв. Якщо служба багато разів поспіль завершувалася з помилкою, systemd припиняє спроби її запускати — тоді після виправлення потрібні дві команди: systemctl --user reset-failed club-api, потім systemctl --user restart club-api.
Код 502 означає: nginx звернувся до твоєї програми й не отримав відповіді. Причини за частотою: служба саме в цю секунду перезапускається — почекай три секунди й повтори; служба у стані failed — дивись попередній пункт; порт у unit-файлі не збігається з тим, який знає nginx. Останнє сам не виправляй: порт видано разом з акаунтом, міняти його не можна, скажи викладачеві.
Це помилка формату у project.yaml. Дві причини покривають майже всі випадки: у файл потрапила табуляція замість пробілів, або після двокрапки немає пробілу. Перевірити файл окремо від служби можна так:
cd ~/app && /opt/club/venv/bin/python -c "import yaml; print(yaml.safe_load(open('project.yaml'))['product'])"Якщо надрукувався словник із твоїми даними — файл цілий, причина в іншому. Якщо помилка — у її тексті буде номер рядка, з якого починати.
Спочатку перевір розкладку клавіатури й Caps Lock: пароль не показується під час введення, тому помилку не видно. Після кількох невдалих спроб підряд адресу твоєї мережі тимчасово блокує fail2ban — програма на сервері, яка стежить за невдалими входами й закриває доступ тим, хто підбирає пароль. Тоді підключитися не вийде навіть із правильним паролем: блокування знімається саме, зазвичай за 10–15 хвилин. Якщо чекати ніколи, скажи викладачеві — він зніме блокування одразу. Якщо пароль ти вже змінював командою passwd на першому занятті, діє новий, а не той, що видали на папірці.