nginx
apt update
apt install nginx
systemctl enable nginx
systemctl start nginx
nginx -t # check nginx config
nginx 配置文件
# vscode remote dev 打开 /etc/nginx 配置文件 OR
vim /etc/nginx/sites-available # nginx config
# /var/www/ 网站目录文件
https 证书配置
获取免费证书
通过 Let's Encrypt 获取免费证书
apt install certbot python3-certbot-nginx
# 生成证书
sudo certbot --nginx -d doc.example.com -d www.example.com
更新证书
手动更新 Certbot 会自动检查所有证书的到期日期,并自动更新到期时间在 30 天以内的证书
sudo certbot renew # 如果证书已经过期,Certbot将无法更新证书
cron 定时任务 👍👍👍
sudo crontab -e # 编辑cron
# 把以下添加到 cron
0 0 1 * * /usr/bin/certbot renew --quiet # 每个月的1日的零点执行Certbot的renew命令
# https://crontab.guru/#0_0_1_*_*
如果证书已经过期,Certbot 将无法更新证书。在这种情况下,你需要生成一个新的证书。可以使用以下命令生成新的证书:
sudo certbot --nginx -d example.com -d www.example.com
这将生成一个新的证书,并配置 nginx 以使用该证书。然后你需要重新启动 nginx,以便使用新的证书。
通配符证书
请替换 example.com 为你自己的域名。此命令将使用 DNS 验证来验证你对该域名的控制权,并生成一个通配符 SSL 证书,以便用于所有子域名(例如 www.example.com, blog.example.com, shop.example.com 等)。 请注意,由于证书颁发机构(CA)的策略,通配符 SSL 证书只能用于一级子域名,而不能使用在二级或更高级别的子域名上。
sudo certbot --server https://acme-v02.api.letsencrypt.org/directory -d '*.rosendo.fun' --manual --preferred-challenges dns-01 certonly
提高性能
修改配置文件 /etc/nginx/nginx.conf
- 增加 worker_processes 数量:可以增加 worker_processes 的数量来充分利用多核 CPU 的性能,提高响应速度。
- 增加 worker_connections 数量:可以增加 worker_connections 的数量来提高每个 worker 处理连接的能力。
- 开启 multi_accept:开启 multi_accept 可以在每个事件循环中一次性处理多个连接,提高响应速度。
- 增加 use epoll 或者 kqueue:对于高并发的情况下,使用 epoll 或者 kqueue 可以提高响应速度。
- 减少文件描述符限制:可以通过修改系统的文件描述符限制来提高 Nginx 的并发连接能力,例如在 Linux 系统中可以通过修改/etc/security/limits.conf 文件中的 nofile 参数来增加文件描述符限制。
events {
worker_connections 1024;
multi_accept on;
use epoll;
# worker_connections 768;
# multi_accept on;
}
代理配置
HTTP 反向代理
http 请求重定向到 https 请求 反向代理 a.b.com 到 localhost:27017
server {
server_name a.b.com; # managed by Certbot
location / {
proxy_pass http://localhost:27017;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 用于 WebSocket 的反向代理
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/a.b.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/a.b.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
listen 80 ;
listen [::]:80 ;
server_name a.b.com;
return 301 https://$host$request_uri;
}
nginx 部署多个 web
每个网站 build
的时候需要配置 baseURL
或base
vite;
yaml
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
server {
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name rosendo.fun; # managed by Certbot
location ^~ /doc {
alias /var/www/doc;
}
location ^~ /it-tools {
alias /var/www/it-tools/;
}
location ^~ /react-practice {
alias /var/www/react-practice/;
}
location /excalidraw {
proxy_pass http://127.0.0.1:5000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 用于 WebSocket 的反向代理
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /nodered {
proxy_pass http://127.0.0.1:1880/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 用于 WebSocket 的反向代理
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /hooks/ {
proxy_pass http://127.0.0.1:9000/hooks/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 用于 WebSocket 的反向代理
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/rosendo.fun/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/rosendo.fun/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = rosendo.fun) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name rosendo.fun;
return 404; # managed by Certbot
}
TCP
数据库连接反向代理
如果需要远程能访问到,则需要数据库绑定 0.0.0.0 地址,然后防火墙开放对应的端口号 或者 nginx tcp 转发
stream {
upstream mongodb {
server 127.0.0.1:27017;
}
server {
listen 8081;
proxy_pass mongodb;
proxy_bind $remote_addr;
proxy_protocol on;
}
}
开放防火墙
nginx -s reload # reload
ufw allow 8081/tcp # enable 8081
UDP
注意,只能有一个 stream 模块
代理 代理 3001 端口数据到 127.0.0.1:10108
server {
# 监听 3001 端口的 UDP 请求
listen 3001 udp;
# 将 UDP 请求代理到本地 1032 端口
proxy_pass 127.0.0.1:10108;
# 设置代理连接超时为3秒
proxy_connect_timeout 3s;
# 设置代理响应超时为3秒
proxy_timeout 3s;
}
Websocket
location /admin/ {
proxy_pass https://127.0.0.1:9443/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket 代理配置,不配置的话 websocket 代理不过去
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
nginx 模块
echo
实现返回字符串,可用于调试。
当没有配置 default_type
的时候。默认的是 Nginx 实际上会将响应的 Content-Type 设置为application/octet-stream
,这是一种通用的二进制文件类型, 浏览器会将响应解释为文件并尝试下载它。这通常会在浏览器中看到一个下载对话框或者下载的文件。
location /test {
default_type text/plain; ## 不配置 会提示下载
echo 'hello';
}
ngx_http_limit_req_module
nginx conf
yaml
http {
# ...
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;
# server, or location:
location ... {
limit_req zone=ip_limit burst=20 nodelay;
# ...
}
# ...
}
fail2ban conf
/etc/fail2ban/jail.local
[nginx-http-auth]
enabled = true
port = http,https
logpath = %(nginx_error_log)s
# To use 'nginx-limit-req' jail you should have `ngx_http_limit_req_module`
# and define `limit_req` and `limit_req_zone` as described in nginx documentation
# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
# or for example see in 'config/filter.d/nginx-limit-req.conf'
[nginx-limit-req]
enabled = true
port = http,https
logpath = %(nginx_error_log)s
[nginx-botsearch]
enabled = true
port = http,https
logpath = %(nginx_error_log)s
maxretry = 4
http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
nginx 变量控制
http
块内定义变量,其他 server
块中可以直接访问
nginx conf
http {
# global http variable
map $http_host $link {
default "https://github.com";
}
server {
# limit_req zone=lr_zone burst=10 nodelay;
listen 80 default_server;
server_name _;
listen [::]:80 default_server;
return 301 $link;
# return 502;
}
}
常见问题
启动报错
端口已经被占用导致
nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)
systemctl status nginx
lsof -i :443 # 查看 443
lsof -i :80 # 查看 80
kill -9 xx_pid
ps aux | grep nginx # 查看进程
kill -9 xxx_pid
同一域名下 配置多个静态网站
前端项目路径需做额外处理;vuepress 需要配置 base 修改为根路径地址;
alias
server {
# 域名+项目1名称
location ^~ /a1/ {
alias /xxx/xxx/xxx/;
}
# 域名+项目2名称
location ^~ /a2/ {
alias /xxx/xxx/xxx/;
}
}
proxy_pass
location ^~ /xxx/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:xxx/; # 结尾需加上 /
}
server {
listen 80;
listen [::]:80;
server_name test.name;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
# 精确匹配
location = /google {
rewrite ^ http://google.com;
}
# 前缀匹配
location ^~ /baidu {
rewrite ^ http://baidu.com;
}
# 正则匹配 区分大小写
location ~ /sogou {
rewrite ^ http://sogou.com/;
}
# 正则匹配 不 区分大小写
location ~* /SoGou {
rewrite ^ http://sogou.com/;
}
# 正常匹配 优先级低于前缀匹配 (可使用正则,不区分大小写)
location /biying {
rewrite ^ http://biying.com/;
}
# 全匹配
location / {
root /usr/share/nginx/html;
}
# 别名匹配
error_page 404 = @notfound;
location @notfound {
rewrite ^ http://taobao.com/;
}
location = /50x.html {
root /usr/share/nginx/html;
}
}