Skip to content

nginx搭建配置

debian上安装nginx

安装并启动

bash
# 更新包列表并升级系统
sudo apt update && sudo apt upgrade -y

# 安装 Nginx
sudo apt install nginx -y

# 启动并设置开机自启
sudo systemctl start nginx
sudo systemctl enable nginx

# 检查运行状态
sudo systemctl status nginx

基础安全配置

1、备份配置

bash
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d)

2、建立目录和通用snippet

bash
sudo mkdir -p /etc/nginx/snippets
sudo mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled

3、编辑安全头snippet(统一管理,所有站点都一样),/etc/nginx/snippets/security-headers.conf

bash
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# 现代安全策略(适配 VitePress / VuePress)
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:;" always;

4、通用安全规则snippet(限速、方法限制、敏感文件屏蔽),/etc/nginx/snippets/security-rules.conf

bash
# ======================
# 限流(必须依赖 nginx.conf 定义 zone)
# ======================
limit_req zone=general burst=20 nodelay;
limit_conn conn_per_ip 20;

# ======================
# 隐藏文件访问
# ======================
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

# ======================
# 敏感文件
# ======================
location ~* \.(sql|zip|tar|gz|bak|env|git)$ {
    deny all;
    access_log off;
}

# ======================
# 禁止脚本执行文件访问(静态站安全)
# ======================
location ~* \.(php|cgi|pl|py|jsp|asp|sh)$ {
    deny all;
    access_log off;
}

5、错误页snippet(统一错误处理),/etc/nginx/snippets/error-page.conf

bash
error_page 403 404 405 500 502 503 504 /error.html;

location = /error.html {
    root /usr/share/nginx/html;
    internal;

    add_header Cache-Control "no-cache, no-store, must-revalidate";
}

5、改造nginx.conf,只留全局,去掉所有server块,/etc/nginx/nginx.conf

bash
user www-data;    # 有些要使用用户 nginx 才行,如果 nginx -t 出错就改下这个
worker_processes auto;
worker_rlimit_nofile 65535;

error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 65;
    keepalive_requests 1000;

    server_tokens off;

    # ======================
    # DNS(稳定生产版)
    # ======================
    resolver 223.5.5.5 119.29.29.29 1.1.1.1 valid=300s;
    resolver_timeout 5s;

    # ======================
    # 日志
    # ======================
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main buffer=32k flush=5m;

    # ======================
    # 限流定义
    # ======================
    limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;

    # ======================
    # 请求基础控制
    # ======================
    client_max_body_size 20m;
    client_body_timeout 10s;
    client_header_timeout 10s;
    send_timeout 10s;

    large_client_header_buffers 4 16k;

    # ======================
    # gzip
    # ======================
    gzip on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_vary on;
    gzip_proxied any;

    gzip_types
        text/plain
        text/css
        application/json
        application/javascript
        text/xml
        application/xml
        application/xml+rss
        image/svg+xml;

    # ======================
    # SSL(预留,不冲突)
    # ======================
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;
    ssl_ciphers EECDH+AESGCM:EDH+AESGCM;

    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 10m;

    ssl_stapling on;
    ssl_stapling_verify on;

    # ======================
    # 引入站点
    # ======================
    include /etc/nginx/sites-enabled/*;
}

6、创建yuming.com的站点文件,/etc/nginx/sites-available/yuming.com.conf
注意: 在还没有配置ssl证书时需要注释掉一些内容。

bash
server {
    listen 80;
    server_name yuming.com www.yuming.com;

    root /html;
    index index.html index.htm;

    # ======================
    # 引入模块
    # ======================
    include /etc/nginx/snippets/security-headers.conf;
    include /etc/nginx/snippets/security-rules.conf;
    include /etc/nginx/snippets/error-page.conf;

    # ======================
    # 主站点逻辑
    # ======================
    location / {

        limit_except GET HEAD POST {
        deny all;
        }
        try_files $uri $uri/ =404;
    }

    # ======================
    # 静态资源缓存(性能优化)
    # ======================
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2?)$ {
        expires 7d;
        access_log off;
    }
}

7、如果还有别的站点可以继续在/etc/nginx/sites-available/下新建站点,比如yuming2.com.conf的。

8、启用站点(创建软链接)

bash
sudo ln -s /etc/nginx/sites-available/yuming.com.conf /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/yuming2.com.conf /etc/nginx/sites-enabled/
bash
sudo rm -f /etc/nginx/sites-enabled/default

这个软链接会让Nginx加载那个default站点,它通常监听80端口,可能会和我们后面配置的站点发生端口冲突,所以必须删掉。

9、测试并重载Nginx

bash
sudo nginx -t
sudo systemctl reload nginx

配置SSL

使用Let's Encrypt配置

1、安装CertbotNginx插件

bash
sudo apt update
sudo apt install certbot python3-certbot-nginx -y

说明: python3-certbot-nginx这个包提供了certbot --nginx子命令,让Certbot能自动读取和修改你的Nginx配置,实现一键HTTPS

bash
certbot --version

2、申请SSL证书并让Certbot自动配置Nginx

bash
sudo certbot --nginx -d yuming.com

如果还需要让www.yuming.com 也一并获得证书,可以加多个-d参数

bash
sudo certbot --nginx -d yuming.com -d www.yuming.com

执行过程中会依次出现几个交互式询问:

(1)输入邮箱地址
用于证书到期提醒和紧急安全通知,输入你的常用邮箱并按回车。

(2)同意服务条款
输入Y并按回车。

(3)是否订阅EFF新闻邮件
一般情况下输入N按回车,选不订阅即可。

(4)是否将HTTP自动重定向到HTTPS

输入2然后回车 —— 这样别人访问http://yuming.com时会自动跳转到https://yuming.com,强烈推荐。

如果暂时不想跳转,可以选择1

等待几秒,看到类似下面的输出,就代表证书申请成功且Nginx已经配置好了:

text
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/yuming.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/yuming.com/privkey.pem
...
Deploying certificate
Successfully deployed certificate for yuming.com to /etc/nginx/sites-enabled/yuming.com

3、测试HTTPS

bash
curl -I https://yuming.com

看到HTTP/2 200HTTP/1.1 200 OK就说明HTTPS正常工作。

4、验证证书自动续期

Let's Encrypt证书有效期90天,通过APT安装Certbot时会自动创建一个systemd定时器,每天两次检查并自动续期临近到期的证书。

先手动模拟一次续期,确认没有配置错误:

bash
sudo certbot renew --dry-run

如果没有报错(或者只看到一些无害的警告),自动续期机制就是正常的,以后你完全不用操心证书过期问题。

bash
systemctl status certbot.timer

5、查看已经申请了哪些证书

bash
sudo certbot certificates

ls -l /etc/letsencrypt/live/

6、查看/etc/nginx/sites-available/yuming.com.conf,会自动生成ssl相关的配置。

rockylinux9上安装nginx

bash
dnf install -y nginx
systemctl start nginx
systemctl enable nginx
systemctl status nginx

firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https

firewall-cmd --reload
firewall-cmd --list-all

然后将Windows中的共享目录挂载到/mnt/smb

bash
sudo vim /root/smb101.sh    //脚本内容如下
#!/bin/bash
sudo cp -R /mnt/smb/* /nginx/www
sudo find /nginx/www -type f -name "*.html" -exec sed -i '5i <link rel="icon" href="./picture/dnc32.ico" type="image/x-icon">' {} \;

访问静态html配置认证

Nginx上配置基本的HTTP认证(即要求用户名和密码进行登录),你需要进行以下步骤

1、安装htpasswd工具
如果你的服务器上没有安装htpasswd工具,你需要先安装它。这可以通过安装apache2-utils来完成

bash
sudo yum -y update
sudo yum install -y httpd-tools

2、创建密码文件
使用htpasswd创建一个密码文件,并添加用户名和密码。假设你希望添加一个名为user的用户,可以运行以下命令:

bash
sudo htpasswd -c /etc/nginx/.htpasswd user

系统会提示你输入并确认密码。-c选项是用来创建新的.htpasswd文件,如果.htpasswd文件已经存在,请去掉-c选项以避免覆盖文件。

bash
cat /etc/nginx/.htpasswd user
user:$apr1$4JpcXQ3q$NzrXa7vDhPq2PB7b9vAts.

htpasswd -D /etc/nginx/.htpasswd user    //-D:删除指定的用户,改密码先删再添加
sudo systemctl reload nginx

htpasswd工具支持多种加密算法

MD5(\$apr1\$):这是Apache默认的加密方式,也常用于.htpasswd文件。
bcrypt(\$2y\$):一种更强的加密方式,适用于对密码安全性要求更高的场景,加-B选项。
SHA-1(\$sha1\$):另一种加密方式,但不如bcrypt安全。

3、配置Nginx以启用身份验证
编辑你的Nginx配置文件(通常是/etc/nginx/nginx.conf或者位于/etc/nginx/sites-available/default),在你需要保护的serverlocation块中添加以下内容

bash
server {
    listen 80;
    server_name your-domain.com;

    root /path/to/your/root;  # 网站根目录
    index index.html;

    # 保护 /linux 目录
    location /linux {
        auth_basic "Restricted Access for Linux";
        auth_basic_user_file /etc/nginx/.htpasswd;
        add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
        add_header Pragma "no-cache";
        add_header Expires 0;
    }

    # 保护 /own 目录
    location /windows {
        auth_basic "Restricted Access";
        auth_basic_user_file /etc/nginx/.htpasswd-own;
        add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
        add_header Pragma "no-cache";
        add_header Expires 0;
    }

    # 对 /index.html 禁用认证
    location = /index.html {
        auth_basic off;
    }

    # 对 /about.html 禁用认证
    location = /about.html {
        auth_basic off;
    }

    # 默认规则(不启用认证,可根据需求修改)
    location / {
        auth_basic off;  # 不保护其他路径
    }
}

Cache-Control: no-store, no-cache, must-revalidate要求浏览器不缓存页面内容或认证信息。
Pragma: no-cache:兼容老版本HTTP/1.0的浏览器。
Expires 0:明确指定页面已过期。

使用=时,表示路径必须与指定的路径完全一致才会匹配。

这样,所有访问该路径下的页面时都会弹出密码提示框。

bash
sudo systemctl reload nginx

https自签名OpenSSL证书

1、安装openssl并生成私钥

bash
sudo yum install -y openssl
openssl req -newkey rsa:2048 -nodes -keyout mysite.key -out mysite.csr    //生成一个私钥文件和一个CSR文件。

req: 表示生成请求。
-newkey rsa:2048: 使用RSA算法生成2048位私钥。
-nodes: 表示不对私钥进行加密(无需输入密码)。
-keyout mysite.key: 生成的私钥文件名为mysite.key
-out mysite.csr: 输出的CSR文件名为mysite.csr

在执行命令后,系统会提示你填写信息,例如:

Country Name (2 letter code): 国家代码(如CN)。
State or Province Name: 省份。
Locality Name: 城市。
Organization Name: 组织名。
Organizational Unit Name: 部门名。
Common Name: 你的域名或服务器IP(如果通过IP访问,填服务器IP)。
Email Address: 邮箱地址。

注意Common Name应与你访问网站时的地址一致。

2、生成证书

bash
openssl x509 -req -days 365 -in mysite.csr -signkey mysite.key -out mysite.crt    //使用私钥文件签署一个自签名证书。

x509: 表示生成证书。
-req: 表示输入一个CSR文件。
-days 365: 设置证书有效期为365天。
-in mysite.csr: 输入CSR文件。
-signkey mysite.key: 使用私钥签署证书。
-out mysite.crt: 输出生成的证书文件。

4、配置nginx的https

bash
# HTTPS Server 配置
server {
    listen 443 ssl;  # 监听 443 端口并启用 SSL
    server_name your_domain_or_ip;  # 替换为你的域名或服务器 IP

    # SSL 证书配置
    ssl_certificate /path/to/mysite.crt;  # 替换为你的证书路径
    ssl_certificate_key /path/to/mysite.key;  # 替换为你的私钥路径

    # 推荐的 SSL 参数
    ssl_protocols TLSv1.2 TLSv1.3;  # 启用安全的协议
    ssl_ciphers HIGH:!aNULL:!MD5;  # 使用强加密算法
    ssl_prefer_server_ciphers on;  # 优先使用服务器端的加密套件

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;  # 强制https

    # 网站目录配置
    root /path/to/your/website;  # 替换为你的网站目录
    index index.html index.htm;  # 默认首页文件

    location / {
        try_files $uri $uri/ =404;  # 简单的静态文件处理
    }
}

# HTTP 重定向到 HTTPS
server {
    listen 80;  # 监听 80 端口
    server_name your_domain_or_ip;  # 替换为你的域名或服务器 IP
    return 301 https://$server_name$request_uri;  # 将 HTTP 请求重定向到 HTTPS
}

上面的访问认证配置放到443处

添加HSTS(强制HTTPS):在HTTPS配置中增加以下内容

bash
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

浏览器会强制访问HTTPS(有效期31536000秒,约1年)。
includeSubDomains表示对所有子域名生效。

启用OCSP Stapling(减少SSL握手延迟):如果有外部CA证书时,建议启用。对自签名证书一般不必要。

5、测试Nginx配置

bash
sudo nginx -t    //如果配置正确,会显示类似以下内容
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

sudo systemctl reload nginx    //重新加载nginx

6、一些配置说明

bash
server {
    listen 80;
    server_name _;  # `_` 表示匹配所有请求,适用于没有域名的情况

    # 固定跳转到 HTTPS 的 IP 地址
    return 301 https://192.168.0.10$request_uri;
    //return 301 https://www.yourdomain.com$request_uri;
    //return 301 https://$server_name$request_uri;
}

7、网站出错时不显示nginx具体版本

bash
vim /etc/nginx/nginx.conf
http {
    server_tokens off;
    ...
}