摘记一些常用的nginx和passenger(Passenger + Nginx)配置

Basic验证

测试环境的服务要放到互联网上时,如果为了避免测试服务的内容被搜索引擎收录,或者只提供给部分用户试用时,可以设置Basic Auth来限制访问。Basic Auth可以在应用层做,也可以在Nginx侧简单的设置。

如下是Nginx侧的设置方法, 摘录自Nginx官网文章Restricting Access with HTTP Basic Authentication

设置htpasswd

  1. 确保apache2-utils (Debian, Ubuntu) 或者 httpd-tools (RHEL/CentOS/Oracle Linux)已经安装。
  2. 创建htpasswd文件, 使用-c来创建新文件。如下是给用户名carl生成.htpasswd文件,在提示信息中输入访问密码。

    1
    2
    3
    4
    5
    $ sudo htpasswd -c /etc/nginx/.htpasswd carl
    New password:
    Re-type new password:
    Adding password for user carl
    $
  3. 如果要创建新的用户,那么去掉-c参数,往htpasswd文件中添加用户

    1
    2
    3
    4
    5
    $ sudo htpasswd /etc/nginx/.htpasswd shen
    New password:
    Re-type new password:
    Adding password for user shen
    $
  4. 确认.htpasswd文件中是否包含了刚设置的用户carl和shen

    1
    2
    3
    4
    $ cat /etc/nginx/.htpasswd
    carl:$apr1$ofR4vRu4$RwMK.HQawTD8/v.YOA2/d.
    shen:$apr1$c1vlrfgt$TqDy9JDsNcGyfTzcSOPLG0
    $

配置nginx

使用auth_basicauth_basic_user_file来在nginx侧配置Basic Authentication

例子:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 80;
server_name test.jibing57.com;
root /opt/app/web/hexo;
auth_basic "Administrator’s Area";
auth_basic_user_file .htpasswd;
location /images/ {
auth_basic off;
}
}

说明:

  • auth_basic 不为off,表示开启Basic Authentication
  • auth_basic_user_file .htpasswd 表示使用密码文件.htpasswd
  • location /images/中auth_basic off;标明访问/images/下文件不需要验证。

试验

如上配置且重启过nginx后。
访问http://test.jibing57.com就会弹出验证框
auth_basic_pop_username.png

访问http://test.jibing57.com/images/AWS/S3/steve.jpeg 就不需要验证
auth_basic_no_basic_path.png


https配置

https配置和例子

配置https的官方链接: Configuring HTTPS servers
ssl module参数配置说明链接: Module ngx_http_ssl_module

典型配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name test.jibing57.com;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
keepalive_timeout 70;
ssl_certificate cert/www.jibing57.com.pem;
ssl_certificate_key cert/www.jibing57.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}

延伸阅读: SNI

SNI说明

SNI产生的背景,如下文字来自维基百科

基于名称的虚拟主机允许多个DNS主机名由同一IP地址上的单个服务器(通常为Web服务器)托管。为了实现这一点,服务器使用客户端提供的主机名作为协议的一部分(对于HTTP,名称显示在主机头中)。但是,当使用HTTPS时,TLS握手发生在服务器看到任何HTTP头之前。因此,服务器不可能使用HTTP主机头中的信息来决定呈现哪个证书,并且因此只有由同一证书覆盖的名称才能由同一IP地址提供。

SNI是一个扩展的TLS计算机联网协议,在握手阶段由client发送的client hello中添加Extension的Type为server_name的方式来告诉服务端要访问的server name。服务端根据server name来返回对应的ssl证书信息。从而允许服务端支持在同一个IP,同一个端口上根据不同的server name来部署不同的https证书。

SNI抓包看协议

如下是通过Wireshark抓取的包。我访问www.qq.com时,握手阶段的Client Hello中,有type=0x0000的server_nam的extension。
sni_client_hello_on_qq_com.png

Nginx查看SNI支持

Nginx下使用nginx -V来检测nginx是否支持SNI, 如果有TLS SNI support enabled说明nginx支持SNI

1
2
3
4
$ nginx -V
...
TLS SNI support enabled
...

SNI参考资料

Nginx 444

Http code 444是nginx自定义的状态码,不是标准的HTTP code, 表示关闭一个连接,而不返回任何的响应头。

配置不响应未知Host的方法

配置Nginx不响应未知Host的请求的方法参见之前文章Nginx的HTTP Code444和307设置

配置5xx回应为不响应

配置5xx回应为444。

1
2
3
4
5
6
7
8
9
server {
...
error_page 500 502 503 504 =444 @blackhole;
location @blackhole {
return 444;
}
...
}

Nginx redirect配置

Nginx 301和307 redirect配置参见之前文章 Nginx的HTTP Code444和307设置

基础配置如下:

1
2
3
4
5
6
7
8
server {
listen 80;
server_name www.fake.com;
if ($request_method = POST) {
return 307 https://www.fakesite.com$request_uri;
}
return 301 https://www.fakesite.com$request_uri;
}

配置gzip压缩

Nginx gzip模块配置说明ngx_http_gzip_module
Nginx gzip_static模块配置说明ngx_http_gzip_static_module

gzip配置

典型配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
http {
...
server {
...
# gzip module
gzip on; # 是否开启gzip模块,on表示开启,off表示关闭;
gzip_buffers 16 8k;
gzip_min_length 1024;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
gzip_vary on;
gzip_proxied any;
gzip_disable "msie6";
...
}
...
}

其中:

  • gzip on: 是否开启gzip模块,on表示开启,off表示关闭;
  • gzip_buffers 16 8k: 设置临时内存空间,8k表示申请单位是8k,16表示每次以16个8k的单位去申请
  • gzip_min_length 1024: 表示压缩的最小size,如果文件小于1024,则不会被压缩。
  • gzip_http_version 1.1: 表示gzip基于http 1.1进行压缩,默认就是HTTP 1.1
  • gzip_comp_level 6: 表示压缩等级,数字越大,压缩越好,但越占用CPU,默认值是1.
  • gzip_types: 表示需要进行压缩的Content-Type的类型,文本类型的js,css,text,xml,json等压缩后效果比较明显
  • gzip_proxied: Nginx作为反向代理的时候启用,开启或者关闭后端服务器返回的结果,匹配的前提是后端服务器必须要返回包含”Via”的 header头。
    • 默认是 off
    • off - 关闭所有的代理结果数据的压缩
    • expired - 启用压缩,如果header头中包含 “Expires” 头信息
    • no-cache - 启用压缩,如果header头中包含 “Cache-Control:no-cache” 头信息
    • no-store - 启用压缩,如果header头中包含 “Cache-Control:no-store” 头信息
    • private - 启用压缩,如果header头中包含 “Cache-Control:private” 头信息
    • no_last_modified - 启用压缩,如果header头中不包含 “Last-Modified” 头信息
    • no_etag - 启用压缩 ,如果header头中不包含 “ETag” 头信息
    • auth - 启用压缩 , 如果header头中包含 “Authorization” 头信息
    • any - 无条件启用压缩
    • gzip_proxied [off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any] …
  • gzip_vary on: 是否在http header中添加Vary: Accept-Encoding,建议开启
  • gzip_disable "msie6": gzip_disable “msie6”的意思: disable compression for Internet Explorer versions 4-6, special mask “msie6” corresponds to the regular expression “MSIE [4-6].“, but works faster.

Reference:
gzip参数的中文详细说明,可参照博文Nginx Gzip模块启用和配置指令详解

gzip_static配置

gzip_static配置:

1
2
3
4
5
6
7
8
9
10
11
http {
...
server {
...
location ~ "^/assets/.+-[0-9a-f]{32}.*" {
gzip_static on;
expires 30d;
add_header Cache-Control public;
}
...
}

其中:

  • gzip_static on|off|always: 开启时,会读取预先压缩的文件,如果有gz文件,就直接返回gz文件的内容。有些老旧浏览器可能不兼容gzip格式,启用gzip_static时,最好同时保留原始静态文件。

配置最大上传文件限制

设置client允许上传的最大文件size。
Nginx官方说明ngx_http_core_module

典型配置:

1
2
3
4
5
6
7
8
9
10
http {
...
server {
...
client_max_body_size 100m;
client_body_buffer_size 256k;
...
}
...
}


日志格式

Nginx日志设置的guide: Configuring Logging
Nginx http log module的说明: Module ngx_http_log_module

日志设置例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http {
...
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format timer '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_user_agent" request_time $request_time (s)';
...
server {
...
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log notice;
...
}
...
}

主目录非根目录nginx配置

一篇root和alias区别的文章: Understanding the difference between the root and alias directives in Nginx

nginx+passenger配置子目录的例子

1
2
3
4
5
6
7
8
9
10
11
location /movieticket {
alias /opt/app/movieticket/current/public/;
# do not include "$uri/" in try_files, otherwise @my-app not work
try_files $uri @movieticket_app;
}
location @movieticket_app {
passenger_ruby /usr/local/rvm/wrappers/ruby-2.3.3/ruby;
passenger_enabled on;
root /opt/app/movieticket/current/public;
}

CentOS 6和7下的启动脚本

Nginx在各个系统中的启动脚本索引: NGINX Init Scripts

CentOS 7下启动脚本

CentOS 7下systemd官方推荐脚本: NGINX systemd service file

示例如下,其中PIDFile和nginx命令路径按照实际情况配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# vi /lib/systemd/system/nginx.service
--------------------------------
[Unit]
Description=The nginx HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/opt/nginx/sbin/nginx -t
ExecStart=/opt/nginx/sbin/nginx -c /opt/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
--------------------------------

其中:

  • PIDFile需要设置成和nginx.conf中一样的文件
  • nginx命令路径设成实际安装的路径
  • PrivateTmp按照实际需求设成true或是false。PrivateTmp的意思和passenger搭配的坑,参见之前的博文CentOS 7下passenger-status报错中systemd PrivateTmp一章的说明

启动命令:

1
2
# systemctl enable nginx.service
# systemctl start nginx.service

CentOS 6下的启动脚本

Nginx官方在Red Hat下的init script文章: Red Hat NGINX Init Script

实际使用时,可以根据官网的init脚本进行修改。

如下是passenger默认安装时,手动添加的init脚本的例子, 其中nginx路径为/opt/nginx/sbin/nginx.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
$ cat /etc/init.d/nginx
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig: - 85 15
# description: Nginx is an HTTP(S) server, HTTP(S) reverse \
# proxy and IMAP/POP3 proxy server
# processname: nginx
# config: /opt/nginx/conf/nginx.conf
# config: /etc/sysconfig/nginx
# pidfile: /var/run/nginx.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ "$NETWORKING" = "no" ] && exit 0
nginx="/opt/nginx/sbin/nginx"
prog=$(basename $nginx)
NGINX_CONF_FILE="/opt/nginx/conf/nginx.conf"
[ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
lockfile=/var/lock/subsys/nginx
#make_dirs() {
# # make required directories
# user=`$nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
# if [ -z "`grep $user /etc/passwd`" ]; then
# useradd -M -s /bin/nologin $user
# fi
# options=`$nginx -V 2>&1 | grep 'configure arguments:'`
# for opt in $options; do
# if [ `echo $opt | grep '.*-temp-path'` ]; then
# value=`echo $opt | cut -d "=" -f 2`
# if [ ! -d "$value" ]; then
# # echo "creating" $value
# mkdir -p $value && chown -R $user $value
# fi
# fi
# done
#}
start() {
[ -x $nginx ] || exit 5
[ -f $NGINX_CONF_FILE ] || exit 6
# make_dirs
echo -n $"Starting $prog: "
daemon $nginx -c $NGINX_CONF_FILE
retval=$?
echo
[ $retval -eq 0 ] && touch $lockfile
return $retval
}
stop() {
echo -n $"Stopping $prog: "
killproc $prog -QUIT
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
return $retval
}
restart() {
configtest || return $?
stop
sleep 1
start
}
reload() {
configtest || return $?
echo -n $"Reloading $prog: "
killproc $nginx -HUP
RETVAL=$?
echo
}
force_reload() {
restart
}
configtest() {
$nginx -t -c $NGINX_CONF_FILE
}
rh_status() {
status $prog
}
rh_status_q() {
rh_status >/dev/null 2>&1
}
case "$1" in
start)
rh_status_q && exit 0
$1
;;
stop)
rh_status_q || exit 0
$1
;;
restart|configtest)
$1
;;
reload)
rh_status_q || exit 7
$1
;;
force-reload)
force_reload
;;
status)
rh_status
;;
condrestart|try-restart)
rh_status_q || exit 0
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
exit 2
esac


项目部署中遇到的一些漏洞修补方法

HTTP/2漏洞 CVE-2019-9511/CVE-2019-9513/CVE-2019-9516

解决方案,升级到NGINX 1.16.1 (stable)以上
NGINX Updates Mitigate the August 2019 HTTP/2 Vulnerabilities
官方下载地址: nginx-1.16.1


Web服务器HTTP头信息公开处理

检测方法:

通过curl的参数-v来查看header和response的body, 例如 curl -v 'http://www.baidu.com/'

隐藏nginx版本号的方法:

修改nginx.conf文件 在http配置项中增加 server_tokens off;

修改源码:

修改源码,header中不显示对应的nginx和版本号
src/core/nginx.h 修改 NGINX_VER和NGINX_VERSION
src/http/ngx_http_header_filter_module.c 中 u_char ngx_http_server_string一行
src/http/ngx_http_special_response.c 中 修改 u_char ngx_http_error_tail相关内容


移除html/index.html

默认的index.html和50x.html会泄露nginx信息
移除nginx配置下默认的html/index.html


设置默认服务不返回任何消息

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80 default_server;
server_name _;
return 444;
}
server {
listen 443 default_server;
server_name _;
ssl_certificate cert/xxxxx.pem;
ssl_certificate_key cert/xxxxx.key;
return 404;
}

隐藏Passenger的版本

5.0.0版本后,在配置文件中设置passenger_show_version_in_header off;
官方说明https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_show_version_in_header


使用headers-more-nginx-module来去除header

可以使用扩展headers-more-nginx-module来修改nginx中的headers信息。

安装步骤

passenger-install-nginx-module安装headers-more-nginx-module的步骤:

1
2
3
4
wget https://github.com/openresty/headers-more-nginx-module/archive/v0.33.tar.gz
tar xzvf v0.33.tar.gz
cd headers-more-nginx-module-0.33/
passenger-install-nginx-module --extra-configure-flags=' --add-module=$HOME/headers-more-nginx-module-0.33/'

nginx配置

在nginx.conf中server|http的context中设置修改header

1
2
去掉指定header -- more_clear_headers 'Server' 'X-Powered-By';
替换指定header -- more_set_headers

参考

Passenger设置最小的instance数目

passenger关于instance数目有关的几个参数:

Ruby代码中,可能会有些Gem存在内存泄露问题。所以passenger_min_instances和passenger_max_pool_size的配置要错开点,不要保持很高的passenger_min_instances数,从而可以让passenger周期性的回收进程,一定程度上可以缓解内存泄露问题。

修改passenger的最大pool size,并且设置passenger_min_instances的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
http {
...
passenger_max_pool_size 40;
passenger_pool_idle_time 600;
passenger_max_preloader_idle_time 600;
server {
...
passenger_min_instances 16;
passenger_max_request_queue_size 1000;
...
}
...
}

反向代理

Nginx官方反向代理的资料

简单例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
http {
...
server {
...
location / {
proxy_pass http://web_production;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
...
}
...
}

相关文章

之前几篇涉及到反向代理的博文

proxy_pass 后链接是否带’/‘的几种情况

以下文字参考于: https://blog.csdn.net/u010433704/article/details/99945557
首先给出配置例子和转发结果

假设前端访问地址: http://192.168.1.1/proxy/test.html, 如下是各种配置下的代理结果。

例子 配置 结果
第一种 location /proxy/ {
    proxy_pass http://127.0.0.1/;
}
代理到URL:http://127.0.0.1/test.html
第二种 location /proxy/ {
    proxy_pass http://127.0.0.1;
}
代理到URL:http://127.0.0.1/proxy/test.html
第三种 location /proxy/ {
    proxy_pass http://127.0.0.1/aaa/;
}
代理到URL:http://127.0.0.1/aaa/test.html
第四种 location /proxy/ {
    proxy_pass http://127.0.0.1/aaa;
}
代理到URL:http://127.0.0.1/aaatest.html

结论:
HTTP URL的组成: scheme://host.domain:port/path/filename

  1. proxy_pass后面的URL只要带path(path也可以是/), 那么代理到后端URL中时,会删除location匹配的部分,将剩余的部分追加到proxy_pass后设定的URL中。比如第一、三和四种情况。
  2. proxy_pass后面的URL没有带path,那么直接将原请求path添加到proxy_pass的URL中进行代理。

注意:
proxy_pass后面的URL是用变量来实现的,代理规则有一些不同。具体请参照 如何配置Nginx的Dynamic Upstream指向ELB

proxy_redirect作用

proxy_redirect在官网中的用法:

1
2
3
4
5
Syntax: proxy_redirect default;
proxy_redirect off;
proxy_redirect redirect replacement;
Default: proxy_redirect default;
Context: http, server, location`

如果需要修改从被代理服务器传来的应答头中的”Location”和”Refresh”字段,可以用这个指令设置。
简易用法:
假如代理服务器返回了一个header头: Location: http://localhost:8000/two/some/uri/.
此时,如果配置文件中设置了

1
proxy_redirect http://localhost:8000/two/ http://frontend/one/;`

那么header头会被反向代理服务器改写为Location: http://frontend/one/some/uri/

反向代理并改写链接

正常反向代理请求,会将请求路径一同反向代理到upstream服务器中。
比如原连接是https://source.com/xxxxxx/helloworld, 反向代理到example.com时,链接为https://example.com/xxxxxx/helloworld
此时的配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream xxxx {
server example.com:443;
}
# xxxxxx
location ^~ /xxxxxx/ {
proxy_pass https://xxxx;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}

有些情况下,需要去掉/xxxxxx这个前缀, 将https://source.com/xxxxxx/helloworld的请求反向代理到example.com时,变为https://example.com/helloworld的话,这时可以有如下两个方法:

方法一:proxy_pass 地址后添加斜杠

之前已经介绍过,当proxy_pass后传递的值带路径时,会自动将location中匹配的路径截断。
所以,只需要将proxy_pass https://xxxx;加一个/, 改为proxy_pass https://xxxx/;, 即可
配置变为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream xxxx {
server example.com:443;
}
# xxxxxx
location ^~ /xxxxxx/ {
proxy_pass https://xxxx/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
}

方法二:手动添加rewrite改写

可以在location节点中,使用rewrite来手动替换链接。
正则匹配xxxxxx,并且只将xxxxxx后的路径反向代理到upstream中。
配置变为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upstream xxxx {
server example.com:443;
}
# xxxxxx
location ^~ /xxxxxx/ {
proxy_pass https://xxxx;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
rewrite "^/xxxxxx/(.*)$" /$1 break;
}

判断参数再进行redirect

比如需要将https://test.com/?flag=dk重定向到https://staging.com/?flag=dk
nginx可以配置如下:

1
2
3
4
5
6
7
8
9
10
server {
...
server_name test.com;
...
location / {
if ($arg_flag = dk) {
return 301 https://staging.com/?flag=dk;
}
...
}

参考: Nginx redirect URL with specific query parameter

http重定向到https

监听80端口,有请求就重定向到https请求。

1
2
3
4
5
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}

Passenger设置Nodejs

使用Nodejs配置的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
http {
...
server {
listen 80;
server_name test.domain.com;
# gzip module
gzip on;
gzip_buffers 16 8k;
gzip_min_length 1024;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
gzip_vary on;
gzip_proxied any;
gzip_disable "msie6";
# Turn on Passenger
passenger_enabled on;
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log notice;
# Tell Passenger that your app is a Node.js app
passenger_app_type node;
passenger_app_root /app/appname/current;
passenger_startup_file /app/appname/current/dist/app.js;
passenger_force_max_concurrent_requests_per_process 100;
passenger_max_request_queue_size 4000;
}
passenger_pre_start http://test.domain.com/health;
...
}

其中参数说明:

  • passenger_enabled: 表示开启passenger
  • passenger_app_type node: 表示application类型是nodejs
  • passenger_app_root: 用来设置应用根目录
  • passenger_startup_file: 设置启动应用的起始文件,ruby默认是config.ru, node默认是app.js, 也可以手动指定
  • [passenger_force_max_concurrent_requests_per_process](https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_force_max_concurrent_requests_per_process): 该设置用来告诉passenger最多同时将多少个请求发到一个处理进程中。如果设置为0意味着无限,默认的-1是让Passenger自己检测。该选项主要有两个用法:
  • passenger_max_request_queue_size: 设置该server最多能承载的request队列长度。
  • passenger_pre_start: 默认下passenger启动后不会启动application进程,有请求后才会启动。这会导致第一次请求会有一些延迟。使用passenger_pre_start url可以在passenger启动时就预热application进程。
    • 注意点:
      • url的链接的domain,需要设置为server_name一样的值
      • 可以结合passenger_min_instances来使用。
      • passenger不会解析url中真实的domain,而是会将请求发送到localhost,同时使用url中的domain来设置Host的header。
      • 支持https请求,不会验证ssl证书。

参数使用说明:
因为node单进程就可以吃进大量的request,而reqeust多了后,请求速度会降低,因此需要配置passenger_force_max_concurrent_requests_per_process来控制单个node处理请求的并发数。 Rails应用的话,就不需要配置该选项。

Passenger设置header

Passenger支持使用passenger_set_header来设置传递给application的http header。
说明链接: https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_set_header

使用例子

1
2
3
4
5
6
7
server {
...
passenger_set_header X-Forwarded-Proto https;
passenger_set_header X-Forwarded-For app.examples.com;
passenger_set_header X-Forwarded-Host app.examples.com;
...
}

nginx location中的redirect

简单的跳转到不同域名下相同路径下的话,只需要使用return 301 https://new_domain.com$request_uri;即可。

但如果需要跳转到不同的域名的不同路径时,可以使用rewrite通过正则匹配来重写
https://old_example.com/old_path的请求redirect到https://new_examples.com/new_path中,保留相同的其余路径和参数

1
2
3
4
5
6
7
8
server {
server_name old_example.com;
...
location /old_path {
rewrite ^(/old_path)(.*)$ https://new_examples.com/new_path$2 permanent;
}
...
}

如果需要匹配多个旧路径,比如old_pathold_path_second,那么可用正则来实现

1
rewrite ^(/old_path|/old_path_second)(.*)$ https://new_examples.com/new_path$2 permanent;

参考:

Nginx反向代理Jenkins basic auth重复redirect问题

测试环境中,使用Nginx反向代理请求到后端的Jenkins服务上。
测试环境中,所有的请求都添加了简单的Basic Auth。结果发现访问Jenkins的页面,输入Basic Auth的账号密码后,会重复redirect
网上搜索过后发现是Nignx将Authorization header转给后端Jenkins服务导致的。
需要在反向代码时将Authorization的header去掉。

1
2
# Don't forward auth to Tomcat
proxy_set_header Authorization "";

修改过后的配置:

1
2
3
4
5
6
7
8
9
10
11
location / {
proxy_pass http://jenkins_app;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
# Don't forward auth to Tomcat
proxy_set_header Authorization "";
}

参考:

Nginx 变量upstream_xxx_time详解

网上找的一张图,完整解释了$request_time,$upstream_header_time,$upstream_connect_timeupstream_response_time各个变量代表的意义。

images/Nginx/nginx_all_upstream_time.jpg

Reference

留言