參考資料
使用自行編譯安裝
- 將源碼目錄置於 /usr/local/src/ 底下
- 預設,將會生成執行檔於 /usr/local/nginx/ 底下,執行時位於 /usr/local/nginx/sbin/nginx
- 首先相依的開發套件需先安裝。
apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
apt install zlib1g-dev libpcre2-dev libpcre3-dev libssl-dev libkqueue-dev(這個 kqueue 預設下好像是多餘的)
- 接著執行組態生成 ./configure。
- 事實上,使用預設安裝時,./configure,會出現找不到 openssl 的錯誤訊息,因此查找了如上的一些參考資料(條目 2-6)所提供的一些解法。
- 但實際是(條目 7),可能內定設定使用到了 https 的相關參數,但另一方面仍需使用者明定使用 https,才會引入編譯,故此二者不一致才發生這樣的錯誤訊息。解法就是明定使用 https(我們當然該使用),即,加上 –with-http_ssl_module(注意 – -w)參數,就無該訊息了。
- 筆者使用的版本是 nginx version: nginx/1.20.1
- 因此,安裝三步驟即成:
- sudo ./configure –with-http_ssl_module –with-http_v2_module(注意 – -with)
- sudo make
- sudo make install
- 命令列基本用法:
HELP
sudo ./nginx -h
查看版本
sudo ./nginx -v
版本細節
sudo ./nginx -V
啟動 nginx
sudo ./nginx
停止 nginx
sudo ./nginx -s quit
重新加載(config),服務不會中斷
sudo ./nginx -s reload
即刻終止 nginx
sudo ./nginx -s stop
指向配置文件
sudo ./nginx -c path_to_conf_file
檢查配置組態的合法性
sudo ./nginx -t
Service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
# note: if in service status has "nginx.service: Failed to read PID from file nginx.pid: Invalid argument"
# then uncomment this line:
# ExecStartPost=/bin/sleep 0.1
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
組態
- 筆者對於組態中條目的對象不瞭解,組織起來也不清楚其作用與影響,故,當前只能慢慢消化理解了。
- 根據 wordpress 中的 nginx 配置範例,於 conf 目錄下建立出幾個子目錄,放置子組態,其將由 nginx.conf 有條件引入(generic 指的是通用組態,global 此亦指通用,非全域):
- ./generic/global.conf
- ./generic/restrictions.conf
- ./sites/sites.conf
- ./sites/my_site.conf
- ./sites/my_localhost.conf
- the nginx.conf:
include /usr/local/nginx/conf/generic/global.conf;
- the sites.conf: (modify here)
include /usr/local/nginx/conf/sites/my_site.conf;
include /usr/local/nginx/conf/sites/my_localhost.conf;
include /usr/local/nginx/conf/sites/my_site_1.conf;
include /usr/local/nginx/conf/sites/my_site_2.conf;
…
global.conf
user www-data www-data;
#usually equal to number of CPUs you have. run command "grep processor /proc/cpuinfo | wc -l" to find it
worker_processes auto;
worker_cpu_affinity auto;
error_log /usr/local/nginx/logs/error.log;
pid /usr/local/nginx/logs/nginx.pid;
# Keeps the logs free of messages about not being able to bind().
#daemon off;
events {
worker_connections 1024;
}
http {
# rewrite_log on;
include /usr/local/nginx/conf/mime.types;
default_type application/octet-stream;
access_log /usr/local/nginx/logs/access.log;
sendfile on;
# tcp_nopush on;
keepalive_timeout 3;
# tcp_nodelay on;
gzip on;
index index.php index.html index.htm;
# php max upload limit cannot be larger than this
# client_max_body_size 13m;
# Upstream to abstract backend connection(s) for PHP.
upstream php {
# this should match value of "listen" directive in php-fpm pool
server unix:/run/php/php-fpm.sock;
}
include /usr/local/nginx/conf/sites/sites.conf;
}
restrictions.conf
# Global restrictions configuration file.
# Designed to be included in any server {} block.
location = /favicon.ico {
log_not_found off;
access_log off;
}
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~ /\. {
deny all;
}
# Deny access to any files with a .php extension in the uploads directory
# Works in sub-directory installs and also in multisite network
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
my_site.conf
# WordPress single site rules.
# Designed to be included in any server {} block.
server {
server_name _;
return 302 $scheme://example.com$request_uri;
}
server {
## Your website name goes here.
server_name example.com;
## Your only path reference.
root /var/web/wordpress;
index index.php;
include /usr/local/nginx/conf/generic/restrictions.conf;
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
my_localhost.conf
server {
## Your website name goes here.
server_name localhost;
listen 8080;
if ($host != localhost) {
return 404;
}
## Your only path reference.
root /var/web/phpmyadmin;
index index.php index.html index.htm;
include /usr/local/nginx/conf/generic/restrictions.conf;
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
}
SSL by using LetsEncrypt Certbot
- 使用 snap 來安裝 certbot。
sudo snap install –classic certbot(注意 – -c)
- https://certbot.eff.org/docs/install.html
- 接著,按照這篇文章 step by step 操作:
https://certbot.eff.org/instructions
- 請注意,certbot 將會使用它自己內定的 nginx 組態檔路徑與名稱,/etc/nginx/nginx.conf。並且 nginx 執行檔必須在可執行路徑中,即,certbot 可自行呼叫執行。因為它會去修改組態檔,並且隨後執行 nginx 並測試是否成功獲取憑證。
- 故,應對方式便是必須停止 service,設定檔與執行檔可被索引到,如此,預期將會成功,再把被修改的組態更新到真正的組態檔上面。
- 最後,需注意,certbot 會定期更新憑證,故,以上額外的設定應是需保留著。並且,可能,當 nginx service 運作中,certbot 又更新憑證並驗證因而導致衝突。筆者接續在有限能力下 workaround 實測結果,於 /etc/nginx/ 加入 link,依然更新憑證失敗。故要不是有 script file 可搭配此 certbot,要不就是 conf file(注意是已被修改過的 conf)只能置於該處了。當前問題未解只能當憑證失效再來手動處理了。
對了,下 sudo certbot certonly –nginx(注意 – -n),就好了。那麼,schedule 檔就必須使用此指令,問題是筆者找不到該設定,先醬了。
- 以下是成功後,組態檔新增的內容:
# block 1:
# note that these are within the server block.
# need to change example.com to yours.
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# block 2:
# need to change example.com to yours.
server {
if ($host = example.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name example.com;
listen 80;
return 404; # managed by Certbot
}
- 如何查看憑證有效期限:
- openssl x509 -noout -dates -in /etc/letsencrypt/live/example.com/cert.pem
- renewal
- 註銷申請的憑證:
- sudo certbot delete
- 接著選擇代號以刪除之。
- 最後,以上,有幾點需注意的地方,
- 刪除後,記得 nginx config files 需要更新。同理新增也記得更新。因為我們通常做此類操作就是 subdomain name 變更了,故 config files 內將索引不到而報錯。
- 常用指令再列一下:
sudo certbot –nginx(注意 – -n)
sudo certbot certonly –nginx
sudo certbot renew –dryrun(注意 – -d)
sudo certbot delete
- 若在同一個 nginx 控管下有數個網站(domains,subdomains),那麼在做 certbot 時,可分開啟用(方法是在 sites-enabled 底下只放一支欲啟用者,其餘所有先停用,至於是否就不會合併附屬仍不肯定),那麼將會有個別的 tls 檔案,並且名稱將會是唯一的,即例如 a.com 和 www.a.com 即便重導向也無法通用,但 http:80 是允許重導向的。而若同時啟用數個或全部,則 certbot 將會從當中選取一個來産生 tls 檔案,而其他的便附屬於其下,故,這些全都有啟用 SSL 了。後者的缺點是使用者可從憑證查到所有關聯的網站。
- 20230503 補充,
有另一個 command,與 delete 有些差異,撤銷,
certbot revoke –cert-name example.com
或
certbot revoke –cert-path /etc/letsencrypt/live/example.com/cert.pem
(注意是 – – cert-)
revoke 主要指不再使用該 domain,delete 則僅將憑證刪除,細節請自行參考使用手冊。
再一個,
certbot certonly –standalone –preferred-challenges http -d [host1,host2,…] (注意 – -s & – -p)
此表示不針對任何特定的應用,如 nginx,表示,因當前還沒有既定的應用要使用它。然而,此 challenge 仍會使用 port 80,故任何使用 port 80 的應用都須先關閉。
- 20240117 補充,
承上,特別注意,假設某 host 已經使用,且僅使用 http web server,則上式將可能會與此 host 的狀態造成衝突,即,certbot 可能在自動 renew 時,附加去修改了 nginx 的 config file。換言之,上式使用 certonly 去抑制該行為,(或改用關鍵字 dns;又或[不確定]使用此參數表使用非制式埠 –http-01-port 8080[註,注意 – -http]),而 renew 是否也使用 certonly 就不得而知,故該留意。以下為參考。
https://community.letsencrypt.org/t/certbot-creates-a-task-automatically-can-it-be-prevented/182730
再來,
可在
/etc/letsencrypt/renewal/host_name.conf
中追加,以在 renew 後執行該 command
renew_hook = [command]
20210917 補充,使用 apt 預設安裝
- 之前在安裝 php 時,有加入 ppa,其會提示另有 nginx 套件,故我們就加入此 ppa,畢竟 ubuntu 官方更新地較保守。
- sudo add-apt-repository ppa:ondrej/nginx-mainline
- 我們在 /etc/nginx/sites-available/ 加入所有網站的 conf files。
- 並在 ./sites-enabled/ 中建立連結想要啟用的那些網站,nginx 會自動搜尋套用此目錄下的所有 files。
- 之後,比對前述,certbot 因而就可順利安裝與啟用與 renew。它可順利找到與修改由 ln 所連結的 config files。
- 不過有個問題需注意;前述的 config,需懂得如何套用到此,其中,若 fastcgi_pass php; 發生問題,則改為 fastcgi_pass unix:/run/php/php-fpm.sock;
- 此可參考 https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
- 以上,似乎沒什麼其他問題了。
- 再回文,若手動編譯安裝,我們可以將安裝路徑改為如同 apt 安裝路徑則就不會有後續困擾了。
- data files
/etc/nginx
/etc/nginx/nginx.conf
/etc/nginx/mime.types
/etc/nginx/fastcgi_params
/etc/nginx/sites-available/
/etc/nginx/sites-enabled/
/etc/nginx/sites-disabled/
- bin file
/usr/sbin/nginx
- nginx.conf 內容如下,記得要合稱內容的路徑。
而像動態載入 modules,其 config file 內容如下型式:
load_module modules/ngx_ssl_ct_module.so;
load_module modules/ngx_http_ssl_ct_module.so;
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
20210925 補充
- 統合以上,我們使用手動編譯安裝,並使用 apt 安裝的預設路徑,搭配安裝說明如前的參考資料。
./configure
--prefix=/etc/nginx
--sbin-path=/usr/sbin/nginx
--conf-path=/etc/nginx/nginx.conf
--pid-path=/run/nginx.pid
--error-log-path=/var/log/nginx/nginx_error.log
--http-log-path=/var/log/nginx/nginx_access.log
--with-http_ssl_module
--with-http_v2_module
--with-stream
--with-stream_ssl_module
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/run/nginx.pid --error-log-path=/var/log/nginx/nginx_error.log --http-log-path=/var/log/nginx/nginx_access.log --with-http_ssl_module --with-http_v2_module --with-stream --with-stream_ssl_module
...
...
creating objs/Makefile
Configuration summary
+ using system PCRE library
+ using system OpenSSL library
+ using system zlib library
nginx path prefix: "/etc/nginx"
nginx binary file: "/usr/sbin/nginx"
nginx modules path: "/etc/nginx/modules"
nginx configuration prefix: "/etc/nginx"
nginx configuration file: "/etc/nginx/nginx.conf"
nginx pid file: "/run/nginx.pid"
nginx error log file: "/var/log/nginx/nginx_error.log"
nginx http access log file: "/var/log/nginx/nginx_access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"
- 在安裝完成後,
- 接著下 sudo make clean
- 接著改寫 nginx.conf 成如下預設,但還需接著修改
# default file
# begin of nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
# dynamic modules
include /etc/nginx/modules-enabled/*.conf;
error_log /var/log/nginx/nginx_error.log;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
# tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# keepalive_timeout 65;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/nginx_access.log;
error_log /var/log/nginx/nginx_error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {
listen 80;
server_name localhost;
# charset koi8-r;
access_log /var/log/nginx/nginx_host_access.log main;
location / {
root html;
index index.html index.htm;
}
# error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
# location ~ \.php$ {
# proxy_pass http://127.0.0.1;
# }
# 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;
# include fastcgi_params;
# }
# deny access to .htaccess files, if Apache's document root. concurs with nginx's one.
# location ~ /\.ht {
# deny all;
# }
}
# another virtual host using mix of IP-, name-, and port-based configuration
# server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
# }
# HTTPS server
# server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
# }
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
# end of nginx.conf
- 我們先在 /etc/nginx 底下建立一系列的必要目錄。
sudo mkdir /etc/nginx/modules
sudo mkdir /etc/nginx/modules-available
sudo mkdir /etc/nginx/modules-enabled
sudo mkdir /etc/nginx/modules-disabled
sudo mkdir /etc/nginx/conf.d
sudo mkdir /etc/nginx/sites-available
sudo mkdir /etc/nginx/sites-enabled
sudo mkdir /etc/nginx/sites-disabled
# begin of nginx.conf
user www-data;
# usually equal to number of CPUs you have. run command "grep processor /proc/cpuinfo | wc -l" to find it
worker_processes auto;
worker_cpu_affinity auto;
# threading
# thread_pool default_thread threads=64 max_queue=65536;
pid /run/nginx.pid;
# dynamic modules
include /etc/nginx/modules-enabled/*.conf;
error_log /var/log/nginx/nginx_error.log;
# Keeps the logs free of messages about not being able to bind().
# daemon off;
events {
worker_connections 768;
# multi_accept on;
# accept_mutex off;
}
http {
##
# threading
##
# aio threads=default_thread;
##
# Basic Settings
##
sendfile on;
sendfile_max_chunk 512k;
# tcp_nopush on;
# tcp_nodelay on;
# rewrite_log on;
types_hash_max_size 2048;
# server_tokens off;
keepalive_timeout 65;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
# access_log off;
access_log /var/log/nginx/nginx_access.log;
error_log /var/log/nginx/nginx_error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
# php max upload limit cannot be larger than this
client_max_body_size 4096m; # 4G
# Upstream to abstract backend connection(s) for PHP.
upstream php {
# this should match value of "listen" directive in php-fpm pool
server unix:/run/php/php-fpm.sock;
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
# end of nginx.conf
- 最後,我們把前述的 restrictions.conf 放到 /etc/nginx/ 底下,並由每支 server.conf 引入。
- 其中,所有的 server 組態檔都放到 sites-available 底下,並在 sites-enabled 中建立連結,
- 而若要暫時取消,則將該連結移至 sites-disabled 中即可。
- 此外,由於怕先前發生過的 certbot 找不到組態檔,所以建立連結使用絕對路徑,已試過上述的一整套做法,沒問題了。
- 最後,請特別注意,要重新安裝 nginx 乃或重新安裝作業系統,務必要先註銷憑證,斥或新裝好的 nginx 就必須已手動設置好那些憑證設定於 .conf 檔中並予 certbot 以 renew。最好是前者的做法則從頭來過不怕出錯。否則(筆者自判斷),異地連上此網站將取用原先的憑證,而與此新建者不符而致無法存取此網站。
(20220105 這點再補充一下:)
當發生無法存取此網站時,建議先對瀏覽器清空該網站的快取資料試試看。或使用 curl 來探訪會更清楚發生什麼問題。
再來,例如我有新舊主機都用上 https://example.com 這個網址,則舊主機可以不用先刪除憑證,例如舊主機掛掉了無法啟動,但必須將它離線。則在新主機上,可重頭開始(安裝與)設置此網址下的新憑證。
- NGINX 還有些細部的設定;若網頁有某些未預期的行為,可能要先針對 nginx 的設定來調查。例如參見此段落的 nginx.conf
# php max upload limit cannot be larger than this
client_max_body_size 4096m; # 4G
- 這行便是設定能夠上傳到網站的最大檔案大小。若不設定,能上傳的大概幾咩而已。
- 延長 timeout 的時間,可於 http 或 server/location blocks 中:
http {
...
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
...
}
- 針對這個 timeout 問題做個補充。這個問題主要是遇到上傳檔案逾時的問題。然而,正因為上傳檔案是可能相當耗時的,故將不單只是上述處理可以解決。即尚可能影響到其他。在筆者安裝了 wordfence plugin 後,上傳檔案又變得不成功了。這是因為上傳此舉會觸發 wordfence 伴隨執行 php code。換言之,影響了 max_execution_time。而此設定在 php.ini 中,故,尚須將其設大,前述問題才得以解決。
- 承上,仍上傳失敗了。可見以下參考連結。
故第二步是將 wordfence 中,firewall rules 中,當前有搜尋到三條 “Malicious File Upload” rules,取消掉才成功。
- 第三步是在 wp-config.php 內加入一行,set_time_limit(60 or 0); 但這步非必要,請見下參考。
- https://wordpress.org/support/topic/fatal-error-from-lib-rules-php/
- 擋掉某個 IP 或網段;用法可置於 http or server or location(作用域不同)區塊中,其中 deny all 要放在最後面。放較前面的有較高優先權不被較後面者影響到。例如,適用於全新安裝 wordpress 時,且使用中的網址已是公開的,所以其他人都必須被擋在門外避免干擾我們的安裝。範例如下,
allow 192.168.0.0/24;
deny all;
http {
limit_conn_zone $binary_remote_addr zone=my_set_conns:10m;
limit_conn_log_level error;
limit_conn_status 503;
}
server {
limit_conn my_set_conns 1;
}
- configure 加入
--with-threads
(注意 – – w)的參考:
https://www.nginx.com/blog/thread-pools-boost-performance-9x/
不過筆者初級地試過,似乎沒多大改善。
另外該指出的,絕大部份常用的 modules 都已被預設含括進靜態編譯選項了且並不會有相關資訊顯示;而這些模組若不需要編入,則需明示排除或排除後轉成動態載入。只有少部份或第三方模組需明示編入(官方模組說明文件內亦會明示它非預設編入),如上面那行便是。
提到 nginx.conf 內的兩行設定,
worker_processes auto;
worker_cpu_affinity auto;
nginx 便會為我們在效能上做最佳的配置。我們透過 systemctl status nginx,可看到所産生的 processes,原則上幾支 processes 就對上幾核,故基本上 auto 就行了(自動全部用上)。
而我們若想手動全部的核都指定,則如下下法,若 8 核:
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
(補充:因為主行程可佔一核,所以或許使用 cpu_threads – 1 為佳,即此處設定 7 為佳)
原則上來說,若主機只有 webserver 的功能,則使用 multi-thread 可能效果有限。因為用上了便會有類 context switch 的額外花費。倒不如在 single-thread loop 所有 requests。而若 nginx 的 multi-thread 對應 multi-site(筆者未知),當實現兩個網站以上於同一台主機下,或許可試試看。
20211003 補充-網頁速度與安全性測試
# Add HTTP Strict Transport Security(HSTS)
add_header Strict-Transport-Security max-age=31536000;
# Add X-Frame-Options security header
add_header X-Frame-Options "SAMEORIGIN" always;
# Add X-XSS-Protection security header
add_header X-Xss-Protection "1; mode=block" always;
# Add X-Content-Type-Options security header
add_header X-Content-Type-Options "nosniff" always;
# Add Content Security Policy security header
# add_header Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';";
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';" always;
- 再一個。測試下,網頁似乎沒有壓縮。而看到 config file 內的 gzip 是有打開的, gzip on,因此,筆者觀點是,若有安裝 wordpress wp super cache,才把 gzip on 接續的 gzip 選項都打開。如此 wp super cache 就可預先壓縮。而若沒有安裝 cache,那麼即時的壓縮,對於沒有伺服器效能的微型網站反而是有點傷的。
- 因此提及了 wp super cache,以下就超簡短地說明一下 wp super cache 的安裝。而在此之前先說,還記得 siege 嗎?請參考前面文章。在 wp super cache 都設定好後,記得利用 siege,預先將所有連結都走過一遍,那麼,測試起來才會最為快速,即,測 all cached 的上界。
- wp super cache:
- 在安裝前,就先在 wp-config.php 內加入兩行,請注意,加在 require_once( ABSPATH . ‘wp-settings.php’ ); 的上面。
define( ‘WPCACHEHOME’, ‘/var/web/wordpress/wp-content/plugins/wp-super-cache/’ );
define( ‘WP_CACHE’, true );
- 在“設定 -> wp super cache -> 進階 -> Rejected URL Strings”加入兩行,
sitemap-.*.xml
sitemap.xml
- 而記得,若 wp super cache 每有頁面編輯更新就會清除快取的話,就再跑一次 siege。
20211024 將自己最後的版本置於下供參考
# 某些需換成適合自己的,不另標註
# 某些需修改的地方標示了 ****************
# begin of nginx.conf
user www-data;
# usually equal to number of CPUs you have. run command "grep processor /proc/cpuinfo | wc -l" to find it
worker_processes auto;
worker_cpu_affinity auto;
# worker_processes 15;
# worker_cpu_affinity 0000000000000010 0000000000000100 0000000000001000 0000000000010000 0000000000100000 0000000001000000 0000000010000000 0000000100000000 0000001000000000 0000010000000000 0000100000000000 0001000000000000 0010000000000000 0100000000000000 1000000000000000;
# threading
# thread_pool default_thread threads=96 max_queue=65536;
pid /run/nginx.pid;
# dynamic modules
include /etc/nginx/modules-enabled/*.conf;
error_log /var/log/nginx/nginx_error.log;
# Keeps the logs free of messages about not being able to bind().
# daemon off;
events {
worker_connections 1024; # same as ulimit -n
# multi_accept on; # all conns on a single process
# accept_mutex off;
}
http {
##
# threading
##
# aio threads=default_thread;
##
# Basic Settings
##
sendfile on;
sendfile_max_chunk 512k;
# tcp_nopush on;
# tcp_nodelay on;
# rewrite_log on;
types_hash_max_size 2048;
server_tokens off; # hide some server info for security
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
# added for Webp image files at 20220904 by ken.
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
# access_log off;
access_log /var/log/nginx/nginx_access.log;
error_log /var/log/nginx/nginx_error.log;
##
# Gzip Settings
##
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 1; # 1 or 6 depends on machine
gzip_buffers 16 256k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
# php max upload limit cannot be larger than this
client_max_body_size 4096m; # 4G
client_header_buffer_size 2k;
client_body_buffer_size 100k;
large_client_header_buffers 4 8k;
client_header_timeout 12;
client_body_timeout 24;
keepalive_timeout 65;
# send_timeout 24;
# proxy_read_timeout 300;
# proxy_connect_timeout 300;
# proxy_send_timeout 300;
# Upstream to abstract backend connection(s) for PHP.
upstream php {
# this should match value of "listen" directive in php-fpm pool
server unix:/run/php/php-fpm.sock;
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
# it is in case of if we are setting up a brand new wordpress,
# it is ought to block all others except ourselves.
# allow 192.168.0.0/24;
# deny all;
# limit_conn_zone $binary_remote_addr zone=my_set_conns:20m;
# limit_conn_log_level error;
# limit_conn_status 503;
server {
server_name _;
root /var/web/****************;
#return 302 $scheme://example.com$request_uri;
return 302 ****************error.html;
}
}
# end of nginx.conf
# 某些需換成適合自己的,不另標註
# 某些需修改的地方標示了 ****************
# begin of server_1.conf
# WordPress single site rules.
# Designed to be included in any server {} block.
server {
# limit_conn my_set_conns 1;
## Your website name goes here.
server_name ****************.tw www.****************.tw;
## Your only path reference.
root /var/web/****************;
index index.php;
include /etc/nginx/restrictions.conf;
access_log /var/log/nginx/nginx_host_access.log;
# Add HTTP Strict Transport Security(HSTS)
add_header Strict-Transport-Security max-age=31536000;
# Add X-Frame-Options security header
# add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Frame-Options deny;
# Add X-XSS-Protection security header
add_header X-Xss-Protection "1; mode=block" always;
# Add X-Content-Type-Options security header
add_header X-Content-Type-Options "nosniff" always;
# Add Content Security Policy security header
# add_header Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';";
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval';" always; # comment and added by kenwoo@20221213
# new added by kenwoo@20221213
#add_header Content-Security-Policy "default-src 'self'; font-src *;img-src * data:; script-src *; style-src *"; # for ref
add_header Referrer-Policy "strict-origin";
add_header Permissions-Policy "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
# NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include /etc/nginx/fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_pass php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
# added for Webp image files at 20220904 by ken.
location ~* ^.+\.(png|jpe?g|gif)$ {
add_header Vary Accept;
try_files $uri$webp_suffix $uri =404;
}
# for wordpress webp rewrite rules for jpg and png images
# try to load alternative image.png.webp before image.png
location /wp-content/uploads {
location ~ \.(png|jpe?g)$ {
add_header Vary "Accept-Encoding";
access_log off;
log_not_found off;
#expires max;
try_files $uri$webp_suffix $uri =404;
}
}
# webp rewrite rules for the plugin EWWW testing image
location /wp-content/plugins/ewww-image-optimizer/images {
location ~ \.(png|jpe?g)$ {
add_header Vary "Accept-Encoding";
access_log off;
log_not_found off;
#expires max;
try_files $uri$webp_suffix $uri =404;
}
}
# Wordfence plugin: Hiding .user.ini if your server runs NGINX
# The “.user.ini” file that Wordfence creates can contain sensitive information,
# and public access to it should be restricted.
# If your server runs NGINX you have to do this manually.
# Append the following directives to the server context of your “nginx.conf” file.
# Some hosts already prevent “.user.ini” from being publicly readable,
# since it is a common PHP configuration file. A few hosts that use NGINX,
# including Pressable, are using a different method to load the firewall and do not have a “.user.ini” file.
# In these cases, no additional steps are necessary.
## location ~ ^/\.user\.ini {
## deny all;
## }
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/****************/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/****************/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
# ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
}
server {
server_name ****************.tw www.****************.tw;
listen 80;
# might need this block; must check it out.
#if ($host != ****************.tw) {
# return 404;
#}
return 301 https://$host$request_uri;
## example nginx reverse proxy config file
#location /examples {
# proxy_pass http://localhost:8080/examples;
# proxy_buffering off;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-Host $host;
# proxy_set_header X-Forwarded-Port $server_port;
#}
}
# end of server_1.conf