编译安装 nginx
Nginx 是现如今性能最强劲的 Web 服务器及反向代理服务器
构建前准备
1. 依赖项
apt install libgd-dev libgeoip-dev -y
debian12 纯净版所需完整依赖
apt install -y bzip2 xz-utils
apt install -y make gcc libgd-dev libgeoip-dev libxml2-dev libxslt1-dev
2. CAP_NET_BIND_SERVICE
CAP_NET_BIND_SERVICE
是 Linux 内核中的一个能力(capability),它允许进程绑定低于 1024
的端口。这个能力通常用于网络服务程序,如 Web 服务器、邮件服务器等,以便它们能够监听系统保留的低端口。
在 Linux 系统中,只有 root 用户和具有 CAP_NET_BIND_SERVICE
能力的进程才能绑定低于 1024
的端口。为了给一个应用程序设置这个能力,可以使用 setcap 命令。
本次 nginx 的 master 进程用户是 nginx 而非 root,所以需要为程序设置 CAP_NET_BIND_SERVICE
setcap cap_net_bind_service=+eip /server/nginx/sbin/nginx
setcap -r /server/nginx/sbin/nginx
3. 查看构建参数
cd /home/nginx/nginx-1.28.0
./configure --help > help.ini
--help 打印此消息
--prefix=PATH 设置安装前缀
--sbin-path=PATH 设置nginx二进制路径名
--modules-path=PATH 设置模块的路径
--conf-path=PATH 设置nginx.conf路径名
--error-log-path=PATH 设置错误日志路径
--pid-path=PATH PID 文件路径名
--lock-path=PATH nginx.lock 路径名
--user=USER 为工作进程设置非特权用户
--group=GROUP 为工作进程设置非特权组
--build=NAME 设置构建名称
--builddir=DIR 设置构建目录
--with-select_module 启用 select 模块
--without-select_module 禁用 select 模块
--with-poll_module 启用 poll 模块
--without-poll_module 禁用 poll 模块
--with-threads 启用线程池支持
--with-file-aio 启用文件AIO支持
--without-quic_bpf_module 禁用 ngx_quic_bpf_module
--with-http_ssl_module 启用 ngx_http_ssl_module
--with-http_v2_module 启用 ngx_http_v2_module
--with-http_v3_module 启用 ngx_http_v3_module
--with-http_realip_module 启用 ngx_http_realip_module
--with-http_addition_module 启用 ngx_http_addition_module
--with-http_xslt_module 启用 ngx_http_xslt_module
--with-http_xslt_module=dynamic 启用 动态 ngx_http_xslt_module
--with-http_image_filter_module 启用 ngx_http_image_filter_module
--with-http_image_filter_module=dynamic 启用 动态 ngx_http_image_filter_module
--with-http_geoip_module 启用 ngx_http_geoip_module
--with-http_geoip_module=dynamic 启用 动态 ngx_http_geoip_module
--with-http_sub_module 启用 ngx_http_sub_module
--with-http_dav_module 启用 ngx_http_dav_module
--with-http_flv_module 启用 ngx_http_flv_module
--with-http_mp4_module 启用 ngx_http_mp4_module
--with-http_gunzip_module 启用 ngx_http_gunzip_module
--with-http_gzip_static_module 启用 ngx_http_gzip_static_module
--with-http_auth_request_module 启用 ngx_http_auth_request_module
--with-http_random_index_module 启用 ngx_http_random_index_module
--with-http_secure_link_module 启用 ngx_http_secure_link_module
--with-http_degradation_module 启用 ngx_http_degradation_module
--with-http_slice_module 启用 ngx_http_slice_module
--with-http_stub_status_module 启用 ngx_http_stub_status_module
--without-http_charset_module 禁用 ngx_http_charset_module
--without-http_gzip_module 禁用 ngx_http_gzip_module
--without-http_ssi_module 禁用 ngx_http_ssi_module
--without-http_userid_module 禁用 ngx_http_userid_module
--without-http_access_module 禁用 ngx_http_access_module
--without-http_auth_basic_module 禁用 ngx_http_auth_basic_module
--without-http_mirror_module 禁用 ngx_http_mirror_module
--without-http_autoindex_module 禁用 ngx_http_autoindex_module
--without-http_geo_module 禁用 ngx_http_geo_module
--without-http_map_module 禁用 ngx_http_map_module
--without-http_split_clients_module 禁用 ngx_http_split_clients_module
--without-http_referer_module 禁用 ngx_http_referer_module
--without-http_rewrite_module 禁用 ngx_http_rewrite_module
--without-http_proxy_module 禁用 ngx_http_proxy_module
--without-http_fastcgi_module 禁用 ngx_http_fastcgi_module
--without-http_uwsgi_module 禁用 ngx_http_uwsgi_module
--without-http_scgi_module 禁用 ngx_http_scgi_module
--without-http_grpc_module 禁用 ngx_http_grpc_module
--without-http_memcached_module 禁用 ngx_http_memcached_module
--without-http_limit_conn_module 禁用 ngx_http_limit_conn_module
--without-http_limit_req_module 禁用 ngx_http_limit_req_module
--without-http_empty_gif_module 禁用 ngx_http_empty_gif_module
--without-http_browser_module 禁用 ngx_http_browser_module
--without-http_upstream_hash_module 禁用 ngx_http_upstream_hash_module
--without-http_upstream_ip_hash_module 禁用 ngx_http_upstream_ip_hash_module
--without-http_upstream_least_conn_module 禁用 ngx_http_upstream_least_conn_module
--without-http_upstream_random_module 禁用 ngx_http_upstream_random_module
--without-http_upstream_keepalive_module 禁用 ngx_http_upstream_keepalive_module
--without-http_upstream_zone_module 禁用 ngx_http_upstream_zone_module
--with-http_perl_module 启用 ngx_http_perl_module
--with-http_perl_module=dynamic 启用 动态 ngx_http_perl_module
--with-perl_modules_path=PATH 设置Perl模块的路径
--with-perl=PATH 设置perl二进制路径名
--http-log-path=PATH 设置http访问日志路径名
--http-client-body-temp-path=PATH 设置http客户端请求正文临时文件的存放路径
--http-proxy-temp-path=PATH 设置http代理临时文件的存放路径
--http-fastcgi-temp-path=PATH 设置存放http fastcgi临时文件的路径
--http-uwsgi-temp-path=PATH 设置存放http uwsgi临时文件的路径
--http-scgi-temp-path=PATH 设置存放http scgi临时文件的路径
--without-http 禁用HTTP服务器
--without-http-cache 禁用HTTP缓存
--with-mail 启用POP3/IMAP4/SMTP代理模块
--with-mail=dynamic 启用 动态 POP3/IMAP4/SMTP 代理模块
--with-mail_ssl_module 启用 ngx_mail_ssl_module
--without-mail_pop3_module 禁用 ngx_mail_pop3_module
--without-mail_imap_module 禁用 ngx_mail_imap_module
--without-mail_smtp_module 禁用 ngx_mail_smtp_module
--with-stream 启用 TCP/UDP proxy module
--with-stream=dynamic 启用 动态 TCP/UDP proxy module
--with-stream_ssl_module 启用 ngx_stream_ssl_module
--with-stream_realip_module 启用 ngx_stream_realip_module
--with-stream_geoip_module 启用 ngx_stream_geoip_module
--with-stream_geoip_module=dynamic 启用 动态 ngx_stream_geoip_module
--with-stream_ssl_preread_module 启用 ngx_stream_ssl_preread_module
--without-stream_limit_conn_module 禁用 ngx_stream_limit_conn_module
--without-stream_access_module 禁用 ngx_stream_access_module
--without-stream_geo_module 禁用 ngx_stream_geo_module
--without-stream_map_module 禁用 ngx_stream_map_module
--without-stream_split_clients_module 禁用 ngx_stream_split_clients_module
--without-stream_return_module 禁用 ngx_stream_return_module
--without-stream_pass_module 禁用 ngx_stream_pass_module
--without-stream_set_module 禁用 ngx_stream_set_module
--without-stream_upstream_hash_module 禁用 ngx_stream_upstream_hash_module
--without-stream_upstream_least_conn_module 禁用 ngx_stream_upstream_least_conn_module
--without-stream_upstream_random_module 禁用 ngx_stream_upstream_random_module
--without-stream_upstream_zone_module 禁用 ngx_stream_upstream_zone_module
--with-google_perftools_module 启用 ngx_google_perftools_module
--with-cpp_test_module 启用 ngx_cpp_test_module
--add-module=PATH 启用 external module
--add-dynamic-module=PATH 启用 动态 external module
--with-compat 动态模块兼容性
--with-cc=PATH 设置C编译器的路径名
--with-cpp=PATH 设置C预处理器的路径名
--with-cc-opt=OPTIONS 设置额外的C编译器选项
--with-ld-opt=OPTIONS 设置其他链接器选项
--with-cpu-opt=CPU 构建指定的CPU,有效值:pentium, pentiumpro, pentium3, pentium4, athlon, opteron, sparc32, sparc64, ppc64
--without-pcre 禁用PCRE库的使用
--with-pcre 强制使用PCRE库
--with-pcre=DIR 设置PCRE库源的路径
--with-pcre-opt=OPTIONS 为PCRE设置额外的构建选项
--with-pcre-jit JIT编译支持PCRE
--without-pcre2 不使用PCRE2库
--with-zlib=DIR 设置zlib库源文件的路径
--with-zlib-opt=OPTIONS 为zlib设置额外的构建选项
--with-zlib-asm=CPU 汇编器使用zlib源码优化指定CPU,有效值:pentium, pentiumpro
--with-libatomic 强制libatomic操作库使用
--with-libatomic=DIR 设置libatomic操作库源的路径
--with-openssl=DIR 设置OpenSSL库源代码的路径
--with-openssl-opt=OPTIONS 为OpenSSL设置额外的构建选项
--with-debug 启用调试日志记录
开始构建
1. 构建指令
su - nginx -s /bin/zsh
mkdir ~/nginx-1.28.0/build_nginx
cd ~/nginx-1.28.0
./configure --prefix=/server/nginx \
--builddir=/home/nginx/nginx-1.28.0/build_nginx \
--without-select_module \
--without-poll_module \
--with-threads \
--with-file-aio \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_xslt_module \
--with-http_image_filter_module \
--with-http_geoip_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_auth_request_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_degradation_module \
--with-http_slice_module \
--with-http_stub_status_module \
--with-pcre=/home/nginx/pcre2-10.45 \
--with-pcre-jit \
--with-zlib=/home/nginx/zlib-1.3.1 \
--with-openssl=/home/nginx/openssl-3.5.2 > stdout.log
# 4核以上可以使用 make -j4 编译
make -j4 > make.log
# 不挂起,后台执行
nohup make -j4 &
# 安装
make install
./configure --prefix=/server/nginx \
--builddir=/home/nginx/nginx-1.28.0/build_nginx \
# 核心功能模块
--with-threads \
--with-file-aio \
# 自带http功能模块全部启用
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_xslt_module \
--with-http_image_filter_module \
--with-http_geoip_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_auth_request_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_degradation_module \
--with-http_slice_module \
--with-http_stub_status_module \
# prel 是试验性的
--with-http_perl_module \
# 启用邮箱服务
--with-mail \
--with-mail_ssl_module \
# 启用负载均衡服务
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module \
--with-stream_geoip_module \
--with-stream_ssl_preread_module \
# 外库路径
--with-pcre=/home/nginx/pcre2-10.45 \
--with-pcre-jit \
--with-zlib=/home/nginx/zlib-1.3.1 \
--with-openssl=/home/nginx/openssl-3.5.2
# 开启调试,生产环境下建议禁用
--with-debug > stdout.log
2. 测试
使用 curl 检测是否成功
/server/nginx/sbin/nginx
curl -I 127.0.0.1
HTTP/1.1 200 OK
Server: nginx/1.22.1
Date: Tue, 30 Aug 2022 11:50:51 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 30 Aug 2022 11:50:36 GMT
Connection: keep-alive
ETag: "630df98c-267"
Accept-Ranges: bytes
curl: (7) Failed to connect to 127.0.0.1 port 80: 拒绝连接
构建说明
Debian11发行版
下 nginx-1.22.1
完成了上面两套指令的构建
debian12+发行版
只针对当前 nginx 版本的 本次构建指令
进行构建
平滑升级
Nginx 可实现平滑升级,具体操作如下:
1. 构建指令
构建指令参考 开始构建 基本一样
注意
平滑升级时,新版 nginx 只需要执行编译,不要执行安装
2. 替换主文件
# 先备份旧版主文件,防止意外出现
mv /server/nginx/sbin/nginx{,.bak}
# 拷贝新的主文件,到指定目录
cp -p -r /home/nginx/nginx-1.28.0/build_nginx/nginx /server/nginx/sbin/
3. 升级操作
# 通过 ps 指令,检查旧版 nginx 的 pid
ps -ef|grep -E "nginx|PID" |grep -v grep
ps aux|grep -E "nginx|PID" |grep -v grep
# 通过 cat 查看 pid 文件,并记录进程 id 号
cat /run/nginx/process.pid
# 通过 `kill -USR2 <pid>` 启动新版 nginx 可执行文件
kill -USR2 `cat /run/nginx/process.pid`
# 使用 `kill -WINCH <pid>` 来关闭旧版 nginx 进程
kill -WINCH <old_nginx_pid>
提示
kill -WINCH <pid>
指令可实现:当进程没有访问者时,系统自动关闭当前进程
配置
nginx 配置仅有一个入口文件,统一称做 主配置文件
主配置文件
通过 include
指令加载其它文件中的配置信息,统一称做 子配置文件
下面是一些具有代表性的配置文件,提供参考:
1. 主配置文件
# /server/nginx/conf/nginx.conf
# 引入主配置文件
include /server/etc/nginx/main.nginx;
# /server/nginx/conf/nginx.conf
# user 指令是用于指定子进程(worker)用户和用户组
# user 指令只有当主进程(master)用户是超级用户(root)是才有意义,否则会被忽略掉
# user www www;
worker_processes auto;
worker_rlimit_core 50M;
worker_shutdown_timeout 30s;
worker_rlimit_nofile 10240;
working_directory /tmp/;
pid /run/nginx/nginx.pid;
events
{
worker_connections 10240;
worker_aio_requests 1024;
}
http
{
# debug info notice warn error crit alert emerg
error_log /server/logs/nginx/error.log error;
access_log /server/logs/nginx/access.log;
include mime.types;
default_type application/octet-stream;
charset utf-8;
autoindex off;
autoindex_exact_size on;
autoindex_localtime on;
# 启用 gzip 压缩,自定义配置文件
include /server/etc/nginx/custom/gzip;
sendfile on;
# 在响应头中隐藏 Nginx 版本号
server_tokens off;
# 隐藏fastcgi的头信息,如:php-fpm
fastcgi_hide_header X-Powered-By;
# 隐藏反向代理服务器头信息,如:httpd
proxy_hide_header X-Powered-By;
# nginx 启用 TLSv1.3 加密传输协议
ssl_protocols TLSv1.3;
# 预防web攻击
# 预防点击劫持,页面只能被本站页面嵌入到 iframe 或者 frame 中
add_header X-Frame-Options SAMEORIGIN always;
# 检测到反射的跨站点脚本(XSS)攻击时阻止页面加载
add_header X-XSS-Protection "1; mode=block" always;
# 防止基于 MIME 类型混淆的攻击
add_header X-Content-Type-Options nosniff always;
# http 区块设定加载请求限制,需server区块配合
include /server/etc/nginx/custom/limit_req_http;
include /server/etc/nginx/custom/default.nginx;
include /server/sites/*.nginx;
}
# /server/etc/nginx/custom/default.nginx
# 默认站点
server
{
listen 80 default;
root /server/default;
index index.html;
access_log off; # 关闭访问日志
log_not_found off; # 关闭错误日志
# 处理不以指定扩展名结尾的请求
location ~* \.(?!jpe?g$|png$|html?$|css$|js$|ico$|gif$|txt$)[a-zA-Z0-9_\-]+$
{
deny all;
}
}
## php8.4 默认站点
server
{
listen 80;
server_name 84.php.io;
root /server/default;
index index.php;
access_log off; # 关闭访问日志
log_not_found off; # 关闭错误日志
# allow 192.168.3.0/24; # 允许 192.168.3 段的局域网访问
# allow 192.168.10.0/24; # 允许 192.168.10 段的局域网访问
# allow 192.168.66.0/24; # 允许 192.168.66 段的局域网访问
# deny all; # 拒绝 其他IP访问
# php-fpm 转发
location ~* \.php$
{
fastcgi_pass 127.0.0.1:9684;
include fastcgi.conf;
}
}
## php7.4 默认站点
server
{
listen 80;
server_name 74.php.io;
root /server/default;
index index.php;
location /
{
access_log off; # 关闭访问日志
log_not_found off; # 关闭错误日志
}
# allow 192.168.3.0/24; # 允许 192.168.3 段的局域网访问
# allow 192.168.10.0/24; # 允许 192.168.10 段的局域网访问
# allow 192.168.66.0/24; # 允许 192.168.66 段的局域网访问
# deny all; # 拒绝 其他IP访问
# php-fpm 转发
location ~* \.php$
{
fastcgi_pass 127.0.0.1:9674;
include fastcgi.conf;
}
}
# /server/etc/nginx/custom/php_forward
location ~* \.php$
{
# 唯一入口限制:非 /index.php 禁止访问
location ~* ^(?!/index\.php$)
{
deny all;
}
# 转发的 php-fpm 版本
fastcgi_pass 127.0.0.1:9684;
# 根据文件名转发,完全不需要配置 fastcgi_index
# fastcgi_index index.php;
# 载入官方最新版的 fastcgi_params
include fastcgi.conf;
}
2. fastcgi 参数模版
nginx 自带了两个 fastcgi 参数模版,这里推荐使用官方最新的 fastcgi.conf
如果不符合项目需求,还可以自定义 fastcgi 参数配置模板
移除 PATH_INFO
nginx+php-fpm 不论如何配置,PATH_INFO 始终为空,暂无法解决,而且对业务来讲 PATH_INFO 并没有提供任何优秀的作用,所以决定移除 PATH_INFO
3. 缓存模板
站点不经常变动的静态文件,可以让客户端缓存,以减轻服务器压力
# /server/etc/nginx/custom/cache
# html页面缓存,~* 不区分大小写
location ~* \.(?:htm|html)$
{
# 设置缓存上面定义的后缀文件缓存到浏览器的生存时间
expires 1d; # 暂定缓存1天,变动频繁的页面减少缓存时间,页面基本不变的增加缓存时间
# access_log off; # 关闭访问日志,html页面需要开启访问日志
log_not_found off; # 关闭错误日志
}
# 静态资源缓存,~* 不区分大小写
location ~* \.(?:js|css|json|txt|xml|jpe?g|png|gif|ico)$
{
# 设置缓存上面定义的后缀文件缓存到浏览器的生存时间
expires 30d; # 缓存30天
access_log off; # 关闭访问日志
log_not_found off; # 关闭错误日志
}
# favicon 图标缓存
location = /favicon.ico
{
expires 30d; # 缓存30天
access_log off; # 关闭访问日志
log_not_found off; # 关闭错误日志
}
# robots 文件通常不能缓存,蜘蛛一直在爬取
location = /robots.txt
{
access_log off; # 关闭访问日志
log_not_found off; # 关闭错误日志
}
# /server/etc/nginx/custom/no_cache
# 如果你的站点静态文件实时变动,则应该禁用缓存
# 禁用缓存,不区分大小写正则匹配
location ~* \.(?:js|css|json|txt|xml|jpe?g|png|gif|ico|html?)$
{
# 禁止缓存,每次都从服务器请求
add_header Cache-Control no-store always;
}
4. 开启压缩
nginx 支持对文件开启 gzip 压缩,以加快网络传输速度,下面是 html 缓存模板案例:
# /server/etc/nginx/custom/gzip
# == ngx_http_gzip_static_module ==
# 允许发送带有.gz文件扩展名的预压缩文件,而不是常规文件
gzip_static on;
# == ngx_http_gunzip_module ==
gunzip on;
# 解压缩响应的缓冲区的数量和大小,默认即可
# gunzip_buffers 32 4k|16 8k;
# == ngx_http_gzip_module ==
# gzip_http_version, gzip_proxied, gzip_disable, gzip_vary 这4个参数需要根前面2个模块结合使用
# 开启gzip压缩
gzip on;
# 压缩响应的缓冲区的数量和大小,默认即可
# gzip_buffers 32 4k|16 8k;
# 压缩级别,1-9
gzip_comp_level 5;
# ie6之前的浏览器不开启gzip压缩
gzip_disable msie6;
# 启用 gzip 压缩的 http 最低协议版本,默认即可
# gzip_http_version 1.1;
# 文件小于100k,不开启gzip压缩
gzip_min_length 1k;
# 对反向代理传输数据,提供压缩,默认就好
gzip_proxied off;
# 指定文件类型启用gzip压缩,强制开启 text/html
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 通过启用响应标头字段,来控制是否压缩
gzip_vary on;
5. 限制请求数量
nginx 通过 http 区块
和 server 区块
结合可以限制请求数量
# /server/etc/nginx/custom/limit_req_http
# === http 区块设定加载请求限制,需server区块配合 === #
# 限制请求:针对相同客户端ip(这条最重要,其它的看实际情况添加)
# - 默认,每秒可处理5条请求,生成1个标识为 with_ip ,容量为 10M 的内存区域,用来存储访问的频次信息
limit_req_zone $binary_remote_addr zone=with_ip:10m rate=5r/s;
# 限制请求:针对相同客户端ip、相同访问文件路径
# - 默认,每秒可处理 1 条请求,生成1个标识为 with_ip_request ,容量为 5M 的内存区域,用来存储访问的频次信息
limit_req_zone $binary_remote_addr$uri zone=with_ip_request:5m rate=1r/s;
# 限制请求:针对相同客户端ip、相同访问文件路径、相同请求参数
# - 默认,每秒可处理 1 条请求,生成1个标识为 with_ip_request_param ,容量为 5M 的内存区域,用来存储访问的频次信息
limit_req_zone $binary_remote_addr$request_uri zone=with_ip_request_param:5m rate=1r/s;
# 直接写入 server 区块内,不需要单独文件
# === server 区块执行限制,需配合 http 区块 === #
# 针对ip地址相同的请求:
# 每秒最多处理请求数:10 条(rate+burst),
# 设置为nodelay,则每秒可以瞬时处理的请求数为:10 条(rate+burst)
# 每秒请求超过10条(rate+burst)后,直接返回503
limit_req zone=with_ip burst=5 nodelay;
# 针对ip地址相同,访问文件路径相同的请求:
# 每秒最多处理请求数:6 条(rate+burst),
# 每秒前 3 条(rate+delay)请求可以瞬时处理,后3条请求设置定时器,延时处理,
# 每秒请求超过6条(rate+burst)后,直接返回503
limit_req zone=with_ip_request burst=5 delay=2;
# 通常非静态网站,缓存交给后端语言自己处理
location ~* \.php$
{
# 针对ip地址相同,访问文件路径相同,访问参数相同的请求:
# 每秒最多处理 6 条(rate+burst)请求,
# delay留空,则每秒前 1 条(rate)请求可以瞬时处理,后5条(burst)请求设置定时器,延时处理,
# 每秒超过6 条(rate+burst)请求后,直接返回503
limit_req zone=with_ip_request_param burst=5;
}
提示
server 区块里的 zone=with_ip
对应 http 区块里的 $binary_remote_addr
,可以直接限制同 ip 地址的访问频率
对于不同站点(server 区块) ,设置可能各不相同,直接在站点文件中设置即可
6. 文件禁止访问
nginx server
可以对特定文件和目录进行访问限制
# /server/etc/nginx/custom/no_access
# 禁止访问所有以 . 开始的文件和目录
location ~ /\..+
{
deny all;
}
# 禁止访问的文件,不区分大小写正则匹配
location ~* /(?:LICENSE|README\.md)
{
deny all;
}
7. 跨域请求
nginx server
可以配置跨域请求,跨域请求没有单独文件,按需写入对应站点的 location 区块
/server/etc/nginx/custom/cross_domain
# 跨域请求没有单独文件,按需写入对应站点的 location 区块
# ====== 设置跨域配置 Start ====== #
# $http_origin 读取的是请求头header中 origin 的值
if ($http_origin ~* "^(?:http|https)://api\.example\.com$"){
# 该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
add_header Access-Control-Allow-Origin $http_origin always;
# 该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。
# 注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS always;
# 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。
# 默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。
# 这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
add_header Access-Control-Allow-Credentials true always;
# 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。
# 它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。
add_header Access-Control-Allow-Headers DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,x-auth-token always;
# 该字段可选,用来指定本次预检请求的有效期,单位为秒。
# 下面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。
add_header Access-Control-Max-Age 1728000 always;
# 预检请求处理
if ($request_method = OPTIONS) {
return 204;
}
}
# ====== 设置跨域配置 End ====== #
8. 站点配置案例
# /server/sites/*.nginx
server
{
# == 编码3选1,通常建议全部使用 utf-8 == #
# charset gbk; # 支持gbk编码
# charset utf-8; # 支持utf8编码,http区块已经设置
# charset ISO-88509-1; # 同时支持 utf8 和 gbk 编码
listen 80;
server_name example.com www.example.com;
root /www/www_example_com;
access_log /server/logs/nginx/www_example_com.log;
index index.html index.htm;
# 静态站点支持的请求方式仅限 get或post
if ($request_method !~* GET|POST)
{
return 403;
}
# 启用缓存设置,自定义配置文件
include custom/cache;
location /
{
# 加载请求限制,server区域,需要结合http区块
include custom/limit_req_server;
}
# 禁止访问的目录或文件
include custom/no_access;
}
# /server/sites/*.(conf|nginx)
server
{
listen 80;
server_name tp.io;
root /www/tp/public;
access_log /server/logs/nginx/tp.log;
index index.php;
# 设置站点仅至允许 GET、POST 请求
if ($request_method !~* GET|POST|OPTIONS)
{
return 403;
}
# 静态资源启用缓存设置
# include custom/cache; # 部署环境启用
# 加载请求限制,server区域,需要结合http区块
# include custom/limit_req_server; # 部署环境启用
# 统一入口
location /
{
# 隐藏入口文件,如果文件或目录不存在,则尝试使用入口文件解析
if (!-e $request_filename){
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
# 开启跨域请求处理,看自己的后端项目有否需要接受外部请求
# 内容见 cross_domain 配置
}
# 对文件类型为 .php 的url请求做转发处理
include custom/php_forward;
# 禁止访问的目录或文件
# include custom/no_access; # 部署环境可以需要启用,更加安全
}
# /server/sites/*.(conf|nginx)
server
{
listen 80;
server_name core.qyphp.com;
root /www/qyphp/core/public;
access_log /server/logs/nginx/qyphp_core.log;
index index.php;
# 设置站点仅至允许 GET、POST 请求
if ($request_method !~* GET|POST|OPTIONS)
{
return 403;
}
# 静态资源启用缓存设置
# include custom/cache; # 部署环境启用
# 加载请求限制,server区域,需要结合http区块
# include custom/limit_req_server; # 部署环境启用
# 统一入口
location /
{
# 隐藏入口文件,如果文件或目录不存在,则尝试使用入口文件解析
# try_files 解析效率比 rewrite 高
try_files $uri $uri/ /index.php?$query_string;
# 开启跨域请求处理,看自己的后端项目有否需要接受外部请求
# 内容见 cross_domain 配置
}
# 对文件类型为 .php 的url请求做转发处理
include custom/php_forward;
# 禁止访问的目录或文件
# include custom/no_access; # 部署环境可以需要启用,更加安全
}
# /server/sites/*.(conf|nginx)
server
{
listen 80;
server_name laravel.io;
root /www/laravel/public;
access_log /server/logs/nginx/laravel.log;
index index.php;
# 设置站点仅至允许 GET、POST 请求
if ($request_method !~* GET|POST|OPTIONS)
{
return 403;
}
# 静态资源启用缓存设置
# include custom/cache; # 部署环境启用
# 加载请求限制,server区域,需要结合http区块
# include custom/limit_req_server; # 部署环境启用
# 统一入口
location /
{
# 隐藏入口文件,如果文件或目录不存在,则尝试使用入口文件解析
# try_files 解析效率比 rewrite 高
try_files $uri $uri/ /index.php?$query_string;
# 开启跨域请求处理,看自己的后端项目有否需要接受外部请求
# 内容见 cross_domain 配置
}
# 对文件类型为 .php 的url请求做转发处理
include custom/php_forward;
# 禁止访问的目录或文件
# include custom/no_access; # 部署环境可以需要启用,更加安全
}
# /server/sites/*.nginx
server
{
#SSL 默认访问端口号为 443
listen 443 ssl;
#请填写证书文件的相对路径或绝对路径
server_name qyphp.e8so.com;
#请填写证书文件的相对路径或绝对路径
ssl_certificate /server/ssl/qyphp.e8so.com_bundle.crt;
#请填写私钥文件的相对路径或绝对路径
ssl_certificate_key /server/ssl/qyphp.e8so.com.key;
ssl_session_timeout 5m;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
root /www/qyphp/public;
access_log /server/logs/nginx/qyphp_e8so_com.log;
index index.php;
if ($request_method !~* GET|POST|OPTIONS)
{
return 403;
}
# include custom/cache;
# include custom/limit_req_server;
location /
{
try_files $uri $uri/ /index.php?$query_string;
}
# 对文件类型为 .php 的url请求做转发处理
include custom/php_forward;
# 禁止访问的目录或文件
include custom/no_access;
}
# HTTP 自动跳转 HTTPS
server {
listen 80;
server_name qyphp.e8so.com;
return 301 https://$host$request_uri;
}
9. SSL 证书权限
SSL 证书的存放目录及其文件的权限只应该让需要的程序看到,比如只让 nginx 的主进程用户读取
# 查看 nginx 主进程用户
ps -ef|grep -E "nginx|PID"|grep -E "master|PID"|grep -v grep
ps aux|grep -E "nginx|PID"|grep -E "master|PID"|grep -v grep
设置 SSL 证书权限
本次测试环境的 nginx 主进程用户是 nginx 用户
chown nginx -R /server/ssl/
chmod 700 /server/ssl/
chmod 400 /server/ssl/*
管理
1. 内置指令
nginx 内置管理指令
common | info |
---|---|
/server/nginx/sbin/nginx | 启动 |
/server/nginx/sbin/nginx -s quit | 正常关闭 |
/server/nginx/sbin/nginx -s stop | 快速关闭 |
/server/nginx/sbin/nginx -s reload | 重新载入 |
/server/nginx/sbin/nginx -s reopen | 重新打开日志 |
/server/nginx/sbin/nginx -t | 检测配置文件 |
/server/nginx/sbin/nginx -h | 显示帮助信息 |
/server/nginx/sbin/nginx -T | 列出配置信息 |
2. 指定配置文件
nginx 可以在运行时指定配置文件入口:
/server/nginx/sbin/nginx -c /server/nginx/conf/nginx.conf
检测指定的 Nginx 配置文件:
/server/nginx/sbin/nginx -t -c /server/nginx/conf/nginx.conf
3. 强制停止
linux 可以强制停止 Nginx 进程
pkill -9 nginx
Systemd
linux 服务器推荐使用 Systemd 单元(Unit)
来管理守护进程,下面为 Nginx 添加 Systemd
1. 添加 Systemd 流程
echo "[Unit]
Description=nginx-1.28.x
After=network.target
[Service]
Type=forking
User=nginx
Group=nginx
RuntimeDirectory=nginx
RuntimeDirectoryMode=0750
ExecStartPre=/server/nginx/sbin/nginx -t
ExecStart=/server/nginx/sbin/nginx -c /server/nginx/conf/nginx.conf
ExecReload=/server/nginx/sbin/nginx -s reload
ExecStop=/server/nginx/sbin/nginx -s quit
Restart=on-failure
PrivateTmp=true
[Install]
WantedBy=multi-user.target
" > /lib/systemd/system/nginx.service
# 重新载入 Systemd 配置
systemctl daemon-reload
# nginx.service 加入开机启动
systemctl enable nginx.service
2. 管理 Systemd
common | info |
---|---|
systemctl start nginx.service | 立即启动 nginx 服务 |
systemctl stop nginx.service | 立即停止 nginx 服务 |
systemctl reload nginx.service | 重新加载 nginx 服务配置 |
systemctl status nginx.service | 检查 nginx 状态 |
用户身份认证
nginx server
通过 ngx_http_auth_basic_module
模块下的 HTTP Basic Authentication (HTTP 基本身份验证)
协议,可以设置客户端通过验证用户名和密码来访问网站资源
nginx 的用户身份认证,仅区分登录用户和非登录用户的访问差异,没有其它更复杂的权限认证功能
1. 配置
ngx_http_auth_basic_module
模块,只有 2 条配置指令:
1. auth_basic 指令
该指令,用于控制 nginx 是否开启 HTTP 基本身份验证
功能
- 语法 : auth_basic string | off;
- 默认 : auth_basic off;
- 区块 : http 、 server 、 location 、 limit_except
语法分析:
- off : 表示关闭
HTTP 基本身份验证
功能,这是默认值 - string : 任意字符串,表示开启
HTTP 基本身份验证
功能,并且字符串会作为登录提示信息出现
区块说明:
- 通常不会在 http 区块上开启
HTTP 基本身份验证
功能,除非服务器上所有网站都仅供内部访问 - server 和 location 区块是最常使用的
- 当然
HTTP 基本身份验证
功能,只有非常简单的站点需要使用它,比如:纯静态资源站或者其它没有认证系统的网站
注意
在同一区块,仅一个 auth_basic
生效,后面覆盖前面
2. auth_basic_user_file 指令
该指令,用于指定保存用户名和密码的文件
- 语法 : auth_basic_user_file file;
- 默认 : —
- 区块 : http 、 server 、 location 、 limit_except
指定保存用户名和密码的文件,格式如下:
# 备注说明
用户名1:加密密码1
用户名2:加密密码2:用户2说明
用户名3:加密密码3
区块说明:基本跟 auth_basic 指令一致
注意
在同一区块,auth_basic_user_file
仅一个生效,后面覆盖前面
2. 生成加密密码
主要使用以下加密类型生成密码:
crypt()
: 标准 Unix 密码算法MD5-based password algorithm (apr1)
: 基于 MD5 的密码算法,Apache 变体
提示:
apr1
加密类型是 nginx 支持的加密方式中最安全的
对生成密码的工具没有特殊要求,只要加密方式正确,nginx 就可以正确验证
事实上,nginx 是通过 --with-openssl=xxx
自己编译的 openssl 外库来验证的
本次我们就直接使用 openssl passwd 来演示生成加密密码,具体如下:
# 创建目录
mkdir /server/default/nginx_auth
# 创建两个站点的认证文件,文件名与站点名相似
touch /server/default/nginx_auth/{public,qydoc,wangdoc}
# 权限 nginx 读
chown root:nginx /server/default/nginx_auth/{public,qydoc,wangdoc}
chmod 640 /server/default/nginx_auth/{public,qydoc,wangdoc}
# 用户1 emad 密码 123
echo -n 'emad:' >> /server/default/nginx_auth/public
openssl passwd -apr1 123 >> /server/default/nginx_auth/public
# 用户1 emad 密码 123
echo -n 'emad:' >> /server/default/nginx_auth/qydoc
openssl passwd -apr1 123 >> /server/default/nginx_auth/qydoc
# 用户2 qydoc 密码 qy123
echo -n 'qydoc:' >> /server/default/nginx_auth/qydoc
openssl passwd -apr1 qy123 >> /server/default/nginx_auth/qydoc
# 用户1 emad 密码 123
echo -n 'emad:' >> /server/default/nginx_auth/wangdoc
openssl passwd -apr1 123 >> /server/default/nginx_auth/wangdoc
# 用户2 wangdoc 密码 wd123
echo -n 'wangdoc:' >> /server/default/nginx_auth/wangdoc
openssl passwd -apr1 wd123 >> /server/default/nginx_auth/wangdoc
3. 站点配置
nginx 虚拟主机配置 HTTP 基本身份验证
案例
server
{
...
# 整个站点启用身份验证
auth_basic "default site";
auth_basic_user_file /server/default/nginx_auth/public;
}
server
{
...
# 整个站点启用身份验证
location /
{
...
auth_basic "qydocs 站点";
auth_basic_user_file /server/default/nginx_auth/qydocs;
...
}
# /other/ 目录下禁用身份验证
location ^~ /other/
{
auth_basic false;
}
...
}
server
{
...
# 指定目录下启用身份验证
location ~ ^/(?:css|html|javascript)/
{
...
auth_basic "wangdocs 站点";
auth_basic_user_file /server/default/nginx_auth/wangdocs;
...
}
...
}
4. 相关指令说明
common | info |
---|---|
echo -n | 不换行输出 |
>> | 追加输出重定向 |
> | 覆盖输出重定向 |
权限
chown nginx:nginx -R /server/{nginx,sites}
find /server/{nginx,sites} -type f -exec chmod 640 {} \;
find /server/{nginx,sites} -type d -exec chmod 750 {} \;
# conf和sbin目录下的内容权限 nginx 640
# 其他的*_temp不是很重要
# 可执行文件需要执行权限
chmod 750 -R /server/nginx/sbin
chown nginx:nginx -R /server/logs/nginx
chmod 750 /server/logs/nginx
# -- 因为日志文件权限是 nginx 644
# 每次对 sbin 修改权限后,都需要重新启用CAP_NET_BIND_SERVICE能力
setcap cap_net_bind_service=+eip /server/nginx/sbin/nginx
# 权限同部署环境
# 开发用户 emad 加入lnpp包用户组
usermod -a -G sqlite,redis,postgres,mysql,php-fpm,nginx emad