和往常一样,系统为 debian,让我们开始吧。
1. Nginx 安装和配置
Nginx官网文档
https://nginx.org/en/docs/
Nginx(发音为"engine-x")是一个高性能的开源 Web 服务器,也可以用作反向代理服务器、负载均衡器和 HTTP 缓存。
1.1 安装
(1)安装Nginx
# debian
sudo apt update
sudo apt install nginx
# centos
sudo yum update
sudo yum install nginx
关于Nginx的一些命令和配置文件的位置介绍
在安装过程中可以看到 配置文件的位置在
/etc/nginx
下
当然不同的安装方式也可能不一样,可以通过whereis nginx
来搜索
1.2 配置文件
通过包管理工具安装的Nginx一般在 /etc/nginx
下
其中有一个 nginx.conf
文件,它就是Nginx的配置文件,但是为了方便管理,所以我一般不直接修改该文件,而是在 /etc/nginx/conf.d/
下新建文件。
在默认的 nginx.conf
中 http
模块下,有这样一条命令 include /etc/nginx/conf.d/*.conf;
它表示包含了 /etc/nginx/conf.d/
下所有文件,所以我们在/etc/nginx/conf.d/
直接添加新文件即可,如果没有该命令需要手动把文件的路径添加到 nginx.conf
中
关于 Nginx配置文件模块该如何书写,以下做一些简单介绍。
1.3 配置⽂件的结构
Nginx的配置⽂件是由⼀系列的指令组成的,每个指令都是由⼀个指令名和⼀个或者多个参数组成的。
指令和参数之间使⽤空格来分隔,指令以分号 ; 结尾,参数可以使⽤单引号或者双引号来包裹。
配置⽂件分为以下⼏个部分:
# 全局块
worker_processes 1;
events {
# events块
}
http {
# http块
server {
# server块
location / {
# location块
}
}
}
例如:
server {
listen 80;
server_name seektao.cc;
return 301 https://www.seektao.cc$request_uri;
}
server {
listen 80;
server_name www.seektao.cc;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name www.seektao.cc;
}
这个Nginx配置文件包含了三个server块,每个块定义了不同的虚拟主机配置。
- 第一个server块:
listen 80;
: 监听80端口,表示这个server块用于处理HTTP请求。server_name seektao.cc;
: 指定服务器的域名为seektao.cc
。return 301 https://www.seektao.cc$request_uri;
: 当有HTTP请求访问seektao.cc
时,返回301重定向到https://www.seektao.cc$request_uri
,即将HTTP请求重定向到HTTPS协议的www.seektao.cc
。
- 第二个server块:
listen 80;
: 同样监听80端口,处理HTTP请求。server_name www.seektao.cc;
: 指定服务器的域名为www.seektao.cc
。return 301 https://$host$request_uri;
: 当有HTTP请求访问www.seektao.cc
时,返回301重定向到https://$host$request_uri
,即将HTTP请求重定向到HTTPS协议的www.seektao.cc
。
- 第三个server块:
listen 443 ssl http2;
: 监听443端口,启用SSL和HTTP/2协议。server_name www.seektao.cc;
: 指定服务器的域名为www.seektao.cc
。
这个配置文件的作用是:
- 当有HTTP请求访问
seektao.cc
或www.seektao.cc
时,会将请求重定向到相应的HTTPS地址。 - 对于HTTPS请求,只有
www.seektao.cc
会被处理,而其他域名或路径则没有配置处理规则,可能会返回默认的Nginx页面或404错误。
这只是一个简单的配置示例,实际生产环境中还需要根据具体需求进行进一步配置,例如配置SSL证书、代理、缓存等功能。
1.3.1 全局块
全局块是配置⽂件的第⼀个块,也是配置⽂件的主体部分,主要⽤来设置⼀些影响Nginx服务器整体运⾏的配置指令,主要包括配置运⾏Nginx服务器的⽤户(组)、允许⽣成的workerprocess数、进程PID存放路径、⽇志存放路径和类型以及配置⽂件引⼊等。
# 指定运⾏Nginx服务器的⽤户,只能在全局块配置
# 将user指令注释掉,或者配置成nobody的话所有⽤户都可以运⾏
# user [user] [group]
# user nobody nobody;
user nginx;
# 指定⽣成的worker进程的数量,也可使⽤⾃动模式,只能在全局块配置
worker_processes 1;
# 错误⽇志存放路径和类型
error_log /var/log/nginx/error.log warn;
# 进程PID存放路径
pid /var/run/nginx.pid;
1.3.2 events块
events {
# 指定使⽤哪种⽹络IO模型,只能在events块中进⾏配置
# use epoll
# 每个worker process允许的最⼤连接数
worker_connections 1024;
}
1.3.3 http块
http块是配置⽂件的主要部分,包括http全局块和server块。
http {
# nginx 可以使用include指令引入其他配置文件
include /etc/nginx/mime.types;
# 默认类型,如果请求的URL没有包含文件类型,会使用默认类型
default_type application/octet-stream; # 默认类型
# 开启高效文件传输模式
sendfile on;
# 连接超时时间
keepalive_timeout 65;
# access_log 日志存放路径和类型
# 格式为:access_log <path> [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log /var/log/nginx/access.log main;
# 定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';
# 设置sendfile最大传输片段大小,默认为0,表示不限制
# sendfile_max_chunk 1m;
# 每个连接的请求次数
# keepalive_requests 100;
# keepalive超时时间
keepalive_timeout 65;
# 开启gzip压缩
# gzip on;
# 开启gzip压缩的最小文件大小
# gzip_min_length 1k;
# gzip压缩级别,1-9,级别越高压缩率越高,但是消耗CPU资源也越多
# gzip_comp_level 2;
# gzip压缩文件类型
# gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# upstream指令用于定义一组服务器,一般用来配置反向代理和负载均衡
upstream www.example.com {
# ip_hash指令用于设置负载均衡的方式,ip_hash表示使用客户端的IP进行hash,这样可以保证同一个客户端的请求每次都会分配到同一个服务器,解决了session共享的问题
ip_hash;
# weight 用于设置权重,权重越高被分配到的几率越大
server 192.168.50.11:80 weight=3;
server 192.168.50.12:80;
server 192.168.50.13:80;
}
server {
# 参考server块的配置
}
}
1.3.4 server块
server块是配置虚拟主机的,⼀个http块可以包含多个server块,每个server块就是⼀个虚拟主机。
server {
# 监听IP和端口
# listen的格式为:
# listen [ip]:port [default_server] [ssl] [http2] [spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number];
# listen指令非常灵活,可以指定多个IP和端口,也可以使用通配符
# 下面是几个实际的例子:
# listen 127.0.0.1:80; # 监听来自127.0.0.1的80端口的请求
# listen 80; # 监听来自所有IP的80端口的请求
# listen *:80; # 监听来自所有IP的80端口的请求,同上
# listen 127.0.0.1; # 监听来自来自127.0.0.1的80端口,默认端口为80
listen 80;
# server_name 用来指定虚拟主机的域名,可以使用精确匹配、通配符匹配和正则匹配等方式
# server_name example.org www.example.org; # 精确匹配
# server_name *.example.org; # 通配符匹配
# server_name ~^www\d+\.example\.net$; # 正则匹配
server_name localhost;
# location块用来配置请求的路由,一个server块可以包含多个location块,每个location块就是一个请求路由
# location块的格式是:
# location [=|~|~*|^~] /uri/ { ... }
# = 表示精确匹配,只有完全匹配上才能生效
# ~ 表示区分大小写的正则匹配
# ~* 表示不区分大小写的正则匹配
# ^~ 表示普通字符匹配,如果匹配成功,则不再匹配其他location
# /uri/ 表示请求的URI,可以是字符串,也可以是正则表达式
# { ... } 表示location块的配置内容
location / {
# root指令用于指定请求的根目录,可以是绝对路径,也可以是相对路径
root /usr/share/nginx/html; # 根目录
# index指令用于指定默认文件,如果请求的是目录,则会在目录下查找默认文件
index index.html index.htm; # 默认文件
}
# 下面是一些location的示例:
location = / { # 精确匹配请求
root /usr/share/nginx/html;
index index.html index.htm;
}
location ^~ /images/ { # 匹配以/images/开头的请求
root /usr/share/nginx/html;
}
location ~* \.(gif|jpg|jpeg)$ { # 匹配以gif、jpg或者jpeg结尾的请求
root /usr/share/nginx/html;
}
location !~ \.(gif|jpg|jpeg)$ { # 不匹配以gif、jpg或者jpeg结尾的请求
root /usr/share/nginx/html;
}
location !~* \.(gif|jpg|jpeg)$ { # 不匹配以gif、jpg或者jpeg结尾的请求
root /usr/share/nginx/html;
}
# error_page 用于指定错误页面,可以指定多个,按照优先级从高到低依次查找
error_page 500 502 503 504 /50x.html; # 错误页面
location = /50x.html {
root /usr/share/nginx/html;
}
}
1.4 Nginx常用命令
systemctl start nginx # 启动Nginx (默认已经启动)
systemctl stop nginx # 关闭Nginx
systemctl status nginx # 查看Nginx状态
sudo nginx -t # 检查Nginx配置文件语法是否正确
sudo nginx -s reload # 重新加载Nginx配置
sudo nginx # 启动Nginx
sudo nginx -c filename # 指定配置⽂件
nginx -V # 查看Nginx的版本和编译参数等信息
sudo nginx -s quit # 优雅停⽌Nginx
sudo nginx -s stop # 快速停⽌Nginx
sudo nginx -s reopen # 重新打开⽇志⽂件
到此位置,Nginx就结束啦,马上开始我们的SSL证书之旅吧。
2. Certbot 申请SSL证书
Certbot 是一个由 Electronic Frontier Foundation (EFF) 开发的免费、开源的工具,用于自动化在 Web 服务器上部署 SSL/TLS 证书。SSL/TLS 证书是用于加密网站与用户之间传输的数据,确保数据传输的安全性和隐私性。
Certbot 支持大多数常见的 Web 服务器,包括 Apache、Nginx、IIS 等。
2.1 安装 certbot
# debian
sudo apt update
# 添加软件源
sudo apt install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
# 安装certbot
sudo apt install certbot
# centos 没用,不太清楚,应该类似于debian
sudo yum update
此处省略添加软件源,请自己记得添加。。。
sudo yum install certbot
这里注意:一定要添加软件源,安装最新版本的 certbot,否则后面提示安装dns插件有问题
安装完成,查看版本 certbot --version
,目前是 2.9.0
2.2 申请域名证书
使用certbot 来申请 Let’s Encrypt免费CA的SSL证书
官网教程
https://eff-certbot.readthedocs.io/en/latest/using.html#getting-certificates-and-choosing-plugins
# 比如,实际我没用,我使用的是下面的dns插件来获取
certbot certonly --webroot -w /path/to/your/website -d yourdomain.com
使用Web根目录/path/to/your/website
中的文件验证您拥有yourdomain.com
的控制权,并为该域名获取SSL证书。
2.3 DNS获取SSL泛域名证书(推荐)
DNS获取证书的好处在于可以申请泛域名证书,也就是像 *.seektao.cc
也就是一次申请,到处使用,方便至极。
2.3.1 certbot-dns-dnspod
certbot-dns-dnspod 是dnspod的插件,默认的certbot是没有的,需要手动安装
Github地址
# pip
sudo pip install git+https://github.com/tengattack/certbot-dns-dnspod.git
# snap 本次没有采用
sudo snap install certbot-dns-dnspod
sudo snap set certbot trust-plugin-with-root=ok
sudo snap connect certbot:plugin certbot-dns-dnspod
安装完成之后新建一个 .ini文件,比如 /etc/certbot/dnspod.ini
sudo mkdir /etc/certbot
sudo touch /etc/certbot/dnspod.ini
编辑 dnspod.ini,填入下面的内容,点此跳转到dnspod api 申请页面,注意申请的是dnspod token
dns_dnspod_api_id = 12345
dns_dnspod_api_token = 1234567890abcdef1234567890abcdef
sudo chmod 600 /etc/certbot/dnspod.ini
申请,替换为自己的域名
sudo certbot certonly -a dns-dnspod \
--dns-dnspod-credentials /etc/certbot/dnspod.ini \
-d seektao.cc \
-d "*.seektao.cc"
接着就是:
输入邮箱,
是否同意注册acme(选Y),
是否同意发送邮件。。。看自己吧
接着等待,等待。。就完成了
通过日志可以看到证书文件保存在 `/etc/letsencrypt/live
# 其中
[cert name]/privkey.pem:证书的私钥。
[cert name]/fullchain.pem:在大多数服务器软件中使用的证书文件。
[cert name]/chain.pem:在Nginx >=1.3.7 中用于 OCSP stapling。
[cert name]/cert.pem:会破坏许多服务器配置,不应在未进一步阅读文档的情况下使用。
我们用到 privkey.pem,fullchain.pem即可。
此节关于 dnspod 申请ssl证书就是如此。
2.4 自动续期
自动续期添加一个定时任务即可
# 设置定时任务
sudo crontab -e
# 每月1号的午夜执行 certbot renew 命令来续订证书
0 0 1 * * /usr/local/bin/certbot renew
需要注意自己的certbot执行路径是否正确
which certbot
可以看到certbot执行路径
关于续期的更多文档可以观看
https://eff-certbot.readthedocs.io/en/latest/using.html#setting-up-automated-renewal
3. Nginx一键生成模板
3.1 需求
这个需求在于我使用Nginx作为反代服务器,每新增一个服务,就要手动去新增一个nginx文件,而且我主要使用的是二级域名加端口的模式,配合使用 泛域名证书来编写这个脚本就很方便了。
现在想要实现输入 脚本文件 域名 端口
就会在 /etc/nginx/conf.d/
下新增一个以域名开头的配置文件,例如:
$ sudo ./generate_nginx_simple_template.sh test1.seektao.cc 5980
Do you want to reload Nginx configuration? (y/n) y
Reloading Nginx configuration...
$ ll /etc/nginx/conf.d/test1.conf
-rw-r--r-- 1 root root 965 Mar 25 13:01 /etc/nginx/conf.d/test1.conf
模板的内容如下:
$ cat /etc/nginx/conf.d/test1.conf
server {
listen 80;
server_name test1.seektao.cc;
return 301 $scheme://test1.seektao.cc$request_uri;
}
server {
listen 443 ssl http2;
server_name test1.seektao.cc;
# SSL 证书配置
ssl_certificate /etc/letsencrypt/live/seektao.cc/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/seektao.cc/privkey.pem;
# 安全设置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 反向代理
location / {
proxy_pass http://127.0.0.1:5980/;
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;
}
# 日志配置
access_log /var/log/nginx/test1.seektao.cc.access.log;
error_log /var/log/nginx/test1.seektao.cc.error.log;
}
3.2 脚本的配置
使用这个脚本请先申请泛域名证书,或者你自己再修改配置文件的证书位置。
vim generate_nginx_simple_template.sh
#!/bin/bash
# 检查参数数量
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <domain> <application_port>"
exit 1
fi
DOMAIN=$1
APPLICATION_PORT=$2
PORT_HTTP=80
PORT_HTTPS=443
CERT_DOMAIN=$(echo "$DOMAIN" | awk -F. '{print $(NF-1)"."$NF}')
CONF_FILE_PREFIX=$(echo "$DOMAIN" | awk -F. '{print $1}')
CONF_FILE="/etc/nginx/conf.d/${CONF_FILE_PREFIX}.conf"
# 生成 Nginx 配置内容
cat <<EOF > $CONF_FILE
server {
listen $PORT_HTTP;
server_name $DOMAIN;
return 301 \$scheme://$DOMAIN\$request_uri;
}
server {
listen $PORT_HTTPS ssl http2;
server_name $DOMAIN;
# SSL 证书配置
ssl_certificate /etc/letsencrypt/live/$CERT_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$CERT_DOMAIN/privkey.pem;
# 安全设置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# 反向代理
location / {
proxy_pass http://127.0.0.1:$APPLICATION_PORT/;
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;
}
# 日志配置
access_log /var/log/nginx/$DOMAIN.access.log;
error_log /var/log/nginx/$DOMAIN.error.log;
}
EOF
# 检查临时文件是否成功创建
if [ ! -f "${CONF_FILE}" ]; then
echo "Error: Failed to create temporary configuration file."
exit 1
fi
# 提示用户是否需要修改配置文件
# read -p "Do you want to modify the configuration file before saving? (y/n) " choice
# 根据用户选择执行相应操作
# case "$choice" in
# y|Y )
# # 使用文本编辑器让用户修改配置文件
# echo "Editing configuration file..."
# vim "${CONF_FILE}" # 或者使用你喜欢的其他文本编辑器,如 nano
# ;;
# n|N )
# # 直接将临时文件移动到目标位置
# echo "Saving configuration file without modification..."
# mv "${CONF_FILE}" "${CONF_FILE}"
# ;;
# * )
# echo "Invalid choice. Exiting..."
# exit 1
# ;;
# esac
# 检查 SSL 证书路径是否存在,如果不存在,提示用户手动申请
if [ ! -e "/etc/letsencrypt/live/$CERT_DOMAIN/fullchain.pem" ]; then
echo "Warning: SSL certificate for $CERT_DOMAIN does not exist."
echo "Please use certbot or another tool to manually obtain a certificate for $CERT_DOMAIN."
fi
# 提示用户是否需要重新加载 Nginx 配置
read -p "Do you want to reload Nginx configuration? (y/n) " reload_choice
case "$reload_choice" in
y|Y )
# 重新加载 Nginx 配置
echo "Reloading Nginx configuration..."
sudo nginx -s reload
;;
n|N )
echo "Nginx configuration will not be reloaded."
;;
* )
echo "Invalid choice. Exiting..."
exit 1
;;
esac
至此完成~~
4. 后话
在编写这篇教程之前,我一直都是用的是 Nginx Proxy Manager (简称NPM)图形化管理界面,觉得Nginx配置看不懂,太复杂,对Nginx也不太懂。
教程的前一天,我想使用Nginx Proxy Manager为反代的服务添加 location片段,却会导致添加了location的服务挂掉,不论是图形化添加还是修改配置文件,我还以为是我的配置姿势不对,添加的location内容有错,后面找了很久的资料,却没能找到解决办法,最后还是在 NPM 的Github issues很多人出现了这个问题,而且没有一个合适的解决方案,NPM的bug。唉,一不做,二不休,不如直接用Nginx,还少去了NPM占据了一部分内存。
安装Nginx的过程还是很愉快的。但是对于ssl证书我又了解甚少了,对此又花费了很多精力去了解 certbot,结果apt安装的certbot没有dnspod插件??我一个大问号,又卸载了apt方式安装的certbot,去安装snap,通过snap安装certbot,我发现 snap也有问题??但是找到了snap上GitHub上的 dnspod插件,也支持snap,然后又卸载 certbot,snap,重新通过 apt 安装 certbot,然后下载dnspod,结果又在申请证书的时候出错了。原来我为了简便,dnspod.ini 用的是 NPM之前的配置。后来改了就好了。
现在只差反代了,上面的脚本也是为了我在 NPM已经反代的服务而写的,毕竟一个一个复制然后改端口也挺麻烦的。
全文完。
制作不易,如果对您有一丢丢帮助,您可以点赞收藏转发,一键三连,🤞🤞,谢谢您咧~~
如需转载,请注明出处。
创作时间:2024-03-25 13:40
创作者:muyiacc