前几天讲了nginx的升级版本OpenResty和Tengine,说实话用nginx的人还是更多,今天就来唠唠它。现在很多人都习惯用yum或者apt直接装Nginx,但是编译安装真的有它的好处,比如可以自定义模块、优化性能参数什么的。
可能有人会问,包管理器安装不是更简单吗?确实简单,但是编译安装有几个明显的优势。
第一个就是灵活性,你可以选择需要的模块,不需要的就不编译进去,这样可以减少内存占用。我之前遇到过一个项目,对性能要求特别高,通过编译安装去掉了一些不必要的模块,内存使用量直接降了20%。
第二个是版本控制,有时候你需要特定版本的Nginx,或者需要打一些补丁,编译安装就很方便了。
第三个是学习价值,通过编译安装你能更好地理解Nginx的结构和依赖关系。
在开始之前,我们需要准备一些基础环境。我这里用的是Rocky Linux release 8.10,其他发行版的话命令可能稍有不同,但思路是一样的。
首先更新一下系统:
yum update -y
然后安装编译工具和依赖包:
yum groupinstall "Development Tools" -y
yum install -y pcre-devel zlib-devel openssl-devel wget
这几个包都很重要,pcre是用来处理正则表达式的,zlib用于gzip压缩,openssl用于SSL支持。如果你不装这些,编译的时候会各种报错,我当年就在这里卡了好久。
创建一个专门的用户来运行Nginx:
useradd -r -s /sbin/nologin nginx
这里用-r参数创建系统用户,-s指定shell为nologin,这样更安全一些。
接下来我们下载Nginx源码。我建议去官网下载最新的稳定版本,不要下载mainline版本,除非你有特殊需求。
cd /usr/local/src
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0
现在开始配置编译参数,这一步很关键,决定了你的Nginx有哪些功能:
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib64/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_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_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-http_slice_module \
--with-file-aio \
--with-http_v2_module
image-20250909204424049
这个配置看起来很长,但每个参数都有它的作用。比如--with-http_ssl_module是SSL支持,--with-http_v2_module是HTTP/2支持,--with-stream是四层负载均衡支持。
如果configure过程中出现错误,通常是因为缺少依赖包。比如如果你要启用http_xslt_module,就需要安装libxslt-devel包。
配置完成后开始编译:
make && make install
image-20250909204748286
编译时间取决于你的机器性能,一般几分钟到十几分钟不等。我记得第一次编译的时候还挺紧张的,生怕出错。
编译完成后,我们需要创建一些Nginx运行需要的目录:
mkdir -p /var/cache/nginx/client_temp
mkdir -p /var/cache/nginx/proxy_temp
mkdir -p /var/cache/nginx/fastcgi_temp
mkdir -p /var/cache/nginx/uwsgi_temp
mkdir -p /var/cache/nginx/scgi_temp
设置正确的权限:
chown -R nginx:nginx /var/cache/nginx
chown -R nginx:nginx /var/log/nginx
为了方便管理Nginx服务,我们创建一个systemd服务文件:
vim /etc/systemd/system/nginx.service
内容如下:
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillMode=process
KillSignal=SIGQUIT
TimeoutStopSec=5
PrivateTmp=true
[Install]
WantedBy=multi-user.target
image-20250909204840291
然后重载systemd配置:
systemctl daemon-reload
systemctl enable nginx
现在我们来看看Nginx的主配置文件。默认的配置文件在/etc/nginx/nginx.conf,我们先备份一下原文件:
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
然后编辑配置文件:
vim /etc/nginx/nginx.conf
我给出一个比较实用的基础配置:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
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;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/atom+xml
image/svg+xml;
include /etc/nginx/conf.d/*.conf;
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /usr/share/nginx/html;
location / {
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
}
这个配置包含了一些常用的优化参数。worker_processes设置为auto会自动根据CPU核心数设置工作进程数。gzip配置可以有效减少传输数据量。
创建网站根目录:
mkdir -p /usr/share/nginx/html
创建一个简单的测试页面:
cat > /usr/share/nginx/html/index.html << EOF
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you can see this page, the nginx web server is successfully installed and working.</p>
</body>
</html>
EOF
设置正确的权限:
chown -R nginx:nginx /usr/share/nginx/html
现在我们可以启动Nginx了:
systemctl start nginx
systemctl status nginx
image-20250909205049117
如果一切正常,你应该能看到nginx服务正在运行。
测试配置文件语法:
nginx -t
这个命令很有用,每次修改配置后都应该先测试一下语法是否正确。
打开浏览器访问服务器IP地址,应该能看到我们刚才创建的测试页面。
image-20250909205145463
在实际使用中,我们通常需要配置多个网站,这就需要用到虚拟主机功能。
首先创建配置目录:
mkdir -p /etc/nginx/conf.d
创建一个虚拟主机配置文件:
vim /etc/nginx/conf.d/example.com.conf
内容如下:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm index.php;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
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;
}
location ~ /\.ht {
deny all;
}
}
这个配置包含了PHP支持和一些安全设置。
现在HTTPS已经是标配了,我们来配置SSL证书。这里以Let's Encrypt免费证书为例:
首先安装certbot:
yum install -y epel-release
yum install -y certbot
申请证书:
certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com
修改虚拟主机配置,添加HTTPS支持:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm index.php;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
try_files $uri $uri/ =404;
}
}
Nginx的负载均衡功能也很强大,配置起来也不复杂:
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 weight=1 backup;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend;
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_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
}
这个配置实现了基于权重的负载均衡,还设置了一个备用服务器。
为了更好的性能,我们可以调整一些参数。在http块中添加:
client_max_body_size 100m;
client_body_buffer_size 128k;
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;
启用状态监控:
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
这样你就可以通过访问/nginx_status来查看Nginx的运行状态了。
Nginx的日志会越来越大,我们需要配置日志轮转。创建logrotate配置:
vim /etc/logrotate.d/nginx
内容:
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 644 nginx nginx
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
server {
listen 80;
server_name example.com;
location / {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# 其他配置...
root /var/www/html;
index index.html;
}
}
要创建密码文件,可以使用以下命令:
# 安装htpasswd工具(如果没有)
# Debian/Ubuntu
sudo apt-get install apache2-utils
# CentOS/RHEL
sudo yum install httpd-tools
# 创建密码文件(首次创建用户)
sudo htpasswd -c /etc/nginx/.htpasswd username
# 添加更多用户(不使用-c参数)
sudo htpasswd /etc/nginx/.htpasswd another_user
完成后重新加载Nginx配置:
sudo nginx -t && sudo nginx -s reload
# 在http块外部添加stream块
stream {
# 定义上游服务器组
upstream backend_tcp {
server backend1.example.com:3306 weight=5;
server backend2.example.com:3306 backup;
}
# TCP代理配置
server {
listen 3306; # 监听的本地端口
proxy_pass backend_tcp; # 转发到上游服务器组
proxy_timeout 3s; # 超时设置
proxy_connect_timeout 1s;
}
# UDP代理配置示例
server {
listen 53 udp; # UDP监听端口
proxy_pass dns_servers; # 转发到DNS服务器组
proxy_timeout 20s;
}
upstream dns_servers {
server 8.8.8.8:53;
server 8.8.4.4:53;
}
}
这个配置示例包含了:
注意:四层代理需要在Nginx编译时包含--with-stream
模块,如果使用的是预编译包,确保安装了nginx-extras
或包含stream模块的相应包。
在使用过程中可能会遇到一些问题,我总结几个常见的:
我记得有一次配置反向代理,总是502错误,折腾了半天才发现是SELinux的问题,执行了setsebool -P httpd_can_network_connect 1就解决了。
安全方面也需要注意几点:
还可以添加一些安全头:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
通过编译安装Nginx确实比包管理器安装要复杂一些,但是带来的灵活性和可控性是值得的。从下载源码到配置虚拟主机、SSL证书、负载均衡,每一步都需要仔细操作。
我建议大家在学习的时候多动手实践,遇到问题不要怕,查日志、看文档、搜索解决方案,这样才能真正掌握Nginx的使用。
现在的Web架构越来越复杂,Nginx作为入口网关的作用也越来越重要。掌握好Nginx的编译安装和配置,对于运维工作来说是很有价值的技能。
希望这篇文章能帮到正在学习Nginx的朋友们。如果你觉得有用的话,记得点赞转发,让更多的人看到。有问题也欢迎在评论区讨论,我会尽量回复大家的。
如果这篇文章对你有帮助,别忘了点赞转发支持一下!想了解更多运维实战经验和技术干货,记得关注微信公众号@运维躬行录,领取学习大礼包!!!我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习,共同进步!
公众号:运维躬行录
个人博客:躬行笔记