Na przykładzie Fedora Linux 38
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',]
user nginx; http { include /etc/nginx/conf.d/*.conf; server { listen 81; listen [::]:81; }
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
[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
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
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—+
d
: Katalog.rwx
: Prawa dostępu właściciela (czytanie, zapisywanie, wykonywanie).r-x
: Prawa dostępu grupy (czytanie, brak zapisywania, wykonywanie).—
: Brak praw dostępu dla innych.+
: 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—.:
d
: Katalog.rwx
: Prawa dostępu właściciela (czytanie, zapisywanie, wykonywanie).r-x
: Prawa dostępu grupy (czytanie, brak zapisywania, wykonywanie).—
: Brak praw dostępu dla innych..
: 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
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.*
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
2. /run
/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:
[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:
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.*
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:
2. Wyłączanie:
Przykładowy scenariusz wyłączania:
sudo systemctl stop nginx
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
Pobieramy najnowszą wersję nginx. Rozpakowujemy przykładowo w lokalizacji C:\nginx
.
W pliku C:\nginx\nginx.conf
w sekcji http
dodajemy opcję:
http{ ... include waitress.onf; ... }
W tym samym katalogu tworzymy plik waitress.conf
z zawartością:
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.
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:
# 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; }
W środowisku naszej aplikacji Django instalujemy pakiet waitress:
pip install waitress
W katalogu naszego projekty Django tworzymy plik runserver.py z zawartością:
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.
Pobieramy najnowszą wersję nssm. Rozpakowujemy w katalogu C:\nginx\nssm
. Jeżeli używamy wersji 64bit to wykonujemy następujące polecenia.
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
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
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
runserver.py
i waitress.conf
nginx.conf
i poleceniu startu usługi PHPService
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.