分類: 架設網站

安裝 NGINX

No Comments

參考資料

使用自行編譯安裝

  • 將源碼目錄置於 /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
  • configure 之後,得到輸出如下
...
...
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
  • 搭配路徑,修改後的 nginx.conf
# 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

Categories: 架設網站

Tags:

PHP Code Snippets Powered By : XYZScripts.com