Tarkibga o'tish

Backend ilovani xizmat sifatida ishga tushirish

O'z systemd xizmatini yaratish maqolasida oddiy demo skript yordamida .service faylini qanday yozish ko'rib chiqildi. Bu maqola o'sha bilimni real vaziyatga qo'llaydi: kichik Python backend ilovasini production talablariga yaqin bo'lgan systemd xizmatiga aylantiradi — alohida foydalanuvchi, muhit fayli, avtomatik tiklanish va asosiy xavfsizlik kuchaytirish (hardening) bilan. Bu reverse proxy ortida turadigan har qanday backend uchun ham kerak bo'ladigan poydevor: oldiga veb-server qo'yilishidan oldin u aynan shunday barqaror, nazorat ostidagi xizmat sifatida ishlashi kerak.

Maqsad va yakuniy natija

Bu laboratoriya ishi oxirida:

  • tizimga kira olmaydigan, deploy nomli alohida tizim foydalanuvchisi mavjud bo'ladi;
  • backend ilova root huquqlarisiz, shu foydalanuvchi nomidan ishlaydi;
  • ilova konfiguratsiyasi (masalan, port) unit faylning o'zida emas, alohida muhit faylida turadi;
  • server qayta yuklanganda ilova avtomatik ishga tushadi va kutilmagan chiqishdan keyin avtomatik tiklanadi;
  • ilova log'lari alohida log faylisiz journalctl orqali ko'rinadi.

Boshlang'ich holat

python3 o'rnatilgan (sukut bo'yicha mavjud) Ubuntu Server LTS ishlaydigan, o'chirib tashlasa bo'ladigan sinov VM’i yoki laboratoriya katalogi. Bu laboratoriya hech qanday real production trafigi yaratmaydi — maqsad faqat biror narsani to'g'ri xizmat sifatida ishga tushirish mexanikasini mustahkamlash.

python3 --version
Python 3.12.3

Talablar

  • sudo huquqlariga ega foydalanuvchi;
  • disk joyi va tarmoq — bu yerda muammo emas, chunki ilova lokal va tashqi ulanish talab qilmaydi;
  • O'z systemd xizmatini yaratish maqolasidagi Type=, ExecStart= va daemon-reload tushunchalari.

Xavfsizlik va snapshot haqida eslatma

Bu laboratoriya yangi foydalanuvchi yaratish va yangi port’ni tinglaydigan xizmatni ishga tushirishni o'z ichiga oladi — ikkalasi ham ortga qaytariladigan amallar, lekin baribir o'chirib tashlasa bo'ladigan sinov VM’ida bajarilgani ma’qul. Boshlashdan oldin joriy holatni qayd qiling:

systemctl list-units --type=service --state=running | wc -l

Bu son laboratoriya oxirida aynan bitta yangi xizmat qo'shilganini tasdiqlash uchun ishlatiladi.

Bosqichma-bosqich vazifalar

1-qadam: alohida foydalanuvchi yaratish

sudo useradd --system --no-create-home --shell /usr/sbin/nologin deploy
  • --system — past UID oralig'ida, tizim xizmatlari uchun mo'ljallangan foydalanuvchi yaratadi;
  • --no-create-home — uy katalogi kerak emas, chunki ilova o'z katalogidan ishlaydi;
  • --shell /usr/sbin/nologin — bu foydalanuvchi interaktiv tarzda tizimga kira olmaydi; u faqat xizmatni ishga tushirish uchun mavjud.

Tekshirish:

id deploy
uid=998(deploy) gid=998(deploy) groups=998(deploy)

2-qadam: ilova katalogi va kodini tayyorlash

sudo mkdir -p /opt/backend-demo
sudo nano /opt/backend-demo/app.py
/opt/backend-demo/app.py
import http.server
import os
import socketserver

PORT = int(os.environ.get("APP_PORT", "8080"))

class Handler(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-Type", "text/plain")
        self.end_headers()
        self.wfile.write(b"Backend app is running\n")

with socketserver.TCPServer(("127.0.0.1", PORT), Handler) as httpd:
    print(f"Listening on 127.0.0.1:{PORT}")
    httpd.serve_forever()

Bu faqat Python standart kutubxonasidan foydalanadigan, tashqi bog'liqliklarsiz minimal HTTP server. Maqsad — haqiqiy ilova o'rnini bosadigan, tekshirish oson bo'lgan oddiy narsa; keyinroq uni xizmatning o'zi qanday sozlanganiga hech narsa o'zgartirmasdan haqiqiy ilova bilan almashtirish mumkin.

3-qadam: muhit faylini yaratish

sudo nano /opt/backend-demo/backend-demo.env
/opt/backend-demo/backend-demo.env
APP_PORT=8080

Konfiguratsiyani unit fayldan ajratib, alohida muhit faylida saqlash port yoki boshqa qiymatni o'zgartirish uchun unit faylni emas, faqat shu faylni tahrirlash kifoya ekanini anglatadi. Bunda daemon-reload ham kerak emas (faqat xizmatni restart qilish yetarli).

4-qadam: egalik va ruxsatlarni o'rnatish

sudo chown -R deploy:deploy /opt/backend-demo
sudo chmod 640 /opt/backend-demo/backend-demo.env

deploy foydalanuvchisi o'z ilovasi turgan katalogga egalik qilishi kerak; muhit fayli esa parol yoki boshqa maxfiy qiymatni saqlashi mumkinligi uchun faqat egasi va guruhi o'qiy oladigan qilib cheklanadi.

5-qadam: unit faylni yaratish

sudo nano /etc/systemd/system/backend-demo.service
/etc/systemd/system/backend-demo.service
[Unit]
Description=Backend demo application
After=network.target

[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/opt/backend-demo
EnvironmentFile=/opt/backend-demo/backend-demo.env
ExecStart=/usr/bin/python3 /opt/backend-demo/app.py
Restart=on-failure
RestartSec=5

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/backend-demo

[Install]
WantedBy=multi-user.target

Yangi qatorlar haqida izohlar:

Direktiva Vazifasi
EnvironmentFile= Nomlangan fayldagi KEY=VALUE qatorlarini muhit o'zgaruvchilari sifatida yuklaydi
NoNewPrivileges=true Jarayon va uning bolalari qo'shimcha huquqlarga ega bo'la olmaydi (masalan, setuid orqali)
ProtectSystem=strict ReadWritePaths= da ko'rsatilgan yo'llardan tashqari butun fayl tizimini xizmat uchun faqat o'qiladigan qiladi
ProtectHome=true /home, /root va /run/user ga kirishni butunlay to'sadi
ReadWritePaths= ProtectSystem=strict dan istisno sifatida yozish huquqi berilgan yagona katalog

Info

Bu direktivalar systemd ning sandboxing imkoniyatlariga misol — ular buzib olingan xizmat tizimning qolgan qismiga yetkazishi mumkin bo'lgan zararni cheklaydi. To'liq ro'yxat man systemd.exec da hujjatlashtirilgan.

Intervyuda

Bu demo 127.0.0.1:8080 ni band qiladi — bu istalgan foydalanuvchi ishlatishi mumkin bo'lgan yuqori port. Klassik qo'shimcha savol: root bo'lmagan xizmat 80 yoki 443 kabi imtiyozli port’ni qanday band qiladi? 1024 dan past portlar odatda root talab qiladi, lekin ularni olish uchun User=deploy dan voz kechish huquqsiz xizmatning butun ma’nosini yo'qqa chiqaradi. systemd’ga xos javob — buning o'rniga faqat o'sha bitta capability’ni berish:

[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE

Jarayon hali ham deploy sifatida ishlaydi, lekin endi past portlarni band qilishga ruxsat oladi — bu root sifatida ishlashdan ancha torroq huquq. (sysctl net.ipv4.ip_unprivileged_port_start ni pasaytirish yoki ilova o'z yuqori portida qolishi uchun TLS’ni reverse proxy’da tugatish — keng tarqalgan boshqa ikki javob.)

6-qadam: xizmatni faollashtirish

sudo systemctl daemon-reload
sudo systemctl enable --now backend-demo.service

Tekshirish

Har bir muhim qadamdan keyin holatni tasdiqlang:

systemctl status backend-demo.service

Bu Active: active (running) va enabled ni ko'rsatishi kerak.

curl http://127.0.0.1:8080/
Backend app is running
ps -o user,pid,cmd -C python3
USER       PID CMD
deploy    6301 /usr/bin/python3 /opt/backend-demo/app.py

USER ustunidagi deploy ilova root emas, alohida foydalanuvchi nomidan ishlayotganini tasdiqlaydi.

Kutilgan natija

Xizmat enabled va active (running) holatida, curl 127.0.0.1:8080 dan javob oladi va jarayon egasi root emas, deploy. systemctl list-units --type=service --state=running | wc -l natijasi boshlang'ich sondan aynan bittaga ko'p bo'lishi kerak.

Muammolarni hal qilish bo'yicha maslahatlar

  • Active: failed — avval eng so'nggi xatoni journalctl -u backend-demo.service -n 30 bilan o'qing (journalctl maqolasida chuqur ko'rib chiqiladi).
  • "Permission denied" — odatda chown/chmod qadami to'liq bajarilmaganini yoki ProtectSystem=strict ostida yozish huquqi kerak bo'lgan yo'l ReadWritePaths= ga qo'shilmaganini bildiradi.
  • curl: Connection refused — xizmat hali ishga tushmagan (systemctl status bilan tekshiring) yoki muhit faylida APP_PORT boshqa qiymatga o'zgartirilgan.
  • Xizmat ishga tushib, darhol ishdan chiqadi — ExecStart= absolyut yo'ldan foydalanayotganini va interpretator to'g'ridan-to'g'ri chaqirilayotganini (bu misoldagidek, /usr/bin/python3) tekshiring; bu Type=simple ostida talab qilinadi.

Ortga qaytarish va tozalash

Sinov tugagach yoki xizmatni butunlay olib tashlash kerak bo'lsa:

sudo systemctl disable --now backend-demo.service
sudo rm /etc/systemd/system/backend-demo.service
sudo systemctl daemon-reload
sudo rm -rf /opt/backend-demo
sudo userdel deploy

Danger

rm -rf /opt/backend-demo faqat shu laboratoriya uchun yaratilgan katalogni o'chiradi — ishga tushirishdan oldin yo'lni diqqat bilan o'qing, chunki rm -rf tasdiq so'ramasdan o'chiradi va buni ortga qaytarib bo'lmaydi. userdel faqat shu laboratoriya uchun yaratilgan deploy foydalanuvchisiga qaratilishi kerak — production tizimda xuddi shu nomli boshqa foydalanuvchi allaqachon mavjud emasligiga ishonch hosil qiling.

Yakuniy baholash mezoni

Quyidagilarning hammasi to'g'ri bo'lsa, laboratoriya ishi bajarilgan hisoblanadi:

  • systemctl is-active backend-demo.service active qaytaradi;
  • systemctl is-enabled backend-demo.service enabled qaytaradi;
  • curl http://127.0.0.1:8080/ muvaffaqiyatli javob qaytaradi;
  • ps -o user -C python3 --no-headers root emas, deploy ni ko'rsatadi.

Xulosa

Haqiqiy backend ilovani systemd xizmatiga aylantirish O'z systemd xizmatini yaratish maqolasidagi asosiy direktivalar ustiga uchta narsa qo'shadi: alohida, huquqsiz foydalanuvchi; konfiguratsiyani ham koddan, ham unit fayldan ajratadigan EnvironmentFile=; va ProtectSystem=/NoNewPrivileges= kabi sandboxing direktivalari orqali xavfsizlik chegarasi. Bu andoza port yoki interpretatordan — Python, Node.js, Go, Java — qat’i nazar deyarli o'zgarmaydi. Keyingi maqola — journalctl bu xizmatning log'larini qanday samarali o'qish va filtrlashni ko'rsatadi.

Manbalar