基于Debian 12 通过Nginx、Certbot部署节点

1、通过脚本安装Nginx以及Certbot

以下是一个完整的 Bash 脚本,用于在 Debian 12 系统上一键安装 Nginx(官方最新稳定版)和 Certbot(通过 Snap)。脚本会检查执行权限,逐步执行所有命令,并在最后给出后续配置的提示。

#!/bin/bash

# Nginx 和 Certbot 一键安装脚本(适用于 Debian 12)
# 请以 root 用户或使用 sudo 执行此脚本

set -e  # 遇到错误立即退出

# 颜色定义(便于阅读输出)
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # 无颜色

# 检查是否以 root 身份运行
if [[ $EUID -ne 0 ]]; then
   echo -e "${RED}请以 root 用户或使用 sudo 执行此脚本。${NC}"
   exit 1
fi

echo -e "${GREEN}开始更新系统软件包列表...${NC}"
apt update && apt upgrade -y

echo -e "${GREEN}安装必要的依赖工具...${NC}"
apt install -y curl gnupg2 ca-certificates lsb-release

echo -e "${GREEN}添加 Nginx 官方稳定版仓库...${NC}"
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/debian $(lsb_release -cs) nginx" | tee /etc/apt/sources.list.d/nginx.list

echo -e "${GREEN}更新仓库索引并安装 Nginx...${NC}"
apt update
apt install -y nginx

# 显示 Nginx 版本
nginx_version=$(nginx -v 2>&1 | cut -d '/' -f2)
echo -e "${GREEN}Nginx 安装完成,版本:${nginx_version}${NC}"

echo -e "${GREEN}启动 Nginx 并设置开机自启...${NC}"
systemctl start nginx
systemctl enable nginx

echo -e "${GREEN}安装 Snapd 并更新...${NC}"
apt install -y snapd
snap install core
snap refresh core

echo -e "${GREEN}通过 Snap 安装 Certbot...${NC}"
snap install --classic certbot
ln -sf /snap/bin/certbot /usr/bin/certbot

# 验证 Certbot 安装
certbot_version=$(certbot --version 2>&1)
echo -e "${GREEN}Certbot 安装完成,版本:${certbot_version}${NC}"

echo -e "${GREEN}====================================================${NC}"
echo -e "${GREEN}Nginx 和 Certbot 已成功安装!${NC}"
echo -e "${GREEN}下一步操作:${NC}"
echo -e "1. 根据您的需求修改 Nginx 配置文件:/etc/nginx/nginx.conf"
echo -e "   请确保为 HTTP-01 验证添加 location /.well-known/acme-challenge/ 的配置。"
echo -e "2. 修改后使用 'nginx -t' 测试配置,并使用 'systemctl reload nginx' 重载。"
echo -e "3. 使用以下命令申请 SSL 证书(请替换域名为您的实际域名):"
echo -e "   sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com"
echo -e "4. 申请成功后,更新 Nginx 配置中的证书路径,并启用 HTTPS。"
echo -e "${GREEN}====================================================${NC}"

使用方法

将上述内容保存为文件,例如 install-nginx-certbot.sh

赋予执行权限:chmod +x install-nginx-certbot.sh

以 root 用户或使用 sudo 执行:sudo ./install-nginx-certbot.sh

2、修改Nginx配置。

使用编辑工具修改位于 /etc/nginx/conf.d/*.conf 配置。

server {
    listen 80;
    server_name yisroa.tongames.dpdns.org cangsroa.tongames.dpdns.org;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
        allow all;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

域名根据实际情况修改yisroa.tongames.dpdns.org cangsroa.tongames.dpdns.org。提示:域名与域名之间需用空格间隔。

默认路径为 /var/www/html,如果没有请手动创建

# 1. 创建目录(-p 参数确保如果父目录不存在也会一并创建,且如果目录已存在不会报错)
mkdir -p /var/www/html

# 2. 修改所有者为 www-data (Debian/Ubuntu 上 Nginx 的默认运行用户)
chown -R www-data:www-data /var/www/html

# 3. 设置权限为 755 (所有者可读写执行,其他人可读执行)
chmod -R 755 /var/www/html

修改配置之后,使用命令检查nginx配置,配置没提示报错的情况下,重载nginx配置。

nginx -t
nginx -s reload

之后使用Certbot以webroot模式为域名申请SSL证书。

在正式执行前,加上 --dry-run 参数。这会模拟整个获取流程,而不计入 Let’s Encrypt 的速率限制(Rate Limits)。

sudo certbot certonly --webroot -w /var/www/html -d yourdomain.com -d www.yourdomain.com --email your@email.com --agree-tos --no-eff-email --deploy-hook "systemctl reload nginx" --dry-run
sudo certbot certonly --webroot -w /var/www/html -d yourdomain.com -d www.yourdomain.com --email your@email.com --agree-tos --no-eff-email --deploy-hook "systemctl reload nginx"
  • 域名申请成功之后会显示证书路径,如下示例:
  • /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/fullchain.pem
  • /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/privkey.pem

3、再次为nginx修改配置,添加Https,需修改nginx.conf,以及位于conf.d目录下的配置文件。

nginx.conf配置示例如下:根据实际情况调整。


user nginx;
worker_processes auto;

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

events {
    worker_connections 1024;
}

stream {
    map $ssl_preread_server_name    $name {
        yisroa.tongames.dpdns.org    backend1;
        cangsroa.tongames.dpdns.org  backend2;
        cousroa.tongames.dpdns.org   backend3;
        mensroa.tongames.dpdns.org   backend4;
        default                     default_backend;
    }

    upstream backend1 {
        server 127.0.0.1:48001;
    }

    upstream backend2 {
        server 127.0.0.1:48003;
    }
    upstream backend3 {
        server 127.0.0.1:48005;
    }

    upstream backend4 {
        server 127.0.0.1:48007;
    }

    upstream default_backend {
        server 127.0.0.1:8011;
    }

    server {
        listen            443;
        proxy_pass        $name;
        ssl_preread       on;
        proxy_protocol    on;
    }
}

http {
    # --- 1. 基础全局配置 ---
    include       mime.types;
    default_type  application/octet-stream;
    
    log_format main '[$time_local] $proxy_protocol_addr "$http_referer" "$http_user_agent"';
    access_log /var/log/nginx/access.log main;

    server_tokens off;
    
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    # --- 2. 全局映射逻辑 (原子配置1) ---
    # 这里的变量在所有 server 块中均可直接使用
    
    # WebSocket 升级映射
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ""      close;
    }

    # Proxy Protocol 地址格式化映射
    map $proxy_protocol_addr $proxy_forwarded_elem {
        ~^[0-9.]+$        "for=$proxy_protocol_addr";
        ~^[0-9A-Fa-f:.]+$ "for=\"[$proxy_protocol_addr]\"";
        default           "for=unknown";
    }

    # 复杂的 RFC 7239 Forwarded 头部构造映射
    map $http_forwarded $proxy_add_forwarded {
        "~^(,[ \\t]*)*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*([ \\t]*,([ \\t]*([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?(;([!#$%&'*+.^_`|~0-9A-Za-z-]+=([!#$%&'*+.^_`|~0-9A-Za-z-]+|\"([\\t \\x21\\x23-\\x5B\\x5D-\\x7E\\x80-\\xFF]|\\\\[\\t \\x21-\\x7E\\x80-\\xFF])*\"))?)*)?)*$" "$http_forwarded, $proxy_forwarded_elem";
        default "$proxy_forwarded_elem";
    }

    # --- 3. 包含业务子配置 ---
    # 具体的 server 块依然建议放在独立文件中
    include /etc/nginx/conf.d/*.conf;
}

conf.d目录示例配置如下:

server {
    listen      80;
    server_name yisroa.tongames.dpdns.org cangsroa.tongames.dpdns.org;

    location /.well-known/acme-challenge/ {
        root    /var/www/html;
        allow   all;
    }

    location / {
        return  301 https://$host$request_uri;
    }
}

server {
    listen                  127.0.0.1:8011 ssl proxy_protocol;

    ssl_reject_handshake    on;
    ssl_protocols           TLSv1.2 TLSv1.3;
}

server {
    listen                  127.0.0.1:8002 ssl proxy_protocol;
    http2                   on;

    set_real_ip_from        127.0.0.1;
    real_ip_header          proxy_protocol;

    ssl_certificate         /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/privkey.pem;

    ssl_protocols           TLSv1.2 TLSv1.3;
    ssl_ciphers             TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;

    ssl_session_timeout     1h;
    ssl_session_cache       shared:SSL:10m;

    ssl_stapling            off;
    ssl_stapling_verify     off;
    resolver                1.1.1.1 valid=60s;
    resolver_timeout        2s;

    location / {
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Content-Type-Options "nosniff";
        root       /var/www/html;
        index      index.html index.htm;
    }
}

server {
    listen                  127.0.0.1:8004 ssl proxy_protocol;
    http2                   on;

    set_real_ip_from        127.0.0.1;
    real_ip_header          proxy_protocol;

    ssl_certificate         /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/privkey.pem;

    ssl_protocols           TLSv1.2 TLSv1.3;
    ssl_ciphers             TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;

    ssl_session_timeout     1h;
    ssl_session_cache       shared:SSL:10m;

    ssl_stapling            off;
    ssl_stapling_verify     off;
    resolver                1.1.1.1 valid=60s;
    resolver_timeout        2s;

    location / {
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Content-Type-Options "nosniff";
        root       /var/www/html;
        index      index.html index.htm;
    }
}

server {
    listen                  127.0.0.1:8006 ssl proxy_protocol;
    http2                   on;

    set_real_ip_from        127.0.0.1;
    real_ip_header          proxy_protocol;

    ssl_certificate         /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/privkey.pem;

    ssl_protocols           TLSv1.2 TLSv1.3;
    ssl_ciphers             TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;

    ssl_session_timeout     1h;
    ssl_session_cache       shared:SSL:10m;

    ssl_stapling            off;
    ssl_stapling_verify     off;
    resolver                1.1.1.1 valid=60s;
    resolver_timeout        2s;

    location / {
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Content-Type-Options "nosniff";
        root       /var/www/html;
        index      index.html index.htm;
    }
}

server {
    listen                  127.0.0.1:8008 ssl proxy_protocol;
    http2                   on;

    set_real_ip_from        127.0.0.1;
    real_ip_header          proxy_protocol;

    ssl_certificate         /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/lingsroa.tongames.dpdns.org/privkey.pem;

    ssl_protocols           TLSv1.2 TLSv1.3;
    ssl_ciphers             TLS13_AES_128_GCM_SHA256:TLS13_AES_256_GCM_SHA384:TLS13_CHACHA20_POLY1305_SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers on;

    ssl_session_timeout     1h;
    ssl_session_cache       shared:SSL:10m;

    ssl_stapling            off;
    ssl_stapling_verify     off;
    resolver                1.1.1.1 valid=60s;
    resolver_timeout        2s;

    location / {
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-Content-Type-Options "nosniff";
        root       /var/www/html;
        index      index.html index.htm;
    }
}

修改配置之后,使用命令检查nginx配置,配置没提示报错的情况下,重载nginx配置。

nginx -t
nginx -s reload

4、使用v2node对接v2board,以Reality节点作为示例:

v2board 面板、Reality配置如下,与nginx中的stream sni配置相互对应

  1. 连接端口443,服务端口对应nginx stream sni分流端口,例如48001
  2. Reality配置对应nginx中的Server中的监听端口,例如 8002
  3. 传输协议TCP需添加如下配置:
{
  "acceptProxyProtocol": true,
  "header": {
    "type": "none"
  }
}
基于Debian 12 通过Nginx、Certbot部署节点

参考配置:

1、chika0801/Xray-examples: Xray 配置示例

2、integrated-examples

 

正文完
 0