proxy_set_header field value 格式
$host $http_host $proxy_host
$proxy_host : proxy_pass 后面跟着的host
如果客户端发过来的请求的header 有HOST 字段, $http_host 和 $host 都是原始的HOST 字段
如果header 没有HOST字段, 建议使用$host, 表示 请求中的server name
Just another site
proxy_set_header field value 格式
$host $http_host $proxy_host
$proxy_host : proxy_pass 后面跟着的host
如果客户端发过来的请求的header 有HOST 字段, $http_host 和 $host 都是原始的HOST 字段
如果header 没有HOST字段, 建议使用$host, 表示 请求中的server name
问题症状
Nginx的错误日志里:no resolver defined to resolve example.com
就是提示你没有定义resolver指令,Nginx就这样,它不理会系统的DNS(/etc/resolv.conf)配置, 如果你在配置文件中使用了域名或主机名,一定要配置resolver指令。
查看 pod 的 dns 配置
kubectl exec -it <pod name> -- cat /etc/resolv.conf
search default.svc.cluster.local svc.cluster.local cluster.local home
nameserver 10.96.0.10
options ndots:5
nginx 里 指定 nameserver IP
http {
server {
resolver 10.96.0.10 valid=10s;
resolver kube-dns.kube-system.svc.cluster.local valid=5s;
location /app {
proxy_pass http://webapp.default.svc.cluster.local;
# proxy_pass http://svc-xman-baseline-fe-insight.xman.svc.cluster.local:8080 加端口的
}
# note default and kube-system explicit namespaces)
# webapp is Kuberentes service name
pop名称 xcsc-xcommon-web-gateway-m7v8v-59fbbbbcd-bhk9q
负载均衡 域名 xcsc-xcommon-web-gateway.dev.test.za-tech.net 端口9006
服务地址 svc-xcsc-xcommon-web-gateway.dev:9006
location /app {
proxy_pass http://xcsc-xcommon-gateway.dev.test.za-tech.net;
}
## ship 中 基础镜像 nginx 版本下加入 resolver,才可以解析 域名
http{
resolver local=on valid=5s;
}
如果ship 没有域名解析,用svc 地址
http://xcsc-xcommon-gateway.dev.svc.cluster.local:8080
/xman-api 域名二级路径
/xmancloud 主应用路径
/xmancloud/playboxmicro 子应用路径
/xmancloud/commonmicro 子应用路径
/tptplaybox 活动路径
#主应用
location /xmancloud {
try_files $uri $uri/ /xmancloud/index.html;
if ($request_filename ~* .*\.(?:htm|html)$) {
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
add_header X-Frame-Options ALLOWALL;
}
alias /mnt/nasdata/nginx/html/static/xman-cloud/;
}
# 子应用
location /xmancloud/commonmicro/{
add_header Access-Control-Allow-Origin '*';
add_header Access-Control-Allow-Credentials 'true';
add_header Access-Control-Allow-Methods '*';
add_header Access-Control-Allow-Headers '*';
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Pragma,sec-ch-ua,sec-ch-ua-mobile,Authorization,Accept';
return 200;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Pragma,sec-ch-ua,sec-ch-ua-mobile,Authorization,Accept';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Pragma,sec-ch-ua,sec-ch-ua-mobile,Authorization,Accept';
}
if ($request_filename ~* .*\.(?:htm|html)$) {
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
}
alias /mnt/nasdata/nginx/html/static/xman-common/;
index index.html index.htm;
#try_files $uri $uri/ /index.html;
}
注意
proxy_cache将从C上获取到的数据根据预设规则存放到B上(内存+磁盘)留着备用,A请求B时,B会把缓存的这些数据直接给A,而不需要再去向C去获取。
proxy_cache相关功能生效的前提是,需要设置proxy_buffering on;
默认为off,即关闭proxy_cache功能,zone为用于存放缓存的内存区域名称。
例:proxy_cache my_zone;
从nginx 0.7.66版本开始,proxy_cache机制开启后会检测被代理端的HTTP响应头中的”Cache-Control”、”Expire”头域。
如,Cache-Control为no-cache时,是不会缓存数据的。
该参数设定,什么情况下的请求不读取cache而是直接从后端的服务器上获取资源。
这里的string通常为nginx的一些变量。
例:proxy_cahce_bypass $cookie_nocache $arg_nocache$arg_comment;
意思是,如果$cookie_nocache $arg_nocache$arg_comment这些变量的值只要任何一个不为0或者不为空时,
则响应数据不从cache中获取,而是直接从后端的服务器上获取。
该参数和proxy_cache_bypass类似,用来设定什么情况下不缓存。
例:proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
表示,如果$cookie_nocache $arg_nocache $arg_comment的值只要有一项不为0或者不为空时,不缓存数据。
定义cache key,如: proxy_cache_key $scheme$proxy_host$uri$is_args$args; (该值为默认值,一般不用设置)
path设置缓存数据存放的路径;
levels设置目录层级,如levels=1:2,表示有两级子目录,第一个目录名取md5值的倒数第一个值,第二个目录名取md5值的第2和3个值。keys_zone设置内存zone的名字和大小,如keys_zone=my_zone:10minactive设置缓存多长时间就失效,当硬盘上的缓存数据在该时间段内没有被访问过,就会失效了,该数据就会被删除,默认为10s。max_size设置硬盘中最多可以缓存多少数据,当到达该数值时,nginx会删除最少访问的数据。
http
{
...;
proxy_cache_path /data/nginx_cache/ levels=1:2 keys_zone=my_zone:10m inactive=300s max_size=5g;
...;
server
{
listen 80;
server_name www.aminglinux.com;
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 2 4k;
proxy_busy_buffers_size 4k;
proxy_temp_path /tmp/nginx_proxy_tmp 1 2;
proxy_max_temp_file_size 20M;
proxy_temp_file_write_size 8k;
location /some-api
{
proxy_cache my_zone;
proxy_pass http://192.168.10.110:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
}
nginx指定文件路径有两种方式root和alias,指令的使用方法和作用域:
[root]
语法:root path
默认值:root html
配置段:http、server、location、if
[alias]
语法:alias path
配置段:location
root与alias主要区别在于nginx如何解释location后面的uri,这会使两者分别以不同的方式将请求映射到服务器文件上。
root的处理结果是:root路径+location路径
alias的处理结果是:使用alias路径替换location路径
alias是一个目录别名的定义,root则是最上层目录的定义。
1. alias目录后面带不带/ 需要跟location保持一致就可以。
3. alias在使用正则匹配时,必须捕捉要匹配的内容并在指定的内容处使用。
4. alias只能位于location块中。(root可以不放在location中)
一、伪静态是个啥?
1、说起伪静态基本上搞web开发的人,多多少少都有了解与使用,有人会说什么时候会使用伪静态?使用原生的url地址不是蛮好的吗,确实是这样的,其实我蛮喜欢原生的url风格的,但是由于某些原因我不得不使用伪静态。
比如:
(1), url地址比较友好,看着爽,更有说服务力
(2), 如果是一个内容站,有利于seo优化
(3), 有效的防止sql注入,让别人不知道你真实的url地址
(4), 比如你在公司上班,你的领导,可能就会让你设置伪静态,工作需要。
2、那说了好处,有没有坏处呢? 坏处肯定是有的,与原生的url比较在性能上,不如原生的url,简单的说伪静态就是在服务器上又进行了一层url解析,消耗服务器资源。当然了这点消耗与优点相比,我们还是可以接受的。
3、那伪静态长什么样呢?
比如:
http://www.xxab.com/hello/world.html
http://www.xxx.com/content/23223.html
http://www.xxx.com/content/go/cb
以上这样的url地址,我们就可以叫伪静态url(都是进行过url处理)
4、那原生的url地址是什么样呢?
比如:
http://www.xxx.com/index.php?name=will&age=20
http://www.xxx.com/content/list.php?id=3
以上这样的url地址,就是原生url
二、nginx怎么设置伪静态呢?
如果你之前使用过apache的话很简单的,只要apache有rewrite模块就可以了,然后就可以自己编写rewrite规则了。
但是nginx如果你不明白原理就麻烦了,但只要明白原理就简单的,下面的案例都是我本地开发环境的配置,如果讲的不太合适的地方,请见谅。
1,nginx配置:
server {
listen 80;
server_name localhost;
access_log logs/localhost.access.log main;
#开启伪静态日志,方便调试
rewrite_log on;
#输出错误日志,错误级别设置为notice
error_log logs/error-test.log notice;
root html/test;
index index.php index.html;
location / {
try_files $uri $uri/ @aaaaab;
}
//注意使用@符号,不然不成功
location @aaaaab {
include D:/nginx/html/test/.htaccess;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
2, .htaccess清单
rewrite 语法格式:
rewrite [regex] [replacement] [flag];
url正则表达式 替换真实url 标记(last,break)
实例:
rewrite ^/article/index.html$ /index.php?process=article&a=index last;
//注意,这是一行,由于一行写不下,自动换行了
rewrite ^/article/list/([0-9]+)-([0-9]+)-([0-9]+).html$
/index.php?process=article&a=list&group_id=$1&category_id=$2&p=$3 last;
rewrite ^/article/detail/([0-9]+).html$ /detail.php?id=$1 last;
rewrite ^/group/([0-9]+).html$ /group.php?group_id=$1 last;
3,上面的案例虽然小,但是五脏俱全,我们开始一个一个的分析
try_files $uri $uri/ @aaaaab; 这句话是什么意思?
try_files从字面上理解就是尝试文件,再结合环境理解就是“尝试读取文件”,那他想读取什么文件呢,
答:读取静态文件
$uri 这个是nginx的一个变量,存放着用户访问的地址,
比如:http://www.xxx.com/index.html, 那么$uri就是 /index.html
$uri/ 代表访问的是一个目录,比如:http://www.xxx.com/hello/test/ ,那么$uri/就是 /hello/test/
完整的解释就是:try_files 去尝试到网站目录读取用户访问的文件,如果第一个变量存在,就直接返回;
不存在继续读取第二个变量,如果存在,直接返回;不存在直接跳转到第三个参数上。
比如用户访问这个网地址:http://www.xxx.com/test.html
try_files首先会判断他是文件,还是一个目录,结果发现他是文件,与第一个参数 $uri变量匹配。
然后去到网站目录下去查找test.html文件是否存在,如果存在直接读取返回。如果不存在直接跳转到第三个参数,而第三个参数是一个location,而这个location里面配置的就是rewrite规则。
说到这里大家就明白了,能看懂上面的配置了。
那有人会问了,还要try_files干什么呀,直接使用rewrite不就可以了吗?
答:不可以,因为rewrite这个指令把所有请求过来的url地址,都与htaccess文件中的正则地址进行一次匹配,这样的话,静态的url地址也进行了一次匹配,比如http://xxxx.com/aa.png,这个地址是不需要重写的,但是rewrite也进行了一次匹配,这就浪费服务器资源,影响执行效率。而我们真正需要匹配的,其实都是一些动态url地址,如果我说这么多,你还不明白的话,可以打印日志查看。
include D:/nginx/html/test/.htaccess; 这句就是去加载伪静态文件,把所有的规则写在这里面,注意这里要使用全路径,不然不成功。
RUN后面的指令,是创建完该镜像的容器后,再在容器上执行这些指令。
这里先不用手动build镜像,等会用docker-compose会自动build。
403 问题 docker
docker 寄主目录不支持软链
sudo apt-get install php-fpm
/etc/php/7.0/fpm/pool.d/www.conf 加上
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
然后重启 systemctl start php7.0-fpm.service
所以目前我需求就是获取nginx上使用的.pem和.key两个文件.
获取泛域名文档 看他的泛域名文档,以下是安装总结
1. 使用snap 安装certbot,关于snapd 包管理,可以到网上查看
ubuntu 已经自带snap, 使用时只要更新命令更新 sudo snap install core; sudo snap refresh core
2. 安装 certbot
安装前先删除 原来的安装的certbot , sudo apt remove certbot
执行安装命令 sudo snap install –classic certbot
把certbot命令添加到全局 sudo ln -s /snap/bin/certbot /usr/bin/certbot
3. 获取证书 ,泛域名 要使用下面的泛域名生成方法
sudo certbot certonly –nginx
4 在nginx 配置关联证书
ssl_certificate /etc/letsencrypt/live/xxx.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.com/privkey.pem;
5. 自动更新证书
它到期之前自动更新您的证书,除非你修改配置,更新证书的配置在 /etc/letsencrypt/renewal/下面
sudo certbot renew --dry-run # 测试自动更新是否可用 The command to renew certbot is installed in one of the following locations: /etc/crontab/ /etc/cron.*/* systemctl list-timers
Let’s Encrypt需要验证网站的所有权才能颁发证书, 官方称之为challenge(挑战).
在网站上的指定位置发布指定文件(HTTP-01)
当使用Webroot插件或手动插件时,请确保webroot目录存在并且您正确指定它。如果您为example.com设置了webroot目录,/var/www/example.com 那么放置的文件/var/www/example.com/.well-known/acme-challenge/testfile应该出现在您的网站上http://example.com/.well-known/acme-challenge/testfile(此处重定向到HTTPS是可以的,并且不应该阻止工作中的挑战)
sudo certbot certonly --standalone --email 'zbysir@qq.com' -d 'bysir.com'
standalone 就是独立插件, 它需要绑定80端口, 所以先关掉机器上的80端口吧, 或者换一台主机安装.
不出意外的话, 会死在Waiting for verification…,
可以看到他会请求 http://bysir.store/.well-known/acme-challenge/r9NH9hle6_7L9avkG-ID6A1BI4h4IgFVn6nx3VQZRpI以认证网站.
location ~ “^/\.well-known/acme-challenge/(.*)$” {
default_type text/plain;
return 200 “$1.IL3bE2eqHDs1k0Lmxm63CXpLvzmosMuUDIywEIBTPnG”;
}
certbot certonly --preferred-challenges dns --manual -d *.mydomain.com --server https://acme-v02.api.letsencrypt.org/directory
–preferred-challenges dns: 认证方式选择DNS, 泛域名支持DNS
–manual: 手动模式, 这里为了简单就使用手动认证了, 下面会说自动模式的使用.
-d *.mydomain.com: 就是要申请的泛域名了
–server https://acme-v02.api.letsencrypt.org/directory: 泛域名证书是新功能, 如果要使用就得加上这个参数
注意这一步 命令里会有提示,需要手动配置TXT记录, 在域名解析服务商添加一个泛解析就可以了, 设置好了再敲下回车.
sudo docker run -it --rm --name certbot \
-v "/etc/letsencrypt:/etc/letsencrypt" \
-v "/var/lib/letsencrypt:/var/lib/letsencrypt" \
certbot/certbot certonly -d *.mical.com --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
根据提示 在域名供应商里添加txt 记录
dig -t txt _acme-challenge.michnal.com
再次更新
docker run -it --rm --name certbot
-v "/etc/letsencrypt:/etc/letsencrypt"
-v "/var/lib/letsencrypt:/var/lib/letsencrypt"
certbot/certbot certonly --manual -d '*.michan.cn'
此法就不需要手动在 dns 服务器商那里 添加txt 记录了。
Zone:DNS:Edit
permissions for only the zones you need certificates for.# Cloudflare API token used by Certbot
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567
下面是命令 执行
这里接安装cerbot 的第二步
sudo snap set certbot trust-plugin-with-root=ok # 确认插件包含级别
sudo snap install certbot-dns-cloudflare # 安装插件, 不同的dns 服务商,不同的插件这是是cloudflare
sudo mkdir /home/.secrets/
sudo chmod 700 /home/.secrets/
sudo vim /home/.secrets/certbot_cloudflare.ini
# 輸入: dns_cloudflare_api_token = xxxxtokenxxx
# 在cloudflare上開token,權限 Zone:Zone:Read, Zone:DNS:Edit for all zones
sudo chmod 600 ~/.secrets/cloudflare.ini
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /home/wei/.secrets/certbot_cloudflare.ini \
-d xmetal.cc,*.xmetal.cc
set $group "/var/lib/tomcat8.5/webapps/m.happyeasygo.com";
if ( $remote_addr ~* ^(.*)\.(.*)\.(.*)\.*[1,3,5,7]$){
set $group "/var/lib/tomcat8.5/webapps/m.happyeasygo.com.v2";
}
if ($cookie_newindex){
#if ($http_cookie ~* "newindex=([^;]+)1"){
set $group "/var/lib/tomcat8.5/webapps/m.happyeasygo.com.v2";
}
location / {
#proxy_pass http://newindex;
root $group;
}
以 = 开头,表示精确匹配;如只匹配根目录结尾的请求,后面不能带任何字符串。
以^~ 开头,表示uri以某个常规字符串开头,不是正则匹配
以~ 开头,表示区分大小写的正则匹配;
以~* 开头,表示不区分大小写的正则匹配
以/ 开头,通用匹配, 如果没有其它匹配,任何请求都会匹配到
主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对一类路径做控制访问或反向代理,可以proxy_pass到其他机器。
if ( $remote_addr = 58.23.234.3){
rewrite ^/heg_api/queryPaymentChannelV2.do$
/payment_api/payment/queryPaymentChannel.do break;
}
[cc]rewrite regex replacement [flag];[/cc]
1rewrite功能就是,使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现url重写以及重定向。
2 rewrite只能放在server{}, location{}, if{} 中,并且只能对域名后边传递的参数外的字符串起作用
表面上看rewrite和location功能有点像,都能实现跳转,主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对一类路径做控制访问或反向代理,可以proxy_pass到其他机器。很多情况下rewrite也会写在location里,它们的执行顺序是:
执行server块的rewrite指令
执行location匹配
执行选定的location中的rewrite指令
如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。
因为301和302不能简单的只返回状态码,还必须有重定向的URL,这就是return指令无法返回301,302的原因了。
对于上面的flag,有几点需要强调一下:
也就是说,nginx虽然对请求url进行了重写,但是地址栏不会有任何明显的改变,仍然显示nginx重写前的地址;这与redirect和permanent不同。
二者都会终止当前ngx_http_rewrite_module的指令集的执行,但是 last 立即发起新一轮的 请求匹配 而 break 则不会。
if判断指令
语法为if(condition){…} ,对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
[cc]
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
} //如果UA包含”MSIE”,rewrite请求到/msid/目录下
if ($http_cookie ~* “id=([^;]+)(?:;|$)”) {
set $id $1;
} //如果cookie匹配正则,设置变量$id等于正则引用部分
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果query string中包含”post=140″,永久重定向到example.com
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
[/cc]
6)常用的变量
$args : #这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$document_root : 当前请求在root指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$limit_rate : 这个变量可以限制连接速率。
$request_method : 客户端请求的动作,通常为GET或POST。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
$request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri相同。