Nginx Tips

AI 摘要: 该文章介绍了编译安装Nginx的步骤和参数信息,并推荐了官方文档和案例。

1. 编译安装 Nginx

1.1. 安装步骤

  1. 下载源码包: http://nginx.org/en/download.html, wget http://nginx.org/download/nginx-1.24.0.tar.gz
  2. 解压下载包: tar -zxf ./nginx-1.24.0.tar.gz
  3. 安装配置: ./configure ...
  4. 编译安装: make && make install
  5. 做过软连: ln -s /usr/local/nginx/sbin/nginx /usr/sbin/
  6. 查看信息: nginx -t

1.2. 编译参数信息

 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
# 编译安装
./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_stub_status_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_auth_request_module \
--with-http_secure_link_module \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-http_slice_module \
--with-file-aio \
--with-http_v2_module

...
Configuration summary
  + using threads
  + using system PCRE2 library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

2. Nginx Systemd 配置

参考: https://www.nginx.com/resources/wiki/start/topics/examples/systemd/

2.1. 配置步骤

  1. 创建nginx.service: vim /lib/systemd/system/nginx.service,将下述 service 内容补充上
  2. 如果安装后之前有启动 nginx 服务,先通过 root 停止下: nginx -s stop,或者killall nginx
  3. 配置开机启动: systemctl enable nginx.service
  4. 启动服务: systemctl start nginx.service
  5. 查看服务: systemctl status nginx.service
  6. 查看日志: journalctl -xe -u nginx

2.2. nginx.service 内容

注意 PIDFile 是否和自己匹配,查看 ./configure 结尾信息

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

3. archstat.com hugo 静态站点部署过程

3.1. 部署流程

  1. Hugo 皮肤调试(Fork 到了自己的 Github)
  2. archstat.com - content 的内容规划,聚焦后端程序员学习与成长
  3. 项目 git 仓库准备(都存储到 Github、submodule 皮肤使用)
  4. Website 腾讯云服务器初始
    1. hugo 安装,依赖 Git、Go(1.18+)、Hugo Extend 版本(依赖 g++安装)
    2. 远程depoly_website.sh脚本编写(支持 build 目录清理,避免磁盘滚动过大)
    3. 本地配置archstat_publish.sh(支持远程 ssh 执行部署)
  5. 域名备案与解析,因为之前已经备案过archstat.com域名,(做了阿里云 → 迁移腾讯云备案工作)
  6. Nginx Web 配置(80 端口)
  7. Let’s Encrypt 的配置(自动签发域名配置、acme.sh、dns 验证、阿里云 Key+Secret)
  8. Nginx Web 升级到 H2(443、TLS、HTTP2.0 协议)

3.2. Let’s Encrypt 证书签发

参考: 通过 Acme.sh 自动签发阿里云证书

4. 自动化部署&发布

4.1. 本地 depoly_website.sh

1
ssh deployer@archstat.com -p 36000 'sh /home/deployer/sh/archstat_publish.sh'

4.2. 远程 archstat_publish.sh

拿之前写的脚本简单修改下,仍然很好用,哈哈

 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
#!/bin/bash
#
# hugo打包部署website 脚本
#
# Date: 2018-05-11
#

# 相关初始化
projectGitPath="/home/deployer/projects/archstat_docs"
projectGitBranch="main"

buildProjectPath="/data/www/archstat.com"
buildSavePath="${buildProjectPath}/build"
websitePublicLink="${buildProjectPath}/public"

deployer="deployer"

# 本次构建
buildPublicPath="$buildSavePath/$(date +%Y%m%d_%H%M%S)"

# 磁盘最多保存部署次数
limitNum=10

# 1. 检测发布用户
echo "[deploy start... 🚀🚀🚀 ]"
currentUser=$(whoami)
echo "[deploy user account checking... ]"
if [ "$currentUser" != $deployer ]; then
	echo "[Error]: current user[$currentUser] isn't match the deploy user: ${deployer}, reset an try again..."
	exit 1
fi

# 检测构建目录(包含日期)
echo "[deploy user account checking... ]"
if [ ! -d "$(dirname ${buildPublicPath})" ]; then
	mkdir -p "$(dirname ${buildPublicPath})" || echo "[Error]: buildPublicPath($(dirname $buildPublicPath)) not exist, please check again... "
	exit 1
fi

# 2. git仓库代码更新
echo "[✅ git deploy check ok. now begin update the git repository... 🚀🚀🚀 ]"
unset GIT_DIR && "unset GIT_DIR ok."

# 2.1) git 更新website项目
cd ${projectGitPath} || exit
git checkout $projectGitBranch
git reset --hard
git pull --ff-only origin $projectGitBranch || exit 1
echo "[✅ git pull website repository done. ]"

# 2.2) git 更新submodule内容
echo "[update the submodule repository... ]"
git submodule update || exit 1
echo "[✅ git submodule update done. ]"

# 3. 开始hugo构建
echo "[hugo build project... 🚀🚀🚀]"
hugo -v --minify --cleanDestinationDir || exit 1
echo "[✅ hugo build done. ]"

# 4. 将构建内容同步到指定目录
echo "[rsync website public files to build path ... 🚀🚀🚀]"
[ ! -d "$buildPublicPath" ] && mkdir -p "$buildPublicPath"
rsync -az --exclude=.git public/ $buildPublicPath || exit 1
echo "[✅ rsync public to $buildPublicPath ok. ]"

# 5. 重做public软链
echo "[unlink and relink the website public dir ... 🚀🚀🚀]"
if [ -L "$websitePublicLink" ]; then
	unlink $websitePublicLink && ln -s "$buildPublicPath" $websitePublicLink || exit 9
else
	ln -s $buildPublicPath $websitePublicLink || exit 9
fi
echo "[✅ relink website to public path ok. ]"

# 6. 部署完成,定期清理内容,最多保存10个
echo "[clean build path, keep only ($limitNum) build records ... 🚀🚀🚀]"
cleanPath=($(ls -dt $buildSavePath/* | sort))
curNum=${#cleanPath[@]}
if [[ $curNum -gt 2*$limitNum ]]; then
	for i in $(seq 1 $limitNum); do
		toDeletePath="${cleanPath[$i]}"

		# 需要做下检查,避免误删了其他系统文件
		if [[ $toDeletePath == *${buildSavePath}* ]]; then
			echo "try delete index dir:$i , path:${cleanPath[$i]}..."
			echo "rm -rf $toDeletePath || exit 1"
		fi
	done
	echo "[✅ clean website build path ok. ]"
else
	echo "[needn't clean records curNum=($curNum), limitNum=($limitNum)]"
fi

echo "[👏👏👏deploy success]...."

5. 其他

5.1. XFF

X-Forwarded-For(XFF)是用来识别通过 HTTP 代理或负载均衡方式连接到 Web 服务器的客户端最原始的 IP 地址的 HTTP 请求头字段。代理服务器是透明代理,用户甚至不知道自己正在使用代理上网。

XFF 的有效性依赖于代理服务器提供的连接原始 IP 地址的真实性,因此,XFF 的有效使用应该保证代理服务器是可信的,比如可以通过创建可信服务器白名单的方式。非连接发起的原始 IP 地址通过代理服务器可以做行为匿名服务处理,原始 IP 地址不可得,恶意访问的检测与预防的难度将大大增加。

模式:X-Forwarded-For: client1, proxy1, proxy2

逗号+空格 把多个 IP 地址区分开, 最左边(client1)是最原始客户端的 IP 地址, 代理服务器每成功收到一个请求,就把请求来源 IP 地址添加到右边。

伪造这一字段非常容易,应该谨慎使用 X-Forwarded-For 字段。

正常情况下 XFF 中最后一个 IP 地址是最后一个代理服务器的 IP 地址, 这通常是一个比较可靠的信息来源。

5.2. Nginx Proxy 设置

参见:http://nginx.org/en/docs/http/ngx_http_realip_module.html

  • --with-http_realip_module模块,默认未构建
  • real_ip_header field | X-Real-IP | X-Forwarded-For | proxy_protocol;
  • real_ip_recursive off; (禁用递归搜索,匹配其中一个可信地址的原始客户端地址将替换为 real_ip_header 指令定义的请求头字段中发送的最后一个地址 )
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// 参见
location /uri {
    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_connect_timeout   60s;  # nginx跟后端服务器连接超时时间(代理连接超时)
    proxy_send_timeout      90s;  # 后端服务器数据回传时间(代理发送超时)
    proxy_read_timeout      90s;  # 连接成功后,后端服务器响应时间(代理接收超时)
    proxy_buffer_size        4k;  # 设置代理服务器(nginx)保存用户头信息的缓冲区大小
    proxy_buffers         4 32k;  # proxy_buffers缓冲区,网页平均在32k以下的设置
    proxy_busy_buffers_size 64k;  # 高负荷下缓冲大小(proxy_buffers*2)
    proxy_temp_file_write_size 64k; # 设定缓存文件夹大小,大于这个值,将从upstream服务器传
    proxy_buffering         off;
    proxy_ignore_client_abort on;
    proxy_pass   http://xx.xx.xx.xx;
}

6. 推荐地址

  1. 详细的官方文档案例: https://www.nginx.com/resources/wiki/start/topics/examples/systemd/