CentOS Linux 6 / 7 编译安装 Nginx

安装:

1、先去官网下载最新版的 Nginx :

http://nginx.org/en/download.html

如下图所示,复制 Nginx 的下载链接:

下载最新版的 Nginx
下载最新版的 Nginx

2、进入你的 CentOS ,先使用 yum 安装 wget(如果已经安装过,可忽略这步):

[root@host ~]# yum -y install wget

3、Ricky 个人是喜欢把一些临时文件放到 /tmp 目录下,所以进入 /tmp 目录,使用 wget 命令把 Nginx 的 tar.gz 包下载到这里,然后解压(或者下载到 PC 后,再通过 FTP 上传至 CentOS Linux ):

[root@host ~]# cd /tmp
[root@host tmp]# wget http://nginx.org/download/nginx-1.13.7.tar.gz
[root@host tmp]# tar -zxvf nginx-1.13.7.tar.gz

4、升级一下 CentOS ,并通过 yum 源来安装一些依赖包:

[root@host tmp]# yum -y update
[root@host tmp]# yum -y install pcre pcre-devel zlib zlib-devel gcc openssl openssl-devel

5、进入解压出来的文件夹,在这里执行编译安装操作(这里默认添加了对 https 的支持):

[root@host tmp]# cd nginx-1.13.7/
[root@host nginx-1.13.7]# ./configure --with-http_ssl_module
[root@host nginx-1.13.7]# make && make install

6、删除掉这个文件夹,并备份一下默认的配置文件:

[root@host nginx-1.13.7]# cd ..
[root@host tmp]# rm -rf nginx-1.13.7/
[root@host tmp]# cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.default

7、修改 Linux 的连接数最大值,并将命令添加到开机自启动(如果已添加可忽略):

[root@host tmp]# ulimit -SHn 65535
[root@host tmp]# echo "ulimit -SHn 65535" >> /etc/rc.local

[root@host tmp]# echo "* soft    nofile  65536" >> /etc/security/limits.conf
[root@host tmp]# echo "* hard    nofile  65536" >> /etc/security/limits.conf

8、把 Nginx 的启动脚本添加到开机自启动(还要给 rc.local 文件添加可执行权限,如果已添加可忽略),并执行 Nginx 的启动脚本即可:

(1)给 rc.local 文件添加可执行权限:
[root@host tmp]# chmod +x /etc/rc.d/rc.local
[root@host tmp]# chmod +x /etc/rc.local

(2)把 Nginx 的启动脚本添加到开机自启动:
[root@host tmp]# echo "/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf" >> /etc/rc.local

(3)执行 Nginx 的启动脚本:
[root@host tmp]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

至此,安装完成。

使用:

1、对 Nginx 配置文件的语法做检查:

[root@host ~]# /usr/local/nginx/sbin/nginx -t

2、开启 Nginx 的进程:

[root@host ~]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

3、重新载入 Nginx 的配置:

[root@host ~]# /usr/local/nginx/sbin/nginx -s reload

注意:经测试,如果您想让 Nginx 多监听一个 443 端口,reload 命令不会让其生效,需关闭 Nginx 的进程后再重新打开(但更换 https 证书可以 reload )。

4、关闭 Nginx 的进程:

[root@host ~]# /usr/local/nginx/sbin/nginx -s stop    # 快速停止 Nginx
[root@host ~]# /usr/local/nginx/sbin/nginx -s quit    # 完整有序地停止 Nginx

5、查看 Nginx 的版本号:

[root@host ~]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.15.6
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --with-http_ssl_module
[root@host ~]#

升级:

Nginx 的升级很简单,采用覆盖编译安装的方式即可(即直接重复上述过程)。

在执行 make install 命令后,你会发现在 /usr/local/nginx/sbin/ 目录下有两个文件:一个 nginx ,一个 nginx.old ;nginx.old 就是你旧版的那个 Nginx 。

如果需要回滚,请执行以下命令:

[root@host ~]# /usr/local/nginx/sbin/nginx -s stop # 快速停止 Nginx

或者:

[root@host ~]# /usr/local/nginx/sbin/nginx -s quit # 完整有序地停止 Nginx
[root@host ~]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.new
[root@host ~]# mv /usr/local/nginx/sbin/nginx.old /usr/local/nginx/sbin/nginx
[root@host ~]# /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf # 启动 Nginx

配置:

1、这是一份从网上 copy 的极具通用性的 nginx 配置文件,特点在于一个 server 作用域可以同时支持多个站点:

  • 如果接收到的是 a.test.com 的链接,那么变量 $domain 的值为 a.test.com ,同时代码目录就会定位到 /www/app/a.test.com ,日志文件就会定位到 /www/accelog/a.test.com/access.log ;
  • 如果接收到的是 b.test.com 的链接,那么同理。

请先创建以下文件夹,否则使用以下 nginx.conf 配置文件以后 Nginx 会打不开:

[root@host ~]# mkdir -p /www/accesslog/

( 1 )/usr/local/nginx/conf/nginx.conf :

user nobody nobody;
worker_processes 4; # 工作进程的数量,该值可与 CPU 核心数量相同

#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
error_log logs/error.log crit;

pid logs/nginx.pid;

#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 51200;

events
{
    use epoll;
    worker_connections 51200; # 单个工作进程的最大连接数
}

http
{
    include mime.types;
    default_type application/octet-stream;
    server_tokens off;
    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 8m;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 30;
    tcp_nodelay on;

    gzip on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript text/css application/xml;
    gzip_vary on;
    #limit_zone crawler $binary_remote_addr 10m;
    log_format default '$remote_addr - $remote_user [$time_local] "$request" '
    '$status $body_bytes_sent "$http_referer" '
    '"$http_user_agent" -- "$http_cookie" $http_x_forwarded_for "$proxy_add_x_forwarded_for" "$request_time"';

    server
    {
        listen 80;
        server_name _;
        set $domain $host;

        index index.jsp index.html index.htm;
        root /www/app/$domain;
        error_page 404 /404.html;
        error_page 500 501 502 503 504 505 /50x.html;

        if (-d $request_filename) {
            rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
        }

        location / {
            root /www/app/$domain;
            index index.jsp;
            proxy_pass http://localhost:8080;
            include /usr/local/nginx/conf/proxy.conf;
        }

        location ~* \.(jsp|php|asp|aspx|do|shtml)$ {
            root /www/app/$domain;
            index index.jsp;
            proxy_pass http://localhost:8080;
            include /usr/local/nginx/conf/proxy.conf;
        }

        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
            expires 1d;
        }

        location ~ .*\.(js|css)?$ {
            expires 1h;
        }

        location = /404.html {
            root /www/app/$domain;
        }

        location = /50x.html {
            root /www/app/$domain;
        }

        access_log /www/accesslog/access.log default;
    }
}

( 2 )/usr/local/nginx/conf/proxy.conf :

# proxy.conf
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;

client_max_body_size 10m;
client_body_buffer_size 128k;

proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffers 32 4k;

2、修改 Nginx 的配置文件,让其支持 https :

server {
    listen 443;
    ssl on;
    server_name localhost;
    root html;
    index index.html index.htm;
    ssl_certificate   cert/server.pem;
    ssl_certificate_key  cert/server.key;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    location / {
        root html;
        index index.html index.htm;
    }
}

其中 cert/server.pem 和 cert/server.key 为证书和私钥的存放位置,其中 cert/ 为相对路径,它的绝对路径应该是在 /usr/local/nginx/conf/cert 。

如果您使用的是较新版本的 nginx ,请将如下两行配置:

server {
    listen 443;
    ssl on;

    ......

}

改成:

server {
    listen 443 ssl;

    ......

}

否则 nginx 无法启动,会提示配置文件语法错误。

3、防止别人用他的域名随意指向我们的服务器:

server {

    ......

    set $host_flag 0;
    if ( $host ~ "1.1.1.1" ) { set $host_flag 1; }
    if ( $host ~ "test.com" ) { set $host_flag 1; }
    if ( $host ~ "test.cn" ) { set $host_flag 1; }
    if ( $host ~ "test.net" ) { set $host_flag 1; }
    if ($host_flag = 0) { return 403; }

    ......

}

即只允许通过 IP 地址 1.1.1.1 和域名 test.com 、test.cn 、test.net 来访问(如下所示),其余 IP 地址和域名访问均返回 403 :

  • http://1.1.1.1/index.html,可以访问
  • http://test.com/index.html,可以访问
  • http://test.cn/index.html,可以访问
  • http://test.net/index.html,可以访问
  • http://test.lol/index.html,不可以访问,返回 403

4、nginx 配置 ssi :

以下三个参数可以配置在 http、server 或 location 作用域下:

ssi on;
ssi_silent_errors off;
ssi_types text/shtml;
  • ssi :默认值 off ,启用 ssi 时将其设为 on ;
  • ssi_silent_errors :默认值 off ,开启后在处理 ssi 文件出错时不输出错误提示 ” [an error occurred while processing the directive] ” ;
  • ssi_types :默认已支持 html( 即 ssi_types text/html ),所以如果还需支持 shtml 则配置这条:ssi_types text/shtml 。

在实际的使用过程中发现还需要在 server 作用域下配置以下 location 才能使 ssi 生效( root 命令指向代码根目录),否则 ssi 的命令会以注释的形式出现在网页源代码中:

location ~* \.(html|shtml)$ {
    root /www/app/www.test.com/;
}

5、301 永久重定向和 302 临时重定向在 Nginx 上的配置:

现有如下需求,将一个链接根据规则重定向到另一个链接:

  • http://www.test.com/m → http://www.test.com/m/home
  • http://www.test.com/m/ → http://www.test.com/m/home
  • 但是 http://www.test.com/m/XXXX 不做重定向,XXXX 为任意字符
# 301 永久重定向
server {
    listen 80;

    ......

    rewrite "^/m$" /m/home permanent;
    rewrite "^/m/$" /m/home permanent;

    ......

}
# 302 临时重定向
server {
    listen 80;

    ......

    rewrite "^/m$" /m/home redirect;
    rewrite "^/m/$" /m/home redirect;

    ......

}

如需了解《 301 永久重定向和 302 临时重定向的区别》请点击这里

6、现有如下需求,需要对 http://www.test.com/m/ 下的所有链接切换到 https://www.test.com/m/:

  • http://www.test.com/m/ → https://www.test.com/m/
  • http://www.test.com/m/123 → https://www.test.com/m/123

在 server 作用域下配置:

server {
    listen 80;

    ......

    set $flag 0;
    if ($host ~* (www)\.test\.com) {
        set $flag 1;
    }

    if ($request_uri ~* ^/m/) {
        set $flag "${flag}1";
    }

    if ($flag ~ 11) {
        rewrite "^/(\S+)$" https://www.test.com/$1 last;
    }

    ......

}

server {
    listen 443;

    ......

}

7、现有如下需求,将一个链接根据规则重定向到另一个链接:

  • http://www.test.com/forum/registration.jsp?name=XXXX → http://www.test.com/forum/XXXX
  • XXXX 为任意字符

在 server 作用域下配置:

server {
    listen 80;

    ......

    set $flag 0;
    if ($host ~* (www)\.test\.com) {
        set $flag 1;
    }

    if ($request_uri ~* /forum/registration.jsp) {
        set $flag "${flag}1";
    }

    if ($query_string ~* "name=([\s\S]+)") {
        set $flag "${flag}1";
        set $name $1;
    }

    if ($flag = "111") {
        rewrite .* http://www.test.com/forum/$name? permanent;
    }

    ......

}

8、现有如下需求,将一个链接根据规则重定向到另一个链接,同时排除掉所有相关的 jsp 页面(即相关的 jsp 页面不做重定向):

  • http://www.test.com/forum/XXXX → http://www.test.com/forum/registration.jsp?name=XXXX
  • http://www.test.com/forum/XXXX/ → http://www.test.com/forum/registration.jsp?name=XXXX
  • 但是 http://www.test.com/forum/YYYY.jsp 的页面不做重定向
  • XXXX 包含特殊字符
  • YYYY 为任意字符

在 server 作用域下配置:

server {
    listen 80;

    ......

    set $flag 0;

    if ($host ~* (www)\.test\.com) {
        set $flag 1;
    }

    if ($request_uri ~* /forum/([^\f\n\r\t\v/]+)(/)?) {
        set $name $1;
        set $flag "${flag}1";
    }

    if ($request_uri ~* /forum/([\s\S]+).jsp) {
        set $flag "${flag}0";
    }

    if ($flag = "11") {
        rewrite .* http://www.test.com/forum/registration.jsp?name=$name permanent;
    }

    ......

}

关于正则表达式一些匹配上的解释说明:

  • \f :匹配换页字符;
  • \n :匹配换行字符;
  • \r :匹配回车符字符;
  • \s :匹配任何空白,包括空格、制表、换页等,与 ” [ \f\n\r\t\v] ” 等效;
  • \S :匹配任何非空白字符,与 ” [^ \f\n\r\t\v] ” 等效;
  • \t :匹配制表字符;
  • \v :匹配垂直制表符。

9、现有如下需求,将一个链接根据规则重定向到另一个链接,规则不匹配则默认跳转至另一个链接:

  • http://a.test.com/bbs/art.jsp?item={版块 id}&id={帖子 id} → http://b.test.com/m/post-{版块 id}-{帖子 id}-1.shtml
  • http://a.test.com/bbs/list.jsp?item={版块 id} → http://b.test.com/m/list-{版块 id}-1.shtml
  • 除了上述 a.test.com 的规则以外,其他 a.test.com 的链接默认跳转至 http://c.test.com/m/
  • 版块 id 和帖子 id 仅包含数字和大小写字母

在 server 作用域下配置:

server {
    listen 80;

    ......

    set $flag NULL;
    if ($request_uri ~* /bbs/art.jsp) {
        set $flag ART;
    }

    if ($request_uri ~* /bbs/list.jsp) {
        set $flag LIST;
    }

    if ($flag = "NULL") {
        rewrite ^/(.*) http://c.test.com/m/? permanent;
    }

    set $item NULL;
    set $id NULL;

    if ($query_string ~* "item=([A-Za-z0-9]+)&id=([A-Za-z0-9]+)") {
        set $item $1;
        set $id $2;
    }

    if ($flag = "ART") {
        rewrite .* http://b.test.com/m/post-$item-$id-1.shtml? permanent;
    }

    if ($query_string ~* "item=([A-Za-z0-9]+)") {
        set $item $1;
    }

    if ($flag = "LIST") {
        rewrite .* http://b.test.com/m/list-$item-1.shtml? permanent;
    }

    ......

}

10、(懒人版重定向配置)现有如下需求,将一个链接根据规则重定向到另一个链接:

  • https://www.test.com/m/ → https://www.test.com/m/home
  • https://www.test.com/m/dog/history.jsp → https://www.test.com/m/home/history
  • https://www.test.com/m/chapter-XXXX → https://www.test.com/m/book/XXXX/0
  • https://www.test.com/m/chapter-XXXX-YYYY → https://www.test.com/m/book/XXXX/YYYY
  • XXXX 和 YYYY 均为数字

如果不需要校验链接的来源域名(比如上面的 if ($host ~* (www)\.test\.com) { …… } 配置),也不需要那么复杂的判断,仅仅只是做一些 A → B 的重定向,那么可以在 server 作用域下这么配置:

server {
    listen 443;

    ......

    rewrite "^/m/$" /m/home permanent;
    rewrite "^/m/dog/history.jsp$" /m/home/history permanent;
    rewrite "^/m/chapter-(\d+)$" /m/book/$1/0 permanent;
    rewrite "^/m/chapter-(\d+)-(\d+)$" /m/book/$1/$2 permanent;

    ......

}

11、(懒人版重定向配置)现有如下需求,将一个链接根据规则重定向到另一个链接:

  • https://www.test.com/m/card.jsp?id=XXXX → https://www.test.com/m/book/XXXX
  • https://www.test.com/m/story.jsp?id=XXXX → https://www.test.com/m/book/XXXX/0
  • https://www.test.com/m/story.jsp?id=XXXX&cr=YYYY → https://www.test.com/m/book/XXXX/YYYY
  • https://www.test.com/m/story.jsp?id=XXXX&page=1&ty=0&cr=YYYY&num=20000&f=a → https://www.test.com/m/book/XXXX/YYYY
  • XXXX 和 YYYY 均为数字

这个懒人版重定向配置跟上面一个懒人版重定向配置还有所不同,因为 get 传值里的参数(就是 ? 号后面的 id=XXXX&cr=YYYY)是没法通过类似于 (\d+) 这样的正则表达式来直接匹配的,需要在 server 作用域下这么配置:

server {
    listen 443;

    ......

    rewrite "^/m/card.jsp$" /m/book/$arg_id? permanent;

    if ($arg_cr ~ (\d+)) { # 判断 cr 字段的值是否为数字
        # 第一句,这句在前,有顺序要求
        rewrite "^/m/story.jsp$" /m/book/$arg_id/$arg_cr? permanent;
    }

    # 第二句,这句在后,有顺序要求
    rewrite "^/m/story.jsp$" /m/book/$arg_id/0? permanent;

    ......

}

如果第二句写在了第一句的前面,那么在访问 https://www.test.com/m/story.jsp?id=89756&cr=9723444 的时候,会被重定向到 https://www.test.com/m/book/89756/0 ,而不是 https://www.test.com/m/book/89756/9723444 。

同时像 https://www.test.com/m/story.jsp?id=89756&page=1&ty=0&cr=9723444&num=20000&f=a 这种还有其他 get 传值的链接,也是可以被正确重定向到 https://www.test.com/m/book/89756/9723444 的。

12、(懒人版重定向配置)现有如下需求,如果是手机访问则跳转到手机版的网页链接,PC 等其他终端访问不做任何跳转:

  • https://www.test.com/chapter-XXXX( mobile )→ https://www.test.com/m/chapter-XXXX
  • https://www.test.com/chapter-XXXX-YYYY( mobile )→ https://www.test.com/m/chapter-XXXX-YYYY
  • XXXX 和 YYYY 均为数字

需要在 server 作用域下这么配置:

server {

    ......

    if ($http_user_agent ~* "UCBrowser|Android|Iphone|ipad|ipod|BlackBerry|Windows Phone|Symbian(.*)Series60/3|Symbian(.*)Series60/5") {
        rewrite "^/chapter-(\d+)$" /m/chapter-$1 permanent;
        rewrite "^/chapter-(\d+)-(\d+)$" /m/chapter-$1-$2 permanent;
    }

    ......

}

13、在 Nginx 上解决跨域问题(如 JS 上的跨域问题):

如果站点 a.test.com 上需要在用户浏览器端调用 b.test.com 的一些接口,那么可能存在因为跨域(即跨了域名)而导致接口无法访问的问题,则可以在 b.test.com 的 Nginx 的 location 作用域下这么配置来解决跨域的问题:

location / {

    ......

    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Origin "$http_origin";
        add_header Access-Control-Allow-Methods "POST, GET, PUT, OPTIONS, DELETE";
        add_header Access-Control-Max-Age "3600";
        add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
        add_header Access-Control-Allow-Credentials "true";
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }
    add_header 'Access-Control-Allow-Origin' '$http_origin';
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, DELETE, OPTIONS';
    add_header 'Access-Control-Allow-Headers' 'Content-Type,*';

    ......

}

注意:站点 a.test.com 去调用 b.test.com 的接口,那么以上 Nginx 跨域的配置是配置在 b.test.com 的 Nginx 上,而不是配置在 a.test.com 的 Nginx 上。

14、关于 Nginx 的 X-Frame-Options 响应头缺失漏洞,详情请点击这里

15、如果不希望将 Cookie 通过 proxy_pass 代理传递给后端,那么配置这一行即可:

proxy_set_header Cookie null;

例如:

location ^~ /test {

    ......

    set $backend "http://www.test.com";
    proxy_pass $backend$request_uri;

    proxy_set_header Cookie null;

    ......

}

上述配置亲测有效。

16、Nginx 的超时 timeout 配置详解(包括:keepalive_timeout 、client_body_timeout 、client_header_timeout 、send_timeout 、lingering_timeout 、resolver_timeout 、proxy_connect_timeout 、proxy_read_timeout 和 proxy_send_timeout 等),详情请点击这里

打赏作者
这里是 “ CCIE 工程师社区 ” 官方的捐款通道,您是否可以考虑请我们喝杯咖啡呢?

您的支持将鼓励我们继续创作!

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

Was this article helpful?

Related Articles