久违开个技术贴, 从 Nginx 手搓安装开始.
导语
如何安装 Nginx? 方法很多, 最简单的一键脚本安装, 或者宝塔面板之流一键安装, 等等, 高级一点就 apt install nginx. 今天我们不屑于当个小白, 我们来学学最基础的 Nginx 安装方式: 编译安装. 一键脚本, 抑或宝塔面板之流的一键安装, 大抵是替我们我们干了编译安装的各个过程的活罢了. 知其然仍需知其所以然!
虽然是小白参阅系列, 但是仍然要求有基本的 Linux 命令行基础, 你得知道以下命令: rm, mv, cp, wget, 等等. 想知道它们怎么用的吗? 尝试在命令行输入 命令 --help, 如 rm --help, Debian 会告诉你的.
本教程仍然基于并验证于 Debian 12, 故 Debian 系, 含 Ubuntu, 逐步操作大概率没问题. 什么? 还在用 CentOS? 那没救了, 自求多福吧()
编译安装 Nginx
- 更新系统
永远记住, 凡是要用 apt 安装点什么东西, 先更新一下.
apt update -y && apt upgrade -y && apt autoremove -y
- 安装编译依赖
apt install -y build-essential cmake libpcre3 libpcre3-dev libpcre2-dev zlib1g-dev openssl libssl-dev libxml2-dev libxslt1-dev libgd-dev libgeoip-dev libgoogle-perftools-dev libperl-dev perl-base perl
所谓依赖, 就是编译过程中需要的东西.
- 前置准备
# 我习惯建立专门用于编译东西的文件夹, 当然, 你想放哪都可以
# 此处示例为 /home/compile, nginx 用的则在 /home/compile/nginx
mkdir /home/compile
mkdir /home/compile/nginx
# 可以理解为这么干, 后续你敲命令 $COMPILE_PATH 就等同于 /home/compile/nginx
# 只是为了方便~
# 属于 sh 脚本的内容, 按下不表
export COMPILE_PATH="/home/compile/nginx"
cd $COMPILE_PATH
- 下载源代码
export NGINX_VERSION="1.25.3"
# 从 Nginx 官网下载官方压缩打包好的源代码
# 不要告诉我 command not found, 总不能系统 wget 都没有吧, 没有就装一下: apt install wget
wget https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
# 解压压缩包, 我们会得到一个名为 nginx-1.25.3 的文件夹(当然, 版本号不一样文件夹名字也不一样咯)
# 课后习题: -zxvf 是什么意思?
tar -zxvf nginx-$NGINX_VERSION.tar.gz
# 解压完就可以删掉压缩包了
rm nginx-$NGINX_VERSION.tar.gz
# 为了方便后续敲命令, 我们重命名一下
mv nginx-$NGINX_VERSION nginx_src
# 下载 Brotli 压缩的源代码, 此处使用 git 拉取源代码仓库的内容
# Git 是什么, 自行搜索哦
# 不要告诉我 command not found, 我不会告诉你输入 apt install git 就能装上的
# 此步可能执行比较久, 耐心等待~
git clone https://github.com/google/ngx_brotli && cd ngx_brotli && git submodule update --init
# 刚才我们 cd, 也就是进入了 ngx_brotli 文件夹, 现在返回上一层文件夹~
cd -
P.S. 截至写下此贴, Nginx 最新版本为 1.25.3. 请前往 https://nginx.org/en/download.html 查看最新版本, 然后照葫芦画瓢替换一下命令里面的版本号.

- configure
# 进入 Nginx 的源代码文件夹
cd nginx_src
# 配置编译参数, 执行时耐心等待
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/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-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-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 \
--add-module=$COMPILE_PATH/ngx_brotli \
--with-compat \
--with-cc-opt='-g0 -O3 -fstack-reuse=all -fdwarf2-cfi-asm -fplt -fno-trapv -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-check -fno-stack-clash-protection -fno-stack-protector -fcf-protection=none -fno-split-stack -fno-sanitize=all -fno-instrument-functions'
这些编译参数啥意思呢? 说白了就是指定配置文件存哪, 程序本体存哪, 要什么模块等等等等. 这里给出相对标准的参数, 即配置文件相关保存在 /etc/nginx, 附加模块在 /usr/lib/nginx/modules, 程序本体在 /usr/sbin/nginx, 日志在 /var/log/nginx, 各种缓存在 /var/cache/nginx, 添加了最常用的一些模块.
我们也能看到添加了刚刚下载的 ngx_brotli 这个 module(模块)哦.
至于模块是什么, 自己搜啦.
- 编译!
make
简简单单输入个 make, 等它编译完就可以啦~
机器性能差的可能得挺久. 内存小于 512M 的注意设置虚拟内存, 否则 OOM(Out of memory. 内存用完了), 系统就崩啦.
如果机器有多个 CPU 核心, make -j{CPU 核心数} 多线程编译会更快, 如: 你的 VPS 是 16 核的, 就 make -j16.
- 安装!
make install
执行完毕后, Nginx 就按照 configure 的内容安装到指定位置啦!
注意: 如果目标目录有东西, 会直接替换掉, 所以如果是升级, 记得提前备份一下原来的配置, 推荐:
cd /opt
zip nginx.zip /etc/nginx -r
存在 /etc/nginx 的配置文件等东西就给打包好放到 /opt 目录下面的 nginx.zip 压缩包里面了. 什么? command not found? apt install zip unzip 啦!!!
安装后, mv /opt/nginx.zip /etc && cd /etc && unzip nginx.zip 就还原回去啦.
原则上, /etc/nginx 下就是存各种配置文件之类的东西, 包括 SSL 证书等我也推荐放里面.
- 运行!
装好了, 就得运行啦! 全新系统还得进行下面的操作:
- 配置 systemd 持久化
cat < /etc/systemd/system/nginx.service
[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
Restart=always
RestartSec=15
StartLimitInterval=0
User=root
ExecStartPre=/bin/rm -rf /dev/shm/nginx
ExecStartPre=/bin/mkdir /dev/shm/nginx
ExecStartPre=/bin/chmod 711 /dev/shm/nginx
ExecStartPre=/bin/mkdir /dev/shm/nginx/tcmalloc
ExecStartPre=/bin/chmod 0777 /dev/shm/nginx/tcmalloc
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/usr/sbin/nginx -s stop
ExecStopPost=/bin/rm -rf /dev/shm/nginx
PrivateTmp=true
[Install]
WantedBy=multi-user.target
TEXT
- 配置文件调优
默认的 Nginx 配置文件不够好, 给出优化版本.
需要注意: 如 http2 on 是新版本 nginx 才有的语法, 旧版本不能那么写.
当然如果你是看了本教程全新安装那肯定没事.
HTTP3(QUIC) 支持也是 1.25.2 才有的.
# 备份一下原来的
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.b
cat < /etc/nginx/nginx.conf
user nginx nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_priority -20;
worker_rlimit_nofile 51200;
events
{
use epoll;
worker_connections 10240;
multi_accept on;
}
http
{
include mime.types;
# 用了 CDN 的, 去掉下面两行的注释
# set_real_ip_from 0.0.0.0/0;
# real_ip_header X-Forwarded-For;
default_type application/octet-stream;
charset utf-8;
# 设定默认启用 HTTP2
http2 on;
# 设定日志格式
log_format details '[$time_local][$status]|[Client] "$remote_addr" |[Host] "$host" |[Refer] "$http_referer" |[UA] "$http_user_agent" |[REQ] "$request" |[CONNECT] "$connection_requests" |[TIME] "$request_time" |[LENGTH] "$bytes_sent" |[UPSTREAM] "$upstream_addr" |[U_HEAD_TIME] "$upstream_header_time" |[U_CON_TIME] "$upstream_connect_time" |[U_RSP_TIME] "$upstream_response_time" |[U_STATUS] "$upstream_status" |[U_LENGTH] "$upstream_response_length"';
server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50m;
# Perf
access_log off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
reset_timedout_connection on;
client_body_timeout 10;
send_timeout 2;
keepalive_timeout 60;
# SSL
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH AESGCM:EDH AESGCM:AES256 EECDH:AES256 EDH';
ssl_ecdh_curve X25519:secp384r1;
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 24h;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 223.5.5.5 223.6.6.6 valid=60s;
resolver_timeout 5s;
ssl_early_data on;
ssl_buffer_size 8k;
##
# Connection header for WebSocket reverse proxy
##
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# fastcgi
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
# 压缩配置, 保持默认即可
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types
# text/html
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss xml
application/atom xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg xml;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
brotli on;
brotli_comp_level 6;
brotli_types
# text/html
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss xml
application/atom xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg xml;
# Others
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server_tokens off;
## QUIC / HTTP3
http3 on;
http3_hq on;
quic_retry on;
add_header Alt-Svc 'h3=":443"; ma=86400';
# Default server
# 此处配置了默认的 Server 块, 妈妈再也不用担心 SSL 证书泄露源站啦!
server
{
listen 80 default_server;
listen 443 ssl default_server;
listen 443 quic reuseport;
server_name _;
ssl_reject_handshake on;
location /connection-test {
default_type application/json;
return 200 '{"code":0, "message":""}';
}
location / {
return 444;
}
access_log /www/logs/nxdomain.com.log details;
}
# Include other conf
include /etc/nginx/conf.d/*.conf;
}
TEXT
- 扫尾
这些文件夹的名字和路径还熟悉吗? 就是前面 configure 的时候设置的
# 创建缓存目录
mkdir /var/cache/nginx
# 创建 Nginx 配置文件目录. 你的网站的配置文件就得存这里
mkdir /etc/nginx/conf.d
# 创建证书目录, 记得把证书存这里别乱存
mkdir /etc/nginx/certs
# 网站文件目录
mkdir /www
# 网站日志目录
mkdir /www/logs
chmod -R 777 /www
# 创建专门的用户运行 nginx, 更安全!
useradd -M -s /sbin/nologin nginx
- 运行!!!
重载 systemd, 立即启用并运行 Nginx!
systemctl daemon-reload && systemctl enable --now nginx
如果顺利, 执行 systemctl status nginx, 你就能看到 Active: active (running) 啦!

结语
恭喜, Nginx 安装完毕, 相当简单! 一键脚本只是帮你输命令而已!
既然都手搓安装 Nginx 了, 配置文件应该也会写了吧? 给份简单示例:
server
{
# 监听的 HTTP 端口, 默认 80/tcp
listen 80;
# 监听的 HTTPS 端口, 默认 443/tcp
listen 443 ssl;
# 监听的 HTTP3(QUIC) 端口, 默认 443/udp
listen 443 quic;
# 网站的 Host, 可以设置多个
server_name example.com www.example.com;
# SSL 证书存在哪
ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
# SSL 证书私钥存在哪
ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;
# 主页, 也就是访问网站默认加载的文件
index index.html;
# 网页文件存哪, 习惯上我们把 example.com 网站的内容存 /www/example.com
root /www/example.com;
# Location 块, 表示访问到匹配的 Path 就会加载对应内容
# 这里的示例是反向代理了你后端的 Alist
# 课后作业: 自己查询含义!
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Range $http_range;
proxy_set_header If-Range $http_if_range;
proxy_redirect off;
proxy_pass http://127.0.0.1:5244;
# the max size of file to upload
client_max_body_size 20000m;
}
# 访问日志, 习惯上我们把 example.com 网站的日志存到 /www/logs/example.com.log
access_log /www/logs/example.com.log details;
}
切记: 多思考多动手, 遇到问题善于搜索! 当然, 在评论区问我也行, 注意提问的方法哦~
欢迎评论区批评指正! 
Last Edit: 2023/11/14 04:19, Ver 1.0.1
附录
熟练后遇到新机器快速部署, 复制粘贴下面的内容即可
apt update && apt upgrade -y && apt dist-upgrade -y&& apt full-upgrade -y && apt autoremove -y
apt install -y build-essential cmake libpcre3 libpcre3-dev libpcre2-dev zlib1g-dev openssl libssl-dev libxml2-dev libxslt1-dev libgd-dev libgeoip-dev libgoogle-perftools-dev libperl-dev perl-base perl
mkdir /home/compile
mkdir /home/compile/nginx
export COMPILE_PATH="/home/compile/nginx"
cd $COMPILE_PATH
export NGINX_VERSION="1.25.3"
wget https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz
tar -zxvf nginx-$NGINX_VERSION.tar.gz
rm nginx-$NGINX_VERSION.tar.gz
mv nginx-$NGINX_VERSION nginx_src
git clone https://github.com/google/ngx_brotli && cd ngx_brotli && git submodule update --init && cd -
cd nginx_src
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/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-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-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 \
--add-module=$COMPILE_PATH/ngx_brotli \
--with-compat \
--with-cc-opt='-g0 -O3 -fstack-reuse=all -fdwarf2-cfi-asm -fplt -fno-trapv -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-stack-check -fno-stack-clash-protection -fno-stack-protector -fcf-protection=none -fno-split-stack -fno-sanitize=all -fno-instrument-functions'
make
make install
cat < /etc/systemd/system/nginx.service
[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
Restart=always
RestartSec=15
StartLimitInterval=0
User=root
ExecStartPre=/bin/rm -rf /dev/shm/nginx
ExecStartPre=/bin/mkdir /dev/shm/nginx
ExecStartPre=/bin/chmod 711 /dev/shm/nginx
ExecStartPre=/bin/mkdir /dev/shm/nginx/tcmalloc
ExecStartPre=/bin/chmod 0777 /dev/shm/nginx/tcmalloc
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/usr/sbin/nginx -s stop
ExecStopPost=/bin/rm -rf /dev/shm/nginx
PrivateTmp=true
[Install]
WantedBy=multi-user.target
TEXT
mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.b
cat < /etc/nginx/nginx.conf
user nginx nginx;
worker_processes auto;
worker_cpu_affinity auto;
worker_priority -20;
worker_rlimit_nofile 51200;
events
{
use epoll;
worker_connections 10240;
multi_accept on;
}
http
{
include mime.types;
# set_real_ip_from 0.0.0.0/0;
# real_ip_header CF-Connecting-IP;
default_type application/octet-stream;
charset utf-8;
http2 on;
log_format details '[$time_local][$status]|[Client] "$remote_addr" |[Host] "$host" |[Refer] "$http_referer" |[UA] "$http_user_agent" |[REQ] "$request" |[CONNECT] "$connection_requests" |[TIME] "$request_time" |[LENGTH] "$bytes_sent" |[UPSTREAM] "$upstream_addr" |[U_HEAD_TIME] "$upstream_header_time" |[U_CON_TIME] "$upstream_connect_time" |[U_RSP_TIME] "$upstream_response_time" |[U_STATUS] "$upstream_status" |[U_LENGTH] "$upstream_response_length"';
server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50m;
# Perf
access_log off;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
reset_timedout_connection on;
client_body_timeout 10;
send_timeout 2;
keepalive_timeout 60;
# SSL
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers 'EECDH AESGCM:EDH AESGCM:AES256 EECDH:AES256 EDH';
ssl_ecdh_curve X25519:secp384r1;
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 24h;
ssl_session_tickets on;
ssl_stapling on;
ssl_stapling_verify on;
resolver 223.5.5.5 223.6.6.6 valid=60s;
resolver_timeout 5s;
ssl_early_data on;
ssl_buffer_size 8k;
##
# Connection header for WebSocket reverse proxy
##
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
# fastcgi
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
# compress
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types
# text/html
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss xml
application/atom xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg xml;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
brotli on;
brotli_comp_level 6;
brotli_types
# text/html
text/css
text/javascript
text/xml
text/plain
text/x-component
application/javascript
application/x-javascript
application/json
application/xml
application/rss xml
application/atom xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg xml;
# Others
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server_tokens off;
## QUIC
http3 on;
http3_hq on;
quic_retry on;
add_header Alt-Svc 'h3=":443"; ma=86400';
# Default server
server
{
listen 80 default_server;
listen 443 ssl default_server;
listen 443 quic reuseport;
server_name _;
ssl_reject_handshake on;
location /connection-test {
default_type application/json;
return 200 '{"code":0, "message":""}';
}
location / {
return 444;
}
access_log /www/logs/nxdomain.com.log details;
}
# Include other conf
include /etc/nginx/conf.d/*.conf;
}
TEXT
mkdir /var/cache/nginx
mkdir /etc/nginx/conf.d
mkdir /etc/nginx/certs
mkdir /www
mkdir /www/logs
mkdir /www/default
chmod -R 777 /www
useradd -M -s /sbin/nologin nginx
systemctl daemon-reload && systemctl enable --now nginx

手搓caddy2有木有
@sbrvnc #1 caddy 啊, go 写的玩意, 吞吐大流量不行, 占内存还大, 好久没用了()
@Hantong #2 小鸡不需要吞吐大流量