Nginx 安装笔记

By | 2021年12月31日

1 Yum安装(推荐)

1.1 安装

# 1 添加官方提供的云源
sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
# 2 安装 Nginx
sudo yum install -y nginx
# 3 启动 Nginx,并设置开机自动运行
sudo systemctl start nginx.service
sudo systemctl enable nginx.service

1.2 配置文件

安装好后,cd /etc/nginx/,其中有个nginx.conf文件:

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

注意其中的  include 配置,它允许我们在 /etc/nginx/conf.d/中去配置自己的 server,安装好后 conf.d 文件夹中默认会有一个 default.conf,监听80端口,因此你安装完nginx输入 http://localhost,才会出来nginx的欢迎页面,这个默认配置如下:

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/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   /usr/share/nginx/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;
    #}
}

我们也可以在 conf.d 文件夹中自己添加一个文件,如 touch falpolicy.conf:

server {
    listen 81;
    server_name 192.168.1.220;
  
    # 如果关闭端口重定向的总开关,下面的配置都会因为端口不对而导致重定向失败,给他们各自加上 "proxy_set_header   Host $host:$server_port;",就没事了。
    #port_in_redirect off;

    location /falpolicy {
        proxy_pass http://192.168.1.200:8080/falpolicy;
        client_max_body_size 1000m;
        #proxy_set_header        Host $host:$server_port;
    }
    location /cas {
        proxy_pass http://192.168.1.200:8090/cas;
        #proxy_set_header        Host $host:$server_port;
    }
    location / {
        proxy_pass http://192.168.1.200:4200;
    }
}

2 手动安装

2.1 安装编译工具及库文件

sudo yum -y install gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-devel

2.2 首先要安装 prec(若上一步已安装 pcre pcre-devel 请忽略此步骤)

prec 作用是让 ngnix 支持 Rewrite 功能,下载地址:http://www.pcre.org。
首先,这里我下载的是 pcre-8.41.tar.gz,将下载的这个压缩文件拷贝到 linux 的 /usr/local(用户级的程序目录,可以理解为C:/Progrem Files/) 目录下解压出来。
接着,执行以下命令:

cd /usr/local/pcre-8.41
# 为了防止 /usr/local 目录凌乱,这里创建一个 build 目录用来作为安装目录
mkdir build
# 检测并生成 Makefile,可以用 --prefix 指定一个安装目录
./configure --prefix=/usr/local/pcre-8.41/build 
# 编译并安装,make它从Makefile中读取指令,然后编译(如果不指定安装目录,会被安装到 /usr/local 目录)
make && make install 
# 装好后查看pcre版本
./build/bin/pcre-config --version

2.3 安装 ngnix

下载地址:http://nginx.org(进入后,Stable version 稳定版)。
小提示:使用yum安装nginx的目录和使用源文件安装的文件位置不一样,需要用whereis nginx查看文件的安装位置。这里我们用源文件安装。
首先,这里我选择的是 nginx-1.12.2 稳定版,下载后的文件名是 nginx-1.12.2.tar.gz,将它解压到 /usr/local。
接着,执行以下命令:

cd /usr/local/nginx-1.12.2
mkdir build 
#添加 --with-http_ssl_module 是为了支持 https,但加了这个后 chkconfig那执行有问题
./configure --with-http_ssl_module --prefix=/usr/local/nginx-1.12.2/build 
make && make install
./build/sbin/nginx -v

2.4 启动/停止 nginx

安装好后,就需要启动它,由于我们安装时是指定了build安装目录的,所以启用nginx时也要指定配置文件目录。

cd /usr/local/pcre-8.41/build
# 启动nginx
./sbin/nginx -c ./conf/nginx.conf
# 使用netstat检查nginx是否已启动(nginx默认用80端口)
netstat -anp | grep :80
# 关闭nginx(也可以用kill命令来杀进程)
./sbin/nginx -s stop
# 如果改动了配置,可以用这个命令重新加载配置
./sbin/nginx -s reload
# 进去查看日志所在目录,这对于排查问题很有用
vi ./conf/nginx.conf

2.5 设置开机启动 nginx(利用 chkconfig)

nginx官方提供了启动脚本: https://www.nginx.com/resources/wiki/start/topics/examples/redhatnginxinit/
首先,进入 /etc/init.d/ 目录,新添加nginx文件(vi nginx 就可以添加了),把上述连接中的内容粘贴到nginx文件中。
接着,需要修改两处地方:
第一处:nginx=”/usr/sbin/nginx”
修改成:nginx=”/usr/local/nginx-1.12.2/build/sbin/nginx”
第二处:NGINX_CONF_FILE=”/etc/nginx/nginx.conf”
修改成:NGINX_CONF_FILE=”/usr/local/nginx-1.12.2/build/conf/nginx.conf”
请注意:需要设置 chmod 777 /etc/init.d/nginx ,否则 service nginx start 会报没有权限的错误。

上面的方法完成了用脚本管理nginx服务的功能,但是还是不太方便,比如要设置nginx开机启动等。这时可以使用chkconfig来设置。
先将nginx服务加入chkconfig管理列表:
# chkconfig –add /etc/init.d/nginx
加完这个之后,就可以使用service对nginx进行启动,重启等操作了,如:
# service nginx start
# service nginx stop
# service nginx reload
设置终端模式开机启动:
# chkconfig nginx on

2.6 配置 nginx

nginx启动后,经测试可以在局域网内任何机器输入:http://localhost,就会出现 Welcome to nginx!的欢迎界面。
(1)简单配置

server {
    listen 80;
    server_name shiyu.51meiy.com;
    location /shiyu_pos {
        proxy_pass http://4s.dkys.org:15102/shiyu_pos;
        deny 127.0.0.1; #拒绝的ip
        allow 172.18.5.54; #允许的ip
    }
}

3 connect() to 192.168.1.200:8090 failed (13: Permission denied) while connecting to upstream…

解决办法1:给SELinux加入通行规则(推荐)

SeLinux是2.6版本的Linux系统内核中提供的强制访问控制(MAC)系统。算是内置的安全系统,防火墙什么的应该算是外配的。
SELinux默认情况下,只允许非root权限用户,使用几个固定端口。
yum安装的nginx,创建了nginx用户,来进行系统资源的使用,nginx用户是没有root权限的。所以它无法监听 除了默认可以使用的那些 http端口,因为SELinux不允许。
为了保证安全,SELinux是不能关闭的,所以,只能让SELinux加入通行规则,开放一些端口:

# 查看允许访问的 http 端口
sudo semanage port -l | grep http_port_t

# 以ember开发为例,为了开发时处理跨域问题,我在nginx上做了反向代理,但还需要放行两个端口才行(4200-ember默认web服务器端口,8080-java后台接口端口),否则访问不了。
sudo semanage port -a -t http_port_t -p tcp 81
#sudo semanage port -a -t http_port_t -p tcp 4200
sudo semanage port -m -t http_port_t -p tcp 4200
sudo semanage port -a -t http_port_t -p tcp 8080

注意:这里添加4200端口时会报错:“ValueError:已定义端口tcp /4200”,这是因为4200已使用(不在http_port_t),可以通过用-a替换-m选项进行修改,将tcp port 4200添加到http_port_t

解决办法2:sudo启动

运行 sudo service nginx start nginx成功启动,但访问页面报5XX错误。falpolicy.conf  里我监听的 81 端口。这是因为linux下1023端口以下必须管理员权限才可以开启(包括1023端口),使用 sudo nginx 可以解决问题,但我找不到对应的启动脚本,但通过手动执行 sudo nginx -c /etc/nginx/nginx.conf确实可以正确访问页面了。

解决办法3:关闭SELinux

(a)临时关闭(不用重启机器)
# setenforce 0
(b)修改配置文件需要重启机器(我用的这种)
# vim /etc/selinux/config
将 SELINUX=enforcing 改为 SELINUX=disabled,重启机器即可

4 开启gzip压缩

在工作中,部署的jira外网https访问实在太慢,发现切换页面时加载了大量文件,有的高达2M。因此我在nginx上开启了gzip压缩,配置如下:

gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
gzip_vary off;

结果:切换页面速度立马快了一倍。

5 Http自动跳转到Https

server {
        listen 80;
        server_name game.onlypage.mobi;
        rewrite ^/(.*)$ https://game.onlypage.mobi/$1 permanent;
}

# HTTPS server
server {
        listen 443;
        server_name game.onlypage.mobi;

        root html;
        index index.html index.htm;

        ssl on;
        ssl_certificate cert.pem;
        ssl_certificate_key cert.key;

        ssl_session_timeout 5m;

        ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
        ssl_prefer_server_ciphers on;

        location / {
                #proxy_pass http://221.224.53.6:58081;
                proxy_pass http://localhost:8888;
                proxy_set_header Host $host:443;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forworded-For $proxy_add_x_forwarded_for;
                proxy_set_header Via "nginx";

                #root /mnt/wanghua/staticWebsite;
                #index maintain.html;
        }
}

6 实战配置

6.1 Jira http 配置

server {  
    listen 80;
    server_name faljira.uicp.cn;  
    #root html;  
    #index index.html index.htm index.php;  
    port_in_redirect off;  
  
    location ~* ^.+/.(jpg|jpeg|gif|png|swf|rar|zip|css|js|ico)$ {  ##static file   
        rewrite ^(.*) http://localhost:8080/$1;  
        break;  
    }
  
    location / {  
        proxy_pass http://localhost:8080;  
        proxy_redirect          off;    
        proxy_set_header        Host $host:$server_port;   ##重点在$server_port
        proxy_set_header        X-Real-IP $remote_addr;  
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;  
        proxy_max_temp_file_size 0;  
        proxy_connect_timeout 90;  
        proxy_send_timeout 90;  
        proxy_read_timeout 90;  
        proxy_buffer_size 4k;  
        proxy_buffers 4 32k;  
        proxy_busy_buffers_size 64k;  
        proxy_hide_header Vary;  
        proxy_set_header Accept-Encoding '';  
        proxy_set_header Referer $http_referer;  
        proxy_set_header Cookie $http_cookie;
    }  
} 

1)当我们安装JIRA时使用 8080 端口,但用 nginx 时却用 58080 时,如果不设置 “proxy_set_header Host $host:$server_port;” 会报下面的错误:
JIRA is reporting that it is running on the port ‘8080’, which does not match the hostname used to run these diagnostics, ‘58080’.
2)当我们把JIRA装在192.168.1.110上,但设置了 “proxy_pass http://localhost:8080; “,还会报以下错误:
JIRA is reporting that it is running on the hostname ‘localhost’, which does not match the hostname used to run these diagnostics, ‘192.168.1.110’.
解决办法是:改用 “proxy_pass http://192.168.1.110:8080; “;还可以设置 “proxy_set_header Host $host:$server_port;”来解决不报错的问题我发现。
3)需要特别注意:当使用花生壳将 58080 再次映射到外网的 80 端口时,我们此时在公网上用 “http://faljira.uicp.cn” 访问JIRA还会报上面类似的错误:
JIRA is reporting that it is running on the port ‘58080’, which does not match the hostname used to run these diagnostics, ’80’.
目前我的解决办法是直接保持外网域内网端口的映射一致,即将 ‘58080’ 改为 80 端口。(其他办法暂没想到)

6.2 Jira https 配置

#user  nobody;
worker_processes  1;

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

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    #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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;
    gzip_min_length 1k;
    gzip_buffers 4 16k;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
    gzip_vary off;


    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/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 faljira.uicp.cn;
  #server_name 192.168.1.111;

  root html;
  index index.html index.htm;

  ssl_certificate /root/cert.pem;
  ssl_certificate_key /root/cert.key;

        ssl_session_cache   shared:SSL:1m;
  ssl_session_timeout 5m;

  ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
  ssl_prefer_server_ciphers on;

  location /jira {  
    proxy_pass http://localhost:8080/jira;  
    proxy_redirect          off;    
    proxy_set_header        Host $host:$server_port;
    proxy_set_header        X-Real-IP $remote_addr;  
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;  
    proxy_set_header	X-Forwarded-Proto $scheme;
    proxy_max_temp_file_size 0;  
    proxy_connect_timeout 90;  
    proxy_send_timeout 90;  
    proxy_read_timeout 90;  
    proxy_buffer_size 4k;  
    proxy_buffers 4 32k;  
    proxy_busy_buffers_size 64k;  
    proxy_hide_header Vary;  
    proxy_set_header Accept-Encoding '';  
    proxy_set_header Referer $http_referer;  
    proxy_set_header Cookie $http_cookie;
    client_max_body_size	10M;
    proxy_set_header	X-Forwarded-Host $host;
    proxy_set_header	X-Forwarded-Server $host;
    proxy_redirect		http:// https://;
  }
    }
}

7 注意点

1)nginx上传文件大小限制

client_max_body_size 1000m;

2)配置https时,代码中如果有重定向就要注意了。一般情况下,如果有https请求进来,nginx会转到本地或内网的某个web上(如:proxy_pass http://localhost:8888;)。nginx跳转到这个web一般不需要再进行https请求了。因此问题来了,当访问:https://51meiy.com/console 时,其实最终访问的是 http://localhost:8888,此时,
若没有登录凭证,很可能被重定向到登录页面,如果代码中使用的是 request.sendRedirect(request.getContextPath() + “/login.do”); 这种方式,那么重定向后,我们的浏览器里会出现类似 “http://51meiy.com:443/console/login.do”,这导致访问不了登录页,因为nginx没有识别出来是 https 请求,而用了 http。
【解决办法】
照理说,nginx应该很智能才对,不应该给客户端 http 啊,最终发现问题出在”proxy_set_header Host $host:443;”,去掉这句就没有上面的问题了。

8 反向代理概念

反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,
并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。

发表评论

您的电子邮箱地址不会被公开。