相关链接

本篇以Debian13操作系统作为讲解基础,按照行文顺序进行操作,可以基本了解Linux的一些基础操作。

SSH

这是一个很难绕开的问题,也往往是VPS的开端,我们购买了一个VPS,一般厂商会提供用户名root,以及随机密码<root_passwd>,这时我们随手打开Terminal,诸如Powershell、Git Bash以及Linux、MacOS自带的终端界面,输入如下指令来连接VPS:

# server.ipv4为需替换字段
ssh root@server.ip
# 默认走22/tcp端口
ssh root@server.ip -p 22

APT

在Debian系(含Ubuntu)的操作系统上,包管理器为apt,旧时则有apt-get,顾名思义,这是一种管理 软件的“软件”,也就是“应用商店”,可以进行软件的安装、卸载、更新等。

# 更新apt软件列表
apt update
# 执行更新软件包 
apt upgrade
# 也可以放在一起
apt update && apt upgrade

UFW

ufw是一个防火墙工具,运行在操作系统上,而云厂商的安全组才是第一道关卡,但一些VPS厂商对安全组的策略比较放松,也即允许所有入站、出站流量,相当于裸奔,这就需要我们自己在VPS上进行防火墙配置。

# 查找ufw
apt search ufw
# 若没有,则安装
apt install ufw 

首先,我们需要对SSH端口进行放行,默认的22是常见的被扫描端口,因此可以改成不常见(非也)的2222,此时我们还没有运行ufw。

# 放行22、2222/tcp端口
ufw allow 22/tcp
ufw allow 2222/tcp
# 默认拒绝入站,允许出站
sudo ufw default deny incoming
sudo ufw default allow outcoming
# 启动ufw
ufw enable
# 查看状态
ufw status verbose
# 删除策略:“放行22/tcp端口”
ufw delete allow 22/tcp

修改SSH配置

我们需要将SSH默认端口改为2222,并禁止root登录。

# 进入配置目录
cd /etc/ssh
# 编辑配置文件
nano sshd_config

nano是一个文本编辑器,相关快捷键如下:

  • ctrl+w搜索
  • ctrl+o+Enter保存
  • ctrl+x退出 我们更改配置文件行为:Port 2222、PermitRootLogin no

User、Group

在一般情况下,root作为最高权限用户,最好不要在Dev环境中长期使用,这会淡薄权限意识,也会造成不可挽救的麻烦,因此一个临时拥有最高权限的普通用户,就很有必要作为日常操作的主要角色。

# -m 创建/home/rolin家目录,-s 指定用户shell环境,rolin为可替换字段
useradd  -m  -s  /bin/bash rolin
# 设置密码
passwd rolin
# 加入用户管理员组(debian系为sudo、arch为wheel)
usermod -aG sudo rolin

Terminal 是 Shell 的人机交互界面,负责输入和输出;Shell 是命令解释器,负责解析命令并执行内建命令或启动外部程序。

Sudo

sudo意味super-do,可以临时变成root用户进行操作。

# 安装sudo
apt install sudo
# 使用visudo编辑/etc/sudoers
visudo

这里需要编辑行,使得sudo用户组具备sudo能力:

# User Privilege Specification
%sudo ALL=(ALL:ALL) ALL
 
# 若是在sudo时不输入密码即可执行
%sudo ALL=(ALL:ALL) NOPASSWD: ALL
# 也可单独对某一用户
rolin ALL=(ALL:ALL) NOPASSWD: ALL

关于其中的四个“ALL”:

  • 1号“ALL”:表示此主机
  • 2号“ALL”:表示可以sudo -u <user>切换的用户(默认为root)
  • 3号“ALL”:表示可以sudo -g <group>切换的用户组
  • 4号“ALL”:表示可以sudo <command>执行的命令

此后我们就可以切换到rol1n了:

su - rol1n
# 回到家/home/rol1n(root的家在/root)
cd ~

SSH密钥对

SSH在我们本地叫做客户端,那么VPS上的那个就是服务端,前文我们修改了服务端的一些配置,现在我们将使用密钥对,进行无密码的SSH登录。

# 在SSH连接的情况下,退出VPS
exit
# 生成密钥对
ssh-keygen -t ed25519 -C "rolin@example.email"
# 将公钥发到目标VPS(此时由于我们未重启ssh,所以配置2222没有生效)
ssh-copy-id rolin@server.ip -p 22
# 登录VPS
ssh rolin@server.ip

此时,我们可以对sshd_config进行进一步修改行:PasswordAuthentication no

# 修改配置文件(注意使用sudo)
sudo nano /etc/ssh/sshd_config
# 终于可以重启ssh应用配置了
sudo systemctl restart ssh

这里的systemctl是Debian的“服务管理器”,管理的大多是开机自启动和需要热重载的一些服务。

SSH的便捷配置

如果每次连接VPS都需要ssh rolin@server.ip -p 2222,不仅长还难记,这时可以用我们客户端ssh的config了:

# 退出VPS
exit
# 编辑config(这里用的是vim编辑器)
vim ~/.ssh/config

如果是Windows用户,可以win+r,输入.,没错就是一个英文句号,然后找到.ssh,创建一个config文本文件即可 ,如下编辑:

   Host vps
       HostName server.ip             # 登录的 IP 地址
       User rolin                     # 登录的用户名
       Port 2222                      # 端口号
       IdentityFile ~/.ssh/id_ed25519 # 前文ssh-keygen生成的私钥文件

保存之后ssh vps即可快速以rolin登录我们的vps。

初识Nginx与80端口

HTTP 协议的标准熟知端口为 80/TCP,因此成为了早期建站的默认端口。后来引入 SSL/TLS 加密技术衍生出了 HTTPS——这也是如今现代主流浏览器直接访问域名时的默认请求协议,其对应的标准服务端口为 443/TCP。

# 放行80/tcp、443/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 安装nginx
sudo apt install nginx

此时我们可以直接到http://server_ip:80 看到Nginx的默认欢迎页。

nginx-welcome

这是一个简单的html网页,它一般就放在/var/www/html/ 下,在debian13 中,它名为index.nginx-debian.html 。

我们可以将nginx设置为开机自启动:

sudo systemctl enable nginx

那么Nginx又是如何去找到这个文件的呢?

Nginx默认的配置文件为:/etc/nginx/nginx.conf

# 切换到root用户,前往nginx目录
sudo su -
cd /etc/nginx/
# 查看nginx.conf
cat nginx.conf

在该文件的http 字段末尾,有这么两行:

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

这通常是debian13 的写法,其它系统可能有所不同。

我们可以到sites-enabled/ 目录中一探究竟:

# “..”表示回到上一级目录
cd ../sites-enabled/
# 输入ls -la命令查看目录中的文件
ls -la
# 默认输出
lrwxrwxrwx - root  9 May 11:51 default -> /etc/nginx/sites-available/default

这里可以看到有一个default 文件,但它的类型是l 也即link 软连接,指向的源文件是/etc/nginx/sites-available/default ,我们可以直接来编辑看看。

# nano编辑源文件
sudo nano /etc/nginx/sites-available/default

通常可以看到如下内容:

server {
    listen 80 default_server;
    listen [::]:80 default_server;
 
    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
 
    server_name _;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

它存放了一个server 块,监听着IPv4/v6的80端口,将网站根目录指向本机的/var/www/html 路径,并用index 指定了默认的根目录html文件为index.nginx-debian.html ,这是debian 为了方便,将server 以单独文件形式存放,但本质上令其其效果的依然还是初始的那份nginx.conf 文件,因此可以直接在其http 字段中将include 注释掉,把这段server 挪过去。

# ...省略其他字段
http {
    ##
    # 基础传输与性能设置
    ##
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
 
    # 引入 MIME 类型映射,确保浏览器能正确识别 CSS/JS/图片等
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
 
    ##
    # SSL 默认加密套件配置
    ##
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
 
    ##
    # 日志记录配置
    ##
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
 
    ##
    # Gzip 压缩配置
    ##
    gzip on;
    gzip_disable "msie6";
 
    # 注释include
    # include /etc/nginx/conf.d/*.conf;
    # include /etc/nginx/sites-enabled/*;
 
    ##
    # 默认虚拟主机 (合并进来的默认 server 块)
    ##
    server {
        # 监听 IPv4 和 IPv6 的 80 端口,并指定为默认兜底站点
        listen 80 default_server;
        listen [::]:80 default_server;
 
        # 网站根目录与默认首页查找顺序
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
 
        # 匹配任何未被其他 server 块命中的 Host 头
        server_name _;
 
        # 路由规则:优先找匹配文件,其次匹配目录,找不到则返回 404
        location / {
            try_files $uri $uri/ =404;
        }
    }
}
# ...省略其他字段

Certbot的TLS证书申请

  • Let’s Encrypt是一家免费、开放、自动化的公益证书颁发机构(CA)
  • acme.sh 是一套shell脚本,整体轻量依赖极轻,适用于资源紧张型设备,用于向CA申请证书、定时更新。(默认CA为zeroSSL)
  • Certbot是ACME的Python客户端,相比acme.sh而言,需要python运行环境,因此占用了一些基础资源。(默认CA为LetsEncrypt)
# 切换为rolin用户
su - rolin
# 安装certbot与其nginx插件
sudo apt install certbot 
sudo apt install python3-certbot-nginx

Certbot在申请TLS证书时,会自动暂时修改Nginx的80端口server块配置。

TLS证书是颁布给域名的,而域名最终都是要指向IP的,因此我们需要在DNS解析处,编写一条A记录,将要申请证书的域名,指向本服务器的IPv4。

这样做以便于CA能找到我们的服务器,进而确定为该域名颁发证书到这台服务器上,而TLS证书本质,也就是这三样信息:

  • 域名/通配符
  • 公钥字符串
  • CA机构名
# 仅申请证书(文件名为首个域名)
sudo certbot certonly --nginx -d <your-domain-1> -d <your-domain-2>
# 查看已安装的证书
sudo certbot certificates
# 删除证书
sudo certbot delete --cert-name <your-domain>

注意这里申请证书时,使用了certonly 命令,这是为了避免certbot自动修改nginx.conf 造成混乱。

通过certbot申请的TLS证书默认都会保存在/etc/letsencrypt/ 目录下,我们可以到这个目录来看看:

# 切换为root
sudo su -
# 进入TLS证书目录 
cd /etc/letsencrypt
# 查看目录下的结构(这里 -la 可以查看一些以'.'开头的隐藏文件、目录)
ls -la
# 得到的大致结果
Permissions Size User Date Modified Name
drwx------     - root  9 May 11:53 accounts
drwx------     - root 19 Sep 00:21 archive
drwx------     - root 19 Sep 00:21 live
drwxr-xr-x     - root 21 Sep 11:59 renewal
drwxr-xr-x     - root  9 May 11:53 renewal-hooks
.rw-r--r--    64 root  9 May 11:53 .updated-options-ssl-nginx-conf-digest.txt
.rw-r--r--    64 root  9 May 11:53 .updated-ssl-dhparams-pem-digest.txt
.rw-r--r--   207 root 12 Nov  2021 cli.ini
.rw-r--r--   774 root  9 May 11:53 options-ssl-nginx.conf
.rw-r--r--   424 root  9 May 11:53 ssl-dhparams.pem

这里最有用的是live 目录,里面是装载了一条条指向archive 中真实TLS文件的软连接的域名目录,但在live 目录下,它们被保持了固定的名称和最新的内容,方便部署时统一。

可以进入任意一个域名文件夹来看看TLS文件是哪些?

# 进入名为for.example.com的TLS文件夹('.'表示当前目录)
cd ./live/for.example.com/
# 查看目录中的结构
ls -la
# 得到的大致结果
Permissions Size User Date Modified Name
lrwxrwxrwx     - root 17 Aug 23:10 cert.pem -> ../../archive/for.example.com/cert2.pem
lrwxrwxrwx     - root 17 Aug 23:10 chain.pem -> ../../archive/for.example.com/chain2.pem
lrwxrwxrwx     - root 17 Aug 23:10 fullchain.pem -> ../../archive/for.example.com/fullchain2.pem
lrwxrwxrwx     - root 17 Aug 23:10 privkey.pem -> ../../archive/for.example.com/privkey2.pem
.rw-r--r--   692 root 18 Jun 18:33  󰂺 README

可以看到他们是一个个link ,值得注意的是cert.pem 拼接上chain.pem 就是fullchain.pem ,因此真正重要的就是fullchain.pem 与privkey.pem 了。

Nginx的网站上线

根据上文部署好的TLS证书,我们可以对默认的http 站点升级到https ,只需修改nginx.conf 的server :

# 80 端口:全局强制重定向至 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name for.example.com;
 
    return 301 https://$host$request_uri;
}
 
# 443 端口:默认 HTTPS 站点
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name for.example.com;
 
    # 替换为你实际的证书与私钥路径
    ssl_certificate     /etc/letsencrypt/live/for.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/for.example.com/privkey.pem;
 
    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
 
    location / {
        try_files $uri $uri/ =404;
    }
}

这里最重要的区别是:

  • 移除了default_server 的声明,添加了server_name
  • 为原server添加一条return重定向规则,强制转向https
  • 新增了一个监听443,声明ssl 的server
  • 在新增的 server中配置了TLS证书路径,并将root、index、location移动到这里

这里需要说明nginx匹配server的优先级问题,自高向低为:

  • 显式配置server_name 的server优先
  • default_server 为默认兜底生效的server
  • 若都没有配置,则优先匹配第一个server

随后可以使用命令检查nginx配置文件是否合法,并热重载nginx使其生效:

# 检查格式
sudo nginx -t
# 热重载
sudo systemctl reload nginx

Certbot自动续签与Hook脚本

在使用certbot进行TLS证书申请时会自动启动一个service,定时执行证书续期命令(sudo certbot renew):

# 切换为rolin用户
su - rolin
# 查看certbot定时器服务状态
sudo systemctl status certbot.timer

我们上文中使用了certonly参数,这导致certbot不被授权修改nginx配置文件,带来一个负面影响:它不会在证书更新后自动执行sudo systemctl reload nginx 来热重载nginx来更新网站证书,进而造成用户访问网站时提示证书失效 的报错。

要解决这个问题,需要用到certbot的deploy hook 功能,还记得/etc/letsencrypt/ 目录吗?其中有个文件夹叫renewal-hooks ,这便是hook脚本的存放目录。

# 切换到root
sudo su -
# 创建deploy目录
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
cd /etc/letsencrypt/renewal-hooks/deploy
# 编写热重载nginx脚本
nano reload-nginx.sh

reload-nginx.sh 内容:

#!/usr/bin/sh
set -e
 
# 推荐方式:通过 systemctl 操作服务
/usr/sbin/nginx -t >/dev/null 2>&1 && /usr/bin/systemctl reload nginx

需要注意的是,这里给到的命令是绝对路径,真实的绝对路径需要自行在机器上检测:

# 查找sh绝对路径
which sh
# 查找nginx绝对路径
which nginx
# 查找systemctl绝对路径
which systemctl

不要忘了给脚本加上执行权,随后可以运行Certbot模拟更新命令:

# 加上执行权限
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
# 运行模拟申请+hook执行
certbot renew --dry-run --run-deploy-hooks
# 检查nginx重载日志,检验hook脚本是否生效
journalctl -u nginx --since "2 minutes ago"

文件、目录权限管理

总所周知,在Linux系统中一切皆文件。

那么文件、目录的权限管理就变得异常重要,这里有三种权限:

  • r :读(read),对用户、组定义哪个文件、目录具有被查看 权
  • w :写(write),对用户、组定义哪个文件、目录具有被编辑 权
  • x :执行(execute),对用户、组定义哪个文件、目录具有被执行 、被进入 权

以上文提到的ls -l 命令为例:

Permissions Size User Date Modified Name
drwx------     - root  9 May 11:53 accounts
drwx------     - root 19 Sep 00:21 archive
drwx------     - root 19 Sep 00:21 live
drwxr-xr-x     - root 21 Sep 11:59 renewal
drwxr-xr-x     - root  9 May 11:53 renewal-hooks
.rw-r--r--   207 root 12 Nov  2021 cli.ini
.rw-r--r--   774 root  9 May 11:53 options-ssl-nginx.conf

在Permissions 一列中,以10个字符来定义文件类型 、用户权 、用户组权 、其他人权 ,以drwxr-xr-x 举例,表面这是一个directory 即目录,所有者拥有rwx 全部权限,所属组拥有rx 权,而其他人拥有rx 权。

注意到rwx 三个权限,按照布尔值的标准,可以组合在一起表示成一个八进制数,这里也就是4+2+1=7 ,那么拓展到将三个对象的权限定义组合在一起,以renewal-hooks 为例,它的权限码就是755 。

再来说针对新文件、目录的权限定义,这也是解释权限最初的来源。Linux对其具有基准值,新建目录的基准权限为0777 ,对于新建文件的基准权限为0666 ,而针对每一个用户,都有一个用户掩码umask ,一般来说,最常见的umask为022 ,最终决定某一个用户创建新文件、新目录的 初始权限公式为:

Effective Permission=Base Permission & (∼umask)\text{Effective Permission} = \text{Base Permission} \ \& \ (\sim\text{umask})

也即对umask取反再与基准权限做与 运算得到最终权限表达,因此我们022 的umask下:

  • 新建文件:rw-r--r-- /644
  • 新建目录:rwxr-xr-x /755

这也解释了为什么644 与755 这么频繁的出现在权限命令中。

# 查看当前用户的umask码
umask
# 将其设置为022
umask 022
# 授权命令
chmod 755 test
# 慎重使用对目录的递归授权(这会造成目录中所有文件也变成644)
chmod -R 644 dir/
# 更改所有者
chown rolin test
# 更改所有组
chown :sudo test
# 同时更改所有组与所有者
chown rolin:sudo test

第三方应用的权限管理

这里我们将一些软件抽象定义成app ,它默认只有在nobody:nogroup 的权限下,才能正常运行,这就要求我们对权限的管理非常严格,而不能仅仅把其全部放在~ 用户目录下。

传统上,对于严格追求FHS标准,我们需要将同一个app的不同文件放在根目录的不同位置:

  • /usr :存放可执行文件
  • /etc :存放静态配置文件
  • /var :存放持久化数据、日志文件
  • /run :存放运行时文件
  • /tmp :存放临时文件

而兼顾方便与FHS标准,我们可以把这个app 放在/opt 中(独立第三方部署包),建立一个标准的权限目录:

/opt/app/
├── bin/          # 可执行文件与依赖库(root:root,只读执行)
├── config/       # 配置文件(root:root,只读)
├── data/         # 运行时数据(nobody:nogroup,完全读写)
├── log/          # 应用日志(nobody:nogroup,完全读写)
# 创建目录树
sudo mkdir -p /opt/app/{bin,config,data,log}
# 权限初始化
sudo chown -R root:root /opt/app
sudo chmod 755 /opt/app
sudo chmod 755 /opt/app/bin
sudo chmod 755 /opt/app/config
# 数据、日志交给默认用户
sudo chown -R nobody:nogroup /opt/app/data /opt/app/log
sudo chmod 750 /opt/app/data /opt/app/log

TLS证书异位自动更新部署

由于Certbot本身权限非常高,也是对私钥文件的保护,除了nginx等web应用,其他非root身份程序无法读取证书文件,这就导致上文提到的/opt/app 在应用证书时,会报出权限不足的错误。

为了保证证书的可读性,又不失Certbot热更新证书的机制,我们可以使用上文提到的Deploy Hook脚本功能,实现证书文件实时copy与热更新机制保留。

# 编辑脚本
sudo nano /etc/letsencrypt/renewal-hooks/deploy/app-cert.sh
# 赋予权限
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/app-cert.sh

脚本内容如下:

#!/bin/sh
set -eu
 
# ==================== 配置区 ====================
# Certbot 证书名(通常为 /etc/letsencrypt/live/ 下的目录名)
CERT_NAME="for.example.com"
 
# 目标应用证书目录
DEST_DIR="/opt/app/cert"
 
# 目标属主与所属组
DEST_USER="root"
DEST_GROUP="nogroup"
 
# 权限掩码:目录 0750(仅属主和组可穿透),文件 0640(仅属主可写,组只读)
DIR_MODE="0750"
FILE_MODE="0640"
 
# 重载命令
RELOAD_CMD="systemctl reload <app_service_name>"
# ===============================================
 
# 1. 匹配当前续期的域名证书,非目标域名直接退出
if [ "${RENEWED_LINEAGE:-}" != "/etc/letsencrypt/live/${CERT_NAME}" ]; then
    exit 0
fi
 
# 2. 确保目标目录存在并具备正确归属与权限
install -d -o "${DEST_USER}" -g "${DEST_GROUP}" -m "${DIR_MODE}" "${DEST_DIR}"
 
# 3. 复制 fullchain.pem 与 privkey.pem
install -o "${DEST_USER}" -g "${DEST_GROUP}" -m "${FILE_MODE}" \
    "${RENEWED_LINEAGE}/fullchain.pem" \
    "${DEST_DIR}/fullchain.pem"
 
install -o "${DEST_USER}" -g "${DEST_GROUP}" -m "${FILE_MODE}" \
    "${RENEWED_LINEAGE}/privkey.pem" \
    "${DEST_DIR}/privkey.pem"
 
# 4. 执行服务热重载
if [ -n "${RELOAD_CMD}" ]; then
    ${RELOAD_CMD}
fi

然后模拟证书更新并执行脚本逻辑:

sudo certbot renew --dry-run --run-deploy-hooks

检查app证书目录是否已完成copy:

cd /opt/app/cert
ls -la

Nginx非域名拒绝访问

Nginx作为一个web服务器,处于公网,且有TLS为HTTP保驾护航,很多时候我们不希望可以从具体IP来访问Nginx代理的网站,包括HTTPS请求,因此我们可以制作一个虚假的SSL证书,并在nginx.conf 中新增两个保底server来承接IP访问:

# 切换为root用户
sudo su -
# 创建自定义证书目录,-p会在缺失父目录时自动创建
mkdir -p /etc/customTLS
cd /etc/customTLS
# 生成一个自签名的10年证书
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout /etc/customTLS/dummy.key \
  -out /etc/customTLS/dummy.crt \
  -subj "/CN=unused"
参数 含义
openssl req 生成证书请求,配合 -x509 时直接生成自签名证书
-x509 直接输出自签名证书(而不是生成待签名的 CSR)
-nodes 私钥不加密(no DES),生成时不提示输入密码
-days 3650 有效期 3650 天(约 10 年)
-newkey rsa:2048 同时生成一对新的 2048 位 RSA 密钥

| -keyout ... | 私钥输出路径 |` | -out ... | 证书输出路径 | | -subj "/CN=unused"` | 证书主题,CN 设为 unused,说明这张证书不用于真实身份 |

这里的\ 是续行符,方便在终端输入命令时,按下回车接着在下一行输入。

最后,就是对nginx.conf 新添两段server:

# ==================== 防IP访问 - HTTP ====================
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    # 匹配所有未绑定的域名和直接 IP 访问
    # 444直接关闭连接,不返回任何信息,比 403 更安全
    server_name _;
    return 444;
}
 
# ==================== 防IP访问 - HTTPS ====================
server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    server_name _;
 
    # 配置一个无效或自签名的 SSL 证书
    # 目的是让通过 IP 的 HTTPS 访问因证书错误而失败
    ssl_certificate /etc/customTLS/dummy.crt;
    ssl_certificate_key /etc/customTLS/dummy.key;
 
    # 也可以直接返回错误,但证书错误通常能阻止连接建立
    return 444;
}

小型下载路由

在最终匹配的server中,可以添加location字段,来将本地文件放在HTTP中,

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name for.example.com; 
 
    ssl_certificate /etc/letsencrypt/for.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/for.example.com/privkey.pem;
 
    root /var/www/html;
    index index.html;
    
    default_type text/plain;
    charset utf-8;
    charset_types text/css text/plain application/javascript application/json text/yaml application/x-yaml;
    add_header Content-Disposition inline;
 
    location = /test.txt  {
        default_type text/plain;
    }
 
    location = /file.json {
    }
 
    location / {
    	try_files $uri $uri/ =404; 
    }
}

这样访问https://for.example.com/test.txt就能获取服务器上的/var/www/html/test.txt文件了。

值得说明的是,这里的charset utf-8;是指定文本编码格式为UTF-8;add_header Content-Disposition inline;则是告诉浏览器,默认将请求内容直接打开,而不是下载。

而location则有三种常见写法,前两种的区别在于是否显式指定类型名,但这里的写法都是合理的,原因是在nginx.conf的http段开头已经include mime.types;,这是专门用于将后缀名映射到指定类型的文件。 最后一种则是使用try_files方法,尝试查找用户请求的文件名、目录名,若均不存在则返回404。