User:Wacek/brudnopis nginx
nginx to darmowy, wysokowydajny serwer HTTP i odwrotne proxy, a także serwer proxy IMAP/POP3, napisany przez Igora Sysoeva w 2005 roku. nginx jest dobrze znany ze swojej stabilności, bogatego zestawu funkcji, prostej konfiguracji i niskiego zużycia zasobów.
W tym artykule opisano, jak skonfigurować nginx i jak go opcjonalnie zintegrować z PHP przez #FastCGI.
Instalacja
Zainstaluj pakiet nginx-mainline (gałąź główna: nowe funkcje, aktualizacje, poprawki błędów) lub nginx (stabilna gałąź: tylko główne poprawki błędów).
Zaleca się korzystanie z głównego gałezi. Głównym powodem używania stabilnej gałęzi jest obawa przed możliwymi wpływami nowych funkcji, takimi jak niekompatybilność z modułami osób trzecich lub przypadkowe wprowadzenie błędów w nowych funkcjach.
W przypadku instalacji opartej na chroot dla dodatkowego bezpieczeństwa zobacz #Installation in a chroot.
Running
Start/enable nginx.service
.
Domyślna strona to w http://127.0.0.1 w /usr/share/nginx/html/index.html
.
Konfiguracja
Pierwsze kroki z nginx są opisane w Przewodniku dla początkujących. Możesz zmodyfikować konfigurację, edytując pliki w /etc/nginx/
Główny plik konfiguracyjny znajduje się w /etc/nginx/nginx.conf
.
Więcej szczegółów i przykładów można znaleźć w http://wiki.nginx.org/Configuration i oficjalnej oficjalnej dokumentacji.
Poniższe przykłady dotyczą najczęściej występujących przypadków użycia. Zakłada się, że używasz domyślnej lokalizacji dla dokumentów (/usr/share/nginx/html
) Jeśli tak nie jest, zamiast tego zastąp ścieżkę.
Przykład konfiguracji
/etc/nginx/nginx.conf
user http; # May be equal to `grep processor /proc/cpuinfo | wc -l` worker_processes auto; worker_cpu_affinity auto; # PCRE JIT can speed up processing of regular expressions significantly. pcre_jit on; events { # Should be equal to `ulimit -n` worker_connections 1024; # Let each process accept multiple connections. multi_accept on; # Preferred connection method for newer linux versions. use epoll; } http { server_tokens off; # Disables the “Server” response header charset utf-8; # Sendfile copies data between one FD and other from within the kernel. # More efficient than read() + write(), since the requires transferring # data to and from the user space. sendfile on; # Tcp_nopush causes nginx to attempt to send its HTTP response head in one # packet, instead of using partial frames. This is useful for prepending # headers before calling sendfile, or for throughput optimization. tcp_nopush on; # Don't buffer data-sends (disable Nagle algorithm). Good for sending # frequent small bursts of data in real time. # tcp_nodelay on; # On Linux, AIO can be used starting from kernel version 2.6.22. # It is necessary to enable directio, or otherwise reading will be blocking. # aio threads; # aio_write on; # directio 8m; # Caches information about open FDs, freqently accessed files. # open_file_cache max=200000 inactive=20s; # open_file_cache_valid 60s; # open_file_cache_min_uses 2; # open_file_cache_errors on; # http://nginx.org/en/docs/hash.html types_hash_max_size 4096; include mime.types; default_type application/octet-stream; # Logging Settings access_log off; # Gzip Settings gzip on; gzip_comp_level 6; gzip_min_length 500; gzip_proxied expired no-cache no-store private auth; gzip_vary on; gzip_disable "MSIE [1-6]\."; gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; # index index.php index.html index.htm; include sites-enabled/*; # See Server blocks }
Ogólna konfiguracja
Procesy i połączenia
Należy wybrać wartość dopasowania dla worker_processes
. To ustawienie określa, ile połączeń zaakceptuje nginx i ile procesorów będzie mógł wykorzystać. Ogólnie rzecz biorąc, uczynienie z niego liczby wątków sprzętowych w systemie jest dobrym początkiem. Alternatywnie, worker_processes
akceptuje wartość auto
od wersji 1.3.8 i 1.2.5, która spróbuje automatycznie wykryć optymalną wartość (source).
Maksymalna liczba połączeń akceptowanych przez nginx jest określona przez max_clients = worker_processes * worker_connections
.
Działa pod innym użytkownikiem
Domyślnie nginx uruchamia proces główny jako procesy root
i procesy robocze jako http
użytkownika. Aby uruchomić procesy robocze jako inny użytkownik, zmień dyrektywę użytkownika w nginx.conf
:
/etc/nginx/nginx.conf
user user [group];
If the group is omitted, a group whose name equals that of user is used.
Jeśli grupa zostanie pominięta, używana jest grupa o nazwie równej nazwie użytkownika.
Jeśli grupa zostanie pominięta, używana jest grupa, której nazwa sięuser.
root
using systemd. See #Running unprivileged using systemd.Bloki serwera
Możliwe jest obsługiwanie wielu domen przy użyciu bloków serwerów. Są one porównywalne z „VirtualHosts” w Apache. Zobacz także przykłady na początku.
W poniższym przykładzie serwer nasłuchuje połączenia przychodzące na portach IPv4 i IPv6 80 dla dwóch domen, domainname1.dom
i domainname2.dom
:
/etc/nginx/nginx.conf
... server { listen 80; listen [::]:80; server_name domainname1.dom; root /usr/share/nginx/domainname1.dom/html; location / { index index.php index.html index.htm; } } server { listen 80; listen [::]:80; server_name domainname2.dom; root /usr/share/nginx/domainname2.dom/html; ... } ...
Restart nginx.service
aby zastosować zmiany.
Upewnij się, że nazwy hostów są rozwiązywalne poprzez skonfigurowanie serwera DNS, takiego jak BIND lub dnsmasq, lub zajrzyj do Network configuration#Local network hostname resolution.
Zarządzanie wpisami serwera
Możliwe jest umieszczenie różnych bloków server
w różnych plikach. Pozwala to na łatwe włączanie lub wyłączanie niektórych witryn.
Utwórz następujące katalogi:
# mkdir /etc/nginx/sites-available # mkdir /etc/nginx/sites-enabled
Utwórz plik w katalogu sites-available
, który zawiera jeden lub więcej bloków serwerów:
/etc/nginx/sites-available/example
server { .. }
Dołącz dołączone sites-enabled/*;
do końca bloku http
:
/etc/nginx/nginx.conf
... http { ... include sites-enabled/*; } ...
Aby włączyć blok server
, wystarczy utworzyć dowiązanie symboliczne:
# ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example
Aby usunąć server
:
# unlink /etc/nginx/sites-enabled/example
Reload/restart nginx.service
aby włączyć nową konfigurację.
TLS
OpenSSL zapewnia obsługę TLS i jest instalowany domyślnie w instalacji Arch.
- You may want to read the ngx_http_ssl_module docs first before configuring SSL.
- Let’s Encrypt is a free, automated, and open certificate authority. A plugin is available to request valid SSL certificates straight from the command line and automatic configuration.
- Mozilla has a useful TLS article as well as an automated tool to help create a more secure configuration.
- Cipherli.st provides strong TLS implementation examples and tutorial for most modern webservers.
Utwórz klucz prywatny i certyfikat z podpisem własnym. Jest to odpowiednie dla większości instalacji, które nie wymagają CSR:
# mkdir /etc/nginx/ssl # cd /etc/nginx/ssl # openssl req -new -x509 -nodes -newkey rsa:4096 -keyout server.key -out server.crt -days 1095 # chmod 400 server.key # chmod 444 server.crt
-days
switch is optional and RSA keysize can be as low as 2048 (default).Jeśli chcesz utworzyć CSR, postępuj zgodnie z poniższymi instrukcjami:
# mkdir /etc/nginx/ssl # cd /etc/nginx/ssl # openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out server.key # chmod 400 server.key # openssl req -new -sha256 -key server.key -out server.csr # openssl x509 -req -days 1095 -in server.csr -signkey server.key -out server.crt
Podstawowy przykład /etc/nginx/nginx.conf
przy użyciu TLS:
/etc/nginx/nginx.conf
http { ... ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; .. # Redirect to HTTPS server { listen 80; server_name localhost; return 301 https://$host$request_uri; } server { #listen 80; # Uncomment to also listen for HTTP requests listen 443 ssl http2; # HTTP/2 is only possible when using SSL server_name localhost; ssl_certificate ssl/server.crt; ssl_certificate_key ssl/server.key; root /usr/share/nginx/html; location / { index index.html index.htm; } } }
Restart nginx.service
aby zastosować zmiany.
Katalogi na użytkownika
Aby replikować adresy URL ~user
w stylu Apache na katalogi użytkowników ~/public_html
wypróbuj poniższe. (Uwaga: jeśli obie reguły są używane, poniżej, bardziej specyficzna reguła PHP musi być na pierwszym miejscu.)
/etc/nginx/nginx.conf
... server { ... # PHP in user directories, e.g. http://example.com/~user/test.php location ~ ^/~(.+?)(/.+\.php)$ { alias /home/$1/public_html$2; fastcgi_pass unix:/run/php-fpm/php-fpm.sock; fastcgi_index index.php; include fastcgi.conf; } # User directories, e.g. http://example.com/~user/ location ~ ^/~(.+?)(/.*)?$ { alias /home/$1/public_html$2; index index.html index.htm; autoindex on; } ... } ...
Zobacz #PHP implementation, aby uzyskać więcej informacji na temat konfiguracji PHP za pomocą nginx
.
Zrestartuj nginx.service
aby włączyć nową konfigurację.
FastCGI
FastCGI, również FCGI, jest protokołem do łączenia interaktywnych programów z serwerem WWW. FastCGI to odmiana wcześniejszego Common Gateway Interface (CGI); Głównym celem FastCGI jest zmniejszenie kosztów związanych z połączeniem serwera WWW i programów CGI, umożliwiając serwerom obsługę większej liczby żądań stron internetowych jednocześnie.
Technologia FastCGI została wprowadzona do nginx do pracy z wieloma zewnętrznymi narzędziami, np. Perl, PHP i Python.
Implementacja PHP
PHP-FPM to zalecane rozwiązanie do uruchamiania jako serwer FastCGI dla PHP.
Install php-fpm i upewnij się, że PHP został poprawnie zainstalowany i skonfigurowany. Głównym plikiem konfiguracyjnym PHP-FPM jest /etc/php/php-fpm.conf
. Dla podstawowego użycia konfiguracja domyślna powinna być wystarczająca.
Na koniec włącz i uruchom php-fpm.service
.
- If you run nginx under a different user, make sure that the PHP-FPM socket file is accessible by this user, or use a TCP socket.
- If you run nginx in chrooted environment (chroot is
/srv/nginx-jail
, web pages are served at/srv/nginx-jail/www
), you must modify the file/etc/php/php-fpm.conf
to include thechroot /srv/nginx-jail
andlisten = /srv/nginx-jail/run/php-fpm/php-fpm.sock
directives within the pool section (a default one is[www]
). Create the directory for the socket file, if missing. Moreover, for modules that are dynamically linked to dependencies, you will need to copy those dependencies to the chroot (e.g. for php-imagick, you will need to copy the ImageMagick libraries to the chroot, but not imagick.so itself).
konfiguracja nginx
Dodawanie do głównej konfiguracji
Podczas obsługi aplikacji internetowej PHP, w każdym server block [2], powinna znajdować się lokalizacja, np.
/etc/nginx/sites-available/example
server { ... root /usr/share/nginx/html; location / { index index.html index.htm; } location ~ [^/]\.php(/|$) { # Correctly handle request like /test.php/foo/blah.php or /test.php/ fastcgi_split_path_info ^(.+?\.php)(/.*)$; try_files $uri $document_root$fastcgi_script_name =404; # Mitigate https://httpoxy.org/ vulnerabilities fastcgi_param HTTP_PROXY ""; fastcgi_pass unix:/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
Jeśli jest to potrzebne do przetwarzania innych rozszerzeń w PHP (np. .html and .htm):
location ~ [^/]\.php|html|htm(/|$) { ... }
Przetwarzanie rozszerzeń bez .php w PHP-FPM powinno być również wyraźnie dodane w /etc/php/php-fpm.d/www.conf
:
security.limit_extensions = .php .html .htm
fastcgi_pass
argument, as it must be the TCP or Unix socket defined by the chosen FastCGI server in its config file. The default (Unix) socket for php-fpm
is:
fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
You might use the common TCP socket, not default,
fastcgi_pass 127.0.0.1:9000;Unix domain sockets should however be faster.
Plik konfiguracyjny PHP
Jeśli używasz wielu bloków server
z włączoną obsługą PHP, może być łatwiej utworzyć plik konfiguracyjny PHP:
/etc/nginx/php.conf
location ~ \.php$ { ... }
Aby włączyć obsługę PHP dla konkretnego serwera, wystarczy dołączyć php.conf
:
/etc/nginx/nginx.conf
server { server_name example.com; ... include php.conf; }
Konfiguracja testowa
Musisz zrestartować jednostki php-fpm.service
i nginx.service
, jeśli konfiguracja została zmieniona w celu zastosowania zmian.
Aby przetestować implementację FastCGI, utwórz nowy plik PHP w folderze root
zawierającym:
<?php phpinfo(); ?>
Przejdź do tego pliku w przeglądarce i powinieneś zobaczyć stronę informacyjną z bieżącą konfiguracją PHP.
Implementacja CGI
Ta implementacja jest potrzebna dla aplikacji CGI.
fcgiwrap
Zainstaluj fcgiwrap. Plik konfiguracyjny to /usr/lib/systemd/system/fcgiwrap.socket
. Włącz i uruchom fcgiwrap.socket
.
Wiele wątków roboczych
Jeśli chcesz wywołać wiele wątków roboczych, zaleca się użycie multiwatchAUR, który zajmie się ponownym uruchomieniem uszkodzonych dzieci. Będziesz musiał użyć spawn-fcgi
, aby utworzyć gniazdo unix, ponieważ multiwatch wydaje się nie być w stanie obsłużyć utworzonego przez systemd gniazda, mimo że sam fcgiwrap nie ma żadnych problemów, jeśli zostanie wywołany bezpośrednio w pliku jednostki.
Skopiuj plik jednostki z /usr/lib/systemd/system/fcgiwrap.service
do /etc/systemd/system/fcgiwrap.service
(i jednostki fcgiwrap.socket
, jeśli jest dostępna) i zmodyfikuj linię {{ic|ExecStart} zgodnie z potrzebami. Oto plik jednostki, który używa multiwatchAUR. Upewnij się, że fcgiwrap.socket
nie jest uruchomiony lub włączony, ponieważ spowoduje to konflikt z tą jednostką:
/etc/systemd/system/fcgiwrap.service
[Unit] Description=Simple CGI Server After=nss-user-lookup.target [Service] ExecStartPre=/bin/rm -f /run/fcgiwrap.socket ExecStart=/usr/bin/spawn-fcgi -u http -g http -s /run/fcgiwrap.sock -n -- /usr/bin/multiwatch -f 10 -- /usr/sbin/fcgiwrap ExecStartPost=/usr/bin/chmod 660 /run/fcgiwrap.sock PrivateTmp=true Restart=on-failure [Install] WantedBy=multi-user.target
Tweak -f 10
, aby zmienić liczbę tworzonych dzieci.
ExecStartPost
line is required because of strange behaviour I'm seeing when I use the -M 660
option for spawn-fcgi
. The wrong mode is set. This may be a bug?konfiguracja nginx
W każdym bloku server
obsługującym aplikację internetową CGI powinien pojawić się blok location
podobny do:
location ~ \.cgi$ { root /path/to/server/cgi-bin; fastcgi_pass unix:/run/fcgiwrap.sock; include fastcgi.conf; }
Domyślnym plikiem gniazda dla fcgiwrap
jest /run/fcgiwrap.sock
.
Jeśli otrzymasz 502 - 502 - bad Gateway
error, powinieneś sprawdzić, czy aplikacja CGI najpierw ogłasza mime-type następującej treści. Dla html musi to być Content-type: text/html
.
Instalacja w chroocie
Instalacja nginx w chroot dodaje dodatkową warstwę bezpieczeństwa. Aby zapewnić maksymalne bezpieczeństwo, chroot powinien zawierać tylko pliki potrzebne do uruchomienia serwera nginx, a wszystkie pliki powinny mieć najbardziej restrykcyjne uprawnienia, np. Jeśli to możliwe powinno być własnością roota, katalogi takie jak /usr/bin
powinny być nieczytelne i niepisywalny itp.
Arch posiada domyślnie użytkownika http
i grupę, która będzie uruchamiać serwer. Chroot będzie w /srv/http
.
Skrypt perla do tworzenia tego więzienia jest dostępny w jail.pl gist Możesz użyć tego lub postępować zgodnie z instrukcjami w tym artykule. Oczekuje, że zostanie uruchomiony jako root. Będziesz musiał odkomentować linię przed dokonaniem jakichkolwiek zmian.
Utwórz niezbędne urządzenia
nginx potrzebuje /dev/null
, /dev/random
, i /dev/urandom
. Aby je zainstalować w chroot, utwórz katalog /dev/
i dodaj urządzenia za pomocą mknod. Unikaj montowania całego /dev/
aby upewnić się, że nawet jeśli chroot jest zagrożony, atakujący musi wyrwać się z chroota, aby uzyskać dostęp do ważnych urządzeń, takich jak /dev/sda1
.
/srv/http
is mounted without nodev optionls -l /dev/{null,random,urandom}
to better understand the mknod options.# export JAIL=/srv/http # mkdir $JAIL/dev # mknod -m 0666 $JAIL/dev/null c 1 3 # mknod -m 0666 $JAIL/dev/random c 1 8 # mknod -m 0444 $JAIL/dev/urandom c 1 9
Tworzenie niezbędnych katalogów
nginx wymaga kilku plików do poprawnego działania. Przed ich skopiowaniem utwórz foldery do przechowywania. Zakłada to, że głównym dokumentem nginx będzie /srv/http/www
.
# mkdir -p $JAIL/etc/nginx/logs # mkdir -p $JAIL/usr/{lib,bin} # mkdir -p $JAIL/usr/share/nginx # mkdir -p $JAIL/var/{log,lib}/nginx # mkdir -p $JAIL/www/cgi-bin # mkdir -p $JAIL/{run,tmp} # cd $JAIL; ln -s usr/lib lib # cd $JAIL; ln -s usr/lib lib64 # cd $JAIL/usr; ln -s lib lib64
Następnie zamontuj $JAIL/tmp
i $JAIL/run
jako tmpfs's. Rozmiar powinien być ograniczony, aby osoba atakująca nie mogła zjeść całej pamięci RAM.
# mount -t tmpfs none $JAIL/run -o 'noexec,size=1M' # mount -t tmpfs none $JAIL/tmp -o 'noexec,size=100M'
Aby zachować montowanie w ponownym uruchomieniu, następujące wpisy powinny zostać dodane do /etc/fstab
:
/etc/fstab
tmpfs /srv/http/run tmpfs rw,noexec,relatime,size=1024k 0 0 tmpfs /srv/http/tmp tmpfs rw,noexec,relatime,size=102400k 0 0
Wypełnij chroot
Najpierw skopiuj łatwe pliki.
# cp -r /usr/share/nginx/* $JAIL/usr/share/nginx # cp -r /usr/share/nginx/html/* $JAIL/www # cp /usr/bin/nginx $JAIL/usr/bin/ # cp -r /var/lib/nginx $JAIL/var/lib/nginx
Teraz skopiuj wymagane biblioteki. Użyj ldd, aby je wyświetlić, a następnie skopiuj wszystkie do właściwej lokalizacji. Kopiowanie jest preferowane w stosunku do twardych linków, aby zapewnić, że nawet jeśli atakujący uzyska dostęp do zapisu plików, nie może zniszczyć ani zmienić prawdziwych plików systemowych.
$ ldd /usr/bin/nginx
linux-vdso.so.1 (0x00007fffc41fe000) libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f57ec3e8000) libcrypt.so.1 => /usr/lib/libcrypt.so.1 (0x00007f57ec1b1000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f57ebead000) libm.so.6 => /usr/lib/libm.so.6 (0x00007f57ebbaf000) libpcre.so.1 => /usr/lib/libpcre.so.1 (0x00007f57eb94c000) libssl.so.1.0.0 => /usr/lib/libssl.so.1.0.0 (0x00007f57eb6e0000) libcrypto.so.1.0.0 => /usr/lib/libcrypto.so.1.0.0 (0x00007f57eb2d6000) libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f57eb0d2000) libz.so.1 => /usr/lib/libz.so.1 (0x00007f57eaebc000) libGeoIP.so.1 => /usr/lib/libGeoIP.so.1 (0x00007f57eac8d000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f57eaa77000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f57ea6ca000) /lib64/ld-linux-x86-64.so.2 (0x00007f57ec604000)
W przypadku plików znajdujących się w /usr/lib
możesz wypróbować następujący one-liner:
# cp $(ldd /usr/bin/nginx | grep /usr/lib | sed -sre 's/(.+)(\/usr\/lib\/\S+).+/\2/g') $JAIL/usr/lib
I następujące dla ld-linux-x86-64.so
:
# cp /lib64/ld-linux-x86-64.so.2 $JAIL/lib
linux-vdso.so
: it is not a real library and does not exist in /usr/lib
.Skopiuj kilka różnych, ale niezbędnych bibliotek i plików systemowych.
# cp /usr/lib/libnss_* $JAIL/usr/lib # cp -rfvL /etc/{services,localtime,nsswitch.conf,nscd.conf,protocols,hosts,ld.so.cache,ld.so.conf,resolv.conf,host.conf,nginx} $JAIL/etc
Utwórz ograniczone pliki user/group dla chroota. W ten sposób tylko użytkownicy potrzebni do działania chroota istnieją tak daleko, jak wie chroot, i żaden z users/groups systemu nie wycieka do atakujących, jeśli uzyska dostęp do chroota.
$JAIL/etc/group
http:x:33: nobody:x:99:
$JAIL/etc/passwd
http:x:33:33:http:/:/bin/false nobody:x:99:99:nobody:/:/bin/false
$JAIL/etc/shadow
http:x:14871:::::: nobody:x:14871::::::
$JAIL/etc/gshadow
http::: nobody:::
# touch $JAIL/etc/shells # touch $JAIL/run/nginx.pid
Na koniec ustaw bardzo restrykcyjne uprawnienia. W miarę możliwości należy do roota i ustawić niezapisywalny.
# chown -R root:root $JAIL/ # chown -R http:http $JAIL/www # chown -R http:http $JAIL/etc/nginx # chown -R http:http $JAIL/var/{log,lib}/nginx # chown http:http $JAIL/run/nginx.pid # find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod -rw # find $JAIL/ -gid 0 -uid 0 -type d -print | xargs chmod +x # find $JAIL/etc -gid 0 -uid 0 -type f -print | xargs chmod -x # find $JAIL/usr/bin -type f -print | xargs chmod ug+rx # find $JAIL/ -group http -user http -print | xargs chmod o-rwx # chmod +rw $JAIL/tmp # chmod +rw $JAIL/run
Jeśli twój serwer będzie wiązał port 80 (lub jakikolwiek inny port w zakresie [1-1023]), nadaj chrootowanemu uprawnieniu wykonywanemu powiązanie tych portów bez roota.
# setcap 'cap_net_bind_service=+ep' $JAIL/usr/bin/nginx
Zmodyfikuj nginx.service, aby uruchomić chroot
Przed zmodyfikowaniem pliku jednostki nginx.service
dobrym pomysłem może być skopiowanie go do /etc/systemd/system/
, ponieważ pliki jednostek mają tam pierwszeństwo przed plikami w /usr/lib/systemd/system/
Oznacza to, że aktualizacja nginx nie zmodyfikuje niestandardowego pliku usługi.
# cp /usr/lib/systemd/system/nginx.service /etc/systemd/system/nginx.service
Jednostka systemd musi zostać zmieniona, aby uruchomić nginx w chroot, jako użytkownik http, i zapisać plik pid w chroot.
/etc/systemd/system/nginx.service
[Unit] Description=A high performance web server and a reverse proxy server After=syslog.target network.target [Service] Type=forking PIDFile=/srv/http/run/nginx.pid ExecStartPre=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -t -q -g 'pid /run/nginx.pid; daemon on; master_process on;' ExecStart=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;' ExecReload=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid; daemon on; master_process on;' -s reload ExecStop=/usr/bin/chroot --userspec=http:http /srv/http /usr/bin/nginx -g 'pid /run/nginx.pid;' -s quit [Install] WantedBy=multi-user.target
Możesz teraz bezpiecznie pozbyć się nie-chrootowanej instalacji nginx.
# pacman -Rsc nginx
Jeśli nie usuniesz nie chrootowanej instalacji nginx, możesz się upewnić, że działający proces nginx jest w rzeczywistości procesem chrootowanym. Możesz to zrobić, sprawdzając, gdzie znajduje się symbol /proc/PID/root
. Jeśli powinien / link do /srv/http
zamiast /
.
# ps -C nginx | awk '{print $1}' | sed 1d | while read -r PID; do ls -l /proc/$PID/root; done
Porady i wskazówki
Uruchamianie bez przywilejów za pomocą systemd
Edytuj nginx.service i ustaw opcje User
i opcjonalnie Group w [Service]
:
/etc/systemd/system/nginx.service.d/user.conf
[Service] User=user Group=group
Możemy zahartować usługę przeciwko coraz wyższym przywilejom:
/etc/systemd/system/nginx.service.d/user.conf
[Service] ... NoNewPrivileges=yes
Następnie musimy upewnić się, że user
ma dostęp do wszystkiego, czego potrzebuje:
- Port
-
Linux nie zezwala procesom innym niż
root
na domyślne powiązanie z portami poniżej 1024. Można użyć portu powyżej 1024:/etc/nginx/nginx.conf
server { listen 8080; }
Tip: If you want nginx accessible on port 80 or 443, configure your firewall to redirect requests from 80 or 443 to the ports nginx listens to. -
Lub możesz przyznać procesowi nginx zdolność CAP_NET_BIND_SERVICE, która pozwoli mu na powiązanie z portami poniżej 1024:
/etc/systemd/system/nginx.service.d/user.conf
[Service] ... CapabilityBoundingSet= CapabilityBoundingSet=CAP_NET_BIND_SERVICE AmbientCapabilities= AmbientCapabilities=CAP_NET_BIND_SERVICE
- PID file
-
nginx uses
/run/nginx.pid
by default. We can create a directory that user has write access to and place our PID file in there. An example using systemd-tmpfiles:/etc/tmpfiles.d/nginx.conf
d /run/nginx 0775 root group - -
Run the configuration:
# systemd-tmpfiles --create
Edit the PID values based on the original
nginx.service
:/etc/systemd/system/nginx.service.d/user.conf
[Service] ... PIDFile=/run/nginx/nginx.pid ExecStart= ExecStart=/usr/bin/nginx -g 'pid /run/nginx/nginx.pid; error_log stderr;' ExecReload= ExecReload=/usr/bin/nginx -s reload -g 'pid /run/nginx/nginx.pid;'
/var/lib/nginx/*
-
Some directories under
/var/lib/nginx
need to be bootstrapped by nginx running asroot
. It is not necessary to start the whole server to do that, nginx will do it on a simple configuration test. So just run one of those and you're good to go. - Log file & Directory Permissions
-
The step of running a configuration test will create a dangling
root
-owned log. Remove logs in/var/log/nginx
to start fresh. -
The nginx service user needs write permission to
/var/log/nginx
. This may require changing permission and/or ownership of this directory on your system.
Now we should be good to go. Go ahead and start nginx, and enjoy your completely rootless nginx.
Alternative script for systemd
On pure systemd you can get advantages of chroot + systemd. [3] Based on set user group an pid on:
/etc/nginx/nginx.conf
user http; pid /run/nginx.pid;
the absolute path of file is /srv/http/etc/nginx/nginx.conf
.
/etc/systemd/system/nginx.service
[Unit] Description=nginx (Chroot) After=syslog.target network.target [Service] Type=forking PIDFile=/srv/http/run/nginx.pid RootDirectory=/srv/http ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf ExecReload=/usr/sbin/nginx -c /etc/nginx/nginx.conf -s reload ExecStop=/usr/sbin/nginx -c /etc/nginx/nginx.conf -s stop [Install] WantedBy=multi-user.target
It is not necesary to set the default location, nginx loads at default -c /etc/nginx/nginx.conf
, but it is a good idea though.
Alternatively you can run only ExecStart
as chroot with parameter RootDirectoryStartOnly
set as yes
man systemd service or start it before mount point as effective or a systemd path is available.
/etc/systemd/system/nginx.path
[Unit] Description=nginx (Chroot) path [Path] PathExists=/srv/http/site/Public_html [Install] WantedBy=default.target
Enable the created nginx.path
and change the WantedBy=default.target
to WantedBy=nginx.path
in /etc/systemd/system/nginx.service
.
The PIDFile
in unit file allows systemd to monitor process (absolute path required). If it is undesired, you can change to default one-shot type, and delete the reference from the unit file.
Nginx Beautifier
nginxbeautifierAUR is a commandline tool used to beautify and format nginx configuration files.
Better headers management
Nginx has a rather unintuitive header management system where headers can only be defined in one context, any other headers are ignored. To remedy this we can install the headers-more-nginx module.
Install the package nginx-mod-headers-more package. This will install the module to /usr/lib/nginx/modules
directory.
To load the module add the following to the top of your main nginx configuration file.
/etc/nginx/nginx.conf
load_module "/usr/lib/nginx/modules/ngx_http_headers_more_filter_module.so"; ...
Troubleshooting
Configuration validation
# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Accessing local IP redirects to localhost
Solution from the Arch Linux forum.
In /etc/nginx/nginx.conf
locate the server_name localhost
line without a #
in front of it, and add below:
server_name_in_redirect off;
Default behavior is that nginx redirects any requests to the value given as server_name
in the config.
This is because the FastCGI server has not been started, or the socket used has wrong permissions.
Try out this answer to fix the 502 error.
In Archlinux, the configuration file mentioned in above link is /etc/php/php-fpm.conf
.
Error: No input file specified
1. Verify that variable open_basedir
in /etc/php/php.ini
contains the correct path specified as root
argument in nginx.conf
(usually /usr/share/nginx/
). When using PHP-FPM as FastCGI server for PHP, you may add fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root/:/tmp/:/proc/";
in the location
block which aims for processing php file in nginx.conf
.
2. Another occasion is that, wrong root
argument in the location ~ \.php$
section in nginx.conf
. Make sure the root
points to the same directory as it in location /
in the same server. Or you may just set root as global, do not define it in any location section.
3. Check permissions: e.g. http
for user/group, 755
for directories and 644
for files. Remember the entire path to the html
directory should have the correct permissions. See File permissions and attributes#Bulk chmod to bulk modify a directory tree.
4. You do not have the SCRIPT_FILENAME
containing the full path to your scripts. If the configuration of nginx (fastcgi_param SCRIPT_FILENAME
) is correct, this kind of error means php failed to load the requested script. Usually it is simply a permissions issue, you can just run php-cgi as root:
# spawn-fcgi -a 127.0.0.1 -p 9000 -f /usr/bin/php-cgi
or you should create a group and user to start the php-cgi:
# groupadd www # useradd -g www www # chmod +w /srv/www/nginx/html # chown -R www:www /srv/www/nginx/html # spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/bin/php-cgi
5. If you are running php-fpm with chrooted nginx ensure chroot
is set correctly within /etc/php-fpm/php-fpm.d/www.conf
(or /etc/php-fpm/php-fpm.conf
if working on older version)
Warning: Could not build optimal types_hash
When starting the nginx.service
, the process might log the message:
[warn] 18872#18872: could not build optimal types_hash, you should increase either types_hash_max_size: 1024 or types_hash_bucket_size: 64; ignoring types_hash_bucket_size
To fix this warning, increase the values for these keys inside the http
block [4] [5]:
/etc/nginx/nginx.conf
http { types_hash_max_size 4096; server_names_hash_bucket_size 128; ... }
Cannot assign requested address
The full error from systemctl status nginx.service
is
[emerg] 460#460: bind() to A.B.C.D:443 failed (99: Cannot assign requested address)
Even, if your nginx unit-file is configured to run after network.target
with systemd, nginx may attempt to listen at an address that is configured but not added to any interface yet. Verify that this the case by manually running start for nginx (thereby showing the IP address is configured properly). Configuring nginx to listen to any address will resolve this issue. Now if your use case requires listening to a specific address, one possible solution is to reconfigure systemd.
To start nginx after all configured network devices are up and assigned an IP address, append network-online.target
to After=
within nginx.service
and start/enable systemd-networkd-wait-online.service
.