Narzędzia użytkownika

Narzędzia witryny


pl:python:serwerdjango

Serwer Django

Na przykładzie Fedora Linux 38

Ustawienia Django

Plik settings.py:

DEBUG = False
 
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
 
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'static'

Dla wersji starszej niż 3.6 powinniśmy użyć:

import os
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

W niektórych wypadkach może zajść konieczność dodania parametru:

CSRF_TRUSTED_ORIGINS = ['http://127.0.0.1',]

NGINX

nginx.conf
user nginx;
http {
    include /etc/nginx/conf.d/*.conf;
        server {
            listen       81;
            listen       [::]:81;
}
gunicorn.conf
server {
    listen      80;
    listen       [::]:80;
    server_name localhost;
    charset     utf-8;
 
    # max upload size
    client_max_body_size 75M;
 
    # Django media
    location /media  {
        alias /path/to/your/mysite/media;
    }
 
    location /static {
        alias /home/user_app/PycharmProjects/venvFolder/FolderProjektDjango/FolerApp/static;
    }
 
    location / {
        proxy_pass http://localhost:8080;
    }
}
systemctl restart nginx

Gunicorn

gunicorn.service
[Unit]
Description=Gunicorn instance to serve application
After=network.target
 
[Service]
User=user_app
Group=user_app
StandardOutput=journal
StandardError=journal
 
WorkingDirectory=/home/user_app/PycharmProjects/venvFolder/FolderProjektDjango
ExecStart=/home/user_app/PycharmProjects/venvFolder/venv/bin/gunicorn --workers 3 --bind 127.0.0.1:8080 ProjektDjango.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
 
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable gunicorn.service
systemctl start gunicorn.service
systemctl status gunicorn.service
journalctl -xe

Uprawnienia do katalogu static

Katalog /home powinien mieć uprawnienia 755. Katalog static i nadrzędne powinny mieć uprawnienia 750 a użytkownik nginx, który uruchamia usługę nginx powinien być dodany do grupy użytkownika Gunicorn:

usermod -aG user_app nginx

Problemy ACL

Wydajemy polecenie getfacl dla katalogu użytkownika aplikacji:

getfacl /home/user_app
getfacl: Usunięcie wiodącego '/' ze ścieżek bezwzględnych
# file: home/user_app
# owner: user_app
# group: user_app
user::rwx
user:qemu:--x
group::---
mask::r-x
other::---

Jak widać katalog nie należy do żadnej grupy. Dodajemy katalog do grupy użytkownika (taka sama nazwa jak nazwa użytkownika.

setfacl -m g:user_app:r-x /home/user_app

Możemy sprawdzić zmiany:

getfacl /home/user_app
getfacl: Usunięcie wiodącego '/' ze ścieżek bezwzględnych
# file: home/user_app
# owner: user_app
# group: user_app
user::rwx
user:qemu:--x
group::---
group:user_app:r-x
mask::r-x
other::---

Jeżeli nadal nie mamy dostępu musimy sprawdzić poszczególne katalogi:

ls -all -d /home/user_app/
drwxr-x---+ 1 user_app user_app 1380 01-03 11:01 /home/user_app/

Różnica między drwxr-x—+ a drwxr-x—. polega na obecności atrybutu + w pierwszym przypadku. Ten atrybut oznacza, że istnieje dodatkowa kontrola dostępu, tak zwane Access Control List (ACL).

1. drwxr-x—+

  1. d: Katalog.
  2. rwx: Prawa dostępu właściciela (czytanie, zapisywanie, wykonywanie).
  3. r-x: Prawa dostępu grupy (czytanie, brak zapisywania, wykonywanie).
  4. : Brak praw dostępu dla innych.
  5. +: Wskaźnik na fakt, że istnieje ACL, który może zawierać dodatkowe reguły dostępu dla konkretnych użytkowników i grup.

2. drwxr-x—.:

  1. d: Katalog.
  2. rwx: Prawa dostępu właściciela (czytanie, zapisywanie, wykonywanie).
  3. r-x: Prawa dostępu grupy (czytanie, brak zapisywania, wykonywanie).
  4. : Brak praw dostępu dla innych.
  5. .: Wskazuje na to, że nie ma dodatkowych reguł ACL. To zazwyczaj oznacza, że kontrola dostępu opiera się wyłącznie na standardowych prawach dostępu (owner, group, others).

Atrybut ACL pozwala na bardziej elastyczną kontrolę dostępu niż standardowe prawa dostępu. Dzięki ACL można, na przykład, precyzyjnie kontrolować dostęp dla konkretnych użytkowników i grup, a także określać dodatkowe uprawnienia.

Na koniec przykład zmian uprawnień dla użytkownika:

setfacl -m u:nginx:r-x /home/user_app

Problemy SELinux

setsebool -P httpd_read_user_content 1
setenforce 1
getenforce
ausearch -c '(gunicorn)' --raw | audit2allow -M my-gunicorn
semodule -X 300 -i my-gunicorn.pp && rm -f my-gunicorn.*

NGINX i Gunicorn na jednym serwerze

Jeżeli Gunicon i NGINX jest na jednym serwerze komunikację między nimi najlepiej użyć za pomocą pliku socket.

Decyzja, czy plik socket Gunicorn powinien być tworzony w katalogu /tmp czy /run, zazwyczaj zależy od preferencji i praktyk administratora systemu oraz zaleceń dystrybucji.

1. /tmp

  • Często używane do przechowywania plików tymczasowych.
  • Może zostać wyczyszczony podczas ponownego uruchamiania systemu.
  • Odpowiednie dla procesów, które nie wymagają trwałego przechowywania plików socket.
  • Może być bardziej dostępny dla różnych usług i użytkowników.

2. /run

  • Zazwyczaj zawiera pliki związane z uruchamianiem usług.
  • Często używane do plików, które muszą być dostępne między restartami systemu.
  • Często dostępne tylko dla określonych usług i użytkowników.
  • Często trwalsze niż /tmp.

Najważniejsze jest, aby pamiętać o tym, żeby nadać odpowiednie uprawnienia do katalogu, w którym utworzysz plik socket, aby Gunicorn i Nginx mogły współpracować. Upewnij się również, że obie usługi (Gunicorn i Nginx) mają dostęp do tego samego katalogu i pliku socket. Ostateczna decyzja zależy od wymagań twojej konkretnego środowiska i preferencji.

Plik uruchamiający usługę Gunicorn:

gunicorn.service
[Unit]
Description=Gunicorn instance to serve application
After=network.target
 
[Service]
User=user_app
Group=user_app
StandardOutput=journal
StandardError=journal
 
WorkingDirectory=/home/user_app/PycharmProjects/venvFolder/FolderProjektDjango
ExecStart=/home/user_app/PycharmProjects/venvFolder/venv/bin/gunicorn --workers 3 --bind unix:/tmp/gunicorn.sock ProjektDjango.wsgi
 
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=false
 
[Install]
WantedBy=multi-user.target

Należy zwrócić uwagę na opcję PrivateTmp=false. Bez niej usługa może utworzyć plik w losowym podkatalogu. Przykładowo /tmp/systemd-private-1ab04e6700c74be2a90e7f49edc79e19-gunicorn.service-94a5le/tmp/gunicorn.sock.

Plik konfiguracji NGiNX do Gunicorn:

gunicorn.conf
server {
    listen	80;
    server_name localhost;
    charset     utf-8;
    client_max_body_size 75M;
    location /media  {
        alias /path/to/your/mysite/media;
    }
    location /static {
        alias /home/user_app/PycharmProjects/venvFolder/FolderProjektDjango/static;
    }
    location / {
        proxy_pass http://unix:/tmp/gunicorn.sock;
    }
}

Podobnie jak z usługą gunicorn.service w pliku /etc/systemd/system/multi-user.target.wants/nginx.service musimy dokonać zmiany i opcję PrivateTmp=true zmienić na PrivateTmp=false.

Możliwe, że SELinux będzie blokował dostęp NGiNX do pliku /tmp/gunicorn.sock. Na to może pomóc:

ausearch -c 'nginx' --raw | audit2allow -M my-nginx
semodule -X 300 -i my-nginx.pp && rm -f my-nginx.*

Kolejność uruchamiania i wyłączania usług

Zachowanie określonej kolejności przy uruchamianiu i wyłączaniu usług Nginx i Gunicorn może być kluczowe w niektórych przypadkach. Oto kilka uwag na ten temat:

1. Uruchamianie:

  • Gunicorn zazwyczaj musi zostać uruchomiony przed Nginx, ponieważ Nginx działa jako serwer HTTP, który przekierowuje żądania do Gunicorn, gdzie są obsługiwane przez aplikację Django lub inną aplikację WSGI.
  • Gdy Gunicorn jest uruchamiany, może zaczekać na żądania od Nginx.

2. Wyłączanie:

  • Kolejność wyłączania może być również ważna. Zazwyczaj zaleca się najpierw wyłączenie Nginx, a następnie Gunicorna.
  • Wyłączenie Nginx może uniemożliwić nowym żądaniom docieranie do Gunicorn, co pozwala zakończyć obsługę istniejących żądań.

Przykładowy scenariusz wyłączania:

  • Wyłącz Nginx: sudo systemctl stop nginx
  • Wyłącz Gunicorn: sudo systemctl stop gunicorn

Pamiętaj, że konkretna kolejność może się różnić w zależności od konfiguracji systemu operacyjnego. Ważne jest, aby dostosować się do specyfiki środowiska i stosować praktyki zgodne z dokumentacją usług oraz zaleceniami dostawcy systemu operacyjnego.

Korzystnie jest zmodyfikować skrypt uruchamiania serwisu nginx i dodać opcje ustalającą uruchomienie nginx po usłudze gunicorn:

After=network-online.target remote-fs.target nss-lookup.target gunicorn.service

Django i DokuWiki na systemie Windows

NGINX

Pobieramy najnowszą wersję nginx. Rozpakowujemy przykładowo w lokalizacji C:\nginx.

W pliku C:\nginx\nginx.conf w sekcji http dodajemy opcję:

nginx.conf
http{
    ...
    include waitress.onf;
    ...
}

W tym samym katalogu tworzymy plik waitress.conf z zawartością:

waitress.conf
server{
    listen localhost:81;
 
    location /static {
        alias "C:/Python/PycharmProjects/DjangoProjects/project/static";
        }
 
    location / {
        proxy_pass http://localhost:8080;
        }
}

Należy zwrócić uwagę, że mimo konfiguracji nginx w systemie windows to w ścieżkach używamy ukośnika jak w systemie UNIX.

PHP

Pobieramy najnowszą wersję php. Rozpakowujemy w katalogu C:\nginx\php.

Oczywiście Django nie wymaga PHP ale tak przy okazji instalacji DokuWiki podaje jak to zrobić. Wracamy ponownie do pliku nginx.conf. Domyślnie w pliku powinna znajdować się sekcja jak poniżej. Należy ją odkomentować i jedynie domyślny wpis /scripts$fastcgi_script_name zmienić na $document_root$fastcgi_script_name. Efekt jak poniżej:

nginx.conf
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
 
location ~ \.php$ {
root           html;
fastcgi_pass   127.0.0.1:9000;
fastcgi_index  index.php;
# fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
include        fastcgi_params;
}

Waitress

W środowisku naszej aplikacji Django instalujemy pakiet waitress:

pip install waitress

W katalogu naszego projekty Django tworzymy plik runserver.py z zawartością:

runserver.py
from waitress import serve
from project.wsgi import application
 
if __name__ == '__main__':
    serve(application, host = 'localhost', port='8080')

Przy czym project w from project.wsgi import application to nazwa naszego projektu Django. Projektu, a nie aplikacji Django.

NSSM

Pobieramy najnowszą wersję nssm. Rozpakowujemy w katalogu C:\nginx\nssm. Jeżeli używamy wersji 64bit to wykonujemy następujące polecenia.

Tworzenie usługi waitress:

C:\nginx\nssm\win64\nssm.exe install WaitressService "C:\Python\PycharmProjects\DjangoProjects\.venv\Scripts\python.exe" "C:\Python\PycharmProjects\DjangoProjects\project\runserver.py"

Możemy sprawdzić status usługi:

C:\nginx\nssm\win64\nssm.exe status WaitressService 

lub uruchomić:

C:\nginx\nssm\win64\nssm.exe start WaitressService 

Tworzenie usługi PHP:

C:\nginx\nssm\win64\nssm.exe install PHPService "C:\nginx\php\php-cgi.exe" -b 127.0.0.1:9000

Możemy sprawdzić status usługi:

C:\nginx\nssm\win64\nssm.exe status PHPService

lub uruchomić:

C:\nginx\nssm\win64\nssm.exe start PHPService

Tworzenie usługi NGINX:

C:\nginx\nssm\win64\nssm.exe install NGINXService "C:\nginx\nginx.exe"

Możemy sprawdzić status usługi:

C:\nginx\nssm\win64\nssm.exe status NGINXService

lub uruchomić:

C:\nginx\nssm\win64\nssm.exe start NGINXService

Jeżeli zajdzie taka konieczność to usługę możemy zatrzymać:

C:\nginx\nssm\win64\nssm.exe stop NGINXService

lub usunąć:

C:\nginx\nssm\win64\nssm.exe remove NGINXService confirm

Jeżeli problem to sprawdź:

  • Czy port 8080 lub inny jest taki sam w pliku runserver.py i waitress.conf
  • Czy port 9000 lub inny dla PHP jest taki sam w pliku nginx.conf i poleceniu startu usługi PHPService

DokuWiki

Możemy katalog C:\nginx\html zmienić na C:\nginx\html_old. Utworzyć nowy katalog C:\nginx\html. W nowym katalogu html pobrać i rozpakować pliki dokuwiki. Na potrzeby bezpieczeństwa aplikacji wprowadzić zmiany w pliku C:\nginx\nginx.conf i usunąć komentarze:

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
    deny  all;
}

a pod nimi dodać:

location ~ /(data|conf|bin|inc|vendor)/ {
      deny all;
}

Po zmianach restart usługi:

C:\nginx\nssm\win64\nssm.exe restart NGINXService

Tym sposobem zanim powstanie nasza aplikacja Django możemy na bieżąco w DokuWiki tworzyć do niej dokumentację.

Aby przesyłać pliki multimedialne przykładowo .jpg to w w pliku C:\nginx\nginx.conf dodajemy opcję:

http {
    ...
    client_max_body_size 40M;
    ...
    }

Następnie w pliku konfiguracyjnym C:\nginx\php\php.ini:

[PHP]
post_max_size = 40M
upload_max_filesize = 40M
display_errors = Off

Restartujemy usługi PHP i NGINX.

pl/python/serwerdjango.txt · ostatnio zmienione: 2024/01/12 12:30 przez sindap

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki