DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • BFC 块级格式化上下文
  • Note
  • WebAssembly
  • public api
  • 位运算
  • bitwise operator
  • css实现隐藏效果
  • css snippets
  • 抖音点赞
  • js 相等判断
  • fetch ReadableStream
  • git
  • Github Actions 工作流
  • google search
  • RPC vs HTTP
  • gravatar
  • hhkb
  • Init project
  • input 文件上传
  • mac

    • Mac 使用技巧
    • alfred
    • mac shortcuts
    • shortcuts text edit
    • mac 修改host
  • 微前端
  • mock
  • nginx dump
  • nginx
  • NirCmd
  • npm
  • Operator Precedence
  • package.json
  • url query 解析
  • pnpm
  • JavaScript Precise countdown
  • react 模版
  • regexp
  • setup web development
  • telegram

    • telegram bot
  • timeFunction ease
  • 视频裁剪
  • vscode

    • vscode 高级指南
    • bracketPairs
    • jsconfig.json
    • vscode pipe into code
    • social project
    • vscode tasks
  • draggable resizable
  • windows 激活
  • 前端截图实现
  • 文本配音 富文本实现
  • 图片处理
  • 前端坐标
  • 定时任务
  • work efficient
  • 微信小程序动画实现方案
  • 排列组合
  • 数列
  • 语音驱动文字
  • 浏览器
  • 状态管理
  • 移动盒子
  • 移动端开发常用snippets
  • 设计模式
  • web performance

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;
    }

  }
Last Updated:
Contributors: rosendo
Prev
nginx dump
Next
NirCmd